| :lock: **template controlled** | Options you (as the template developer) want to controlbecause they are part of the proper implementation of the template | • Must be **enforced** and **hard-coded** in your job implementation. |
| :unlock: **user controlled** | Options that the user will be allowed to customize(project specific preferences) | • **Documented** and **customizable** by the user.<br>• You should decide [what are the **good default**?](#sensible-defaults)(_90% of the time, the tool defaults are fine_). |
| :lock: **template controlled** | Options you (as the template developer) want to control<br>because they are part of the proper implementation of the template | • Must be **enforced** and **hard-coded** in your job implementation. |
| :unlock: **user controlled** | Options that the user will be allowed to customize<br>(project specific preferences) | • **Documented** and **customizable** by the user.<br>• You should decide [what are the **good default**?](#sensible-defaults)(_90% of the time, the tool defaults are fine_). |
Example with a unit-testing tool:
@@ -205,3 +205,78 @@ Example with a unit-testing tool:
- the tests to launch, as a glob pattern (with TBC default `**/*.test.xyz`)
In order to allow users to [multi-instantiate them](../usage.md#multiple-template-instantiation-advanced-usage)(using the
`parallel:matrix` keyword), our templates have to comply to some constraints explained in the following chapters.
### Ensure output artifacts segregation
Every job producing output artifacts (ex: build artifacts, report files...) must make sure there will be
no name/path collision between those output artifacts when the template is multi-instantiated.
#### How to segregate output files?
For example, a unit testing job generating an output JUnit report `$CI_PROJECT_DIR/reports/xyz.xunit.xml` will cause collisions if the template is multi-instantiated, because the report path is absolute.
This problem can be fixed by introducing some variable part (namespacing) that will be used when the template is multi-instantiated.
For example `$CI_PROJECT_DIR/$XYZ_PROJECT_DIR/reports/xyz.xunit.xml`, as `$XYZ_PROJECT_DIR` will have different values in each matrix instance.
#### How to segregate output environment variables?
The same occurs with output environment variables, propagated via [dotenv reports](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportsdotenv).
If your job computes and propagates a variable `XYZ_COMPUTED_VARIABLE`, then you have to pay attention to two things::
1. you have to segregate the dotenv report file itself (see [previous chapter](#how-to-segregate-output-files)),
2. but you also have to segregate variable names too (two instances of your template will produce the same `XYZ_COMPUTED_VARIABLE` variable)...
This problem can be fixed by introducing some (optional) namespacing part that will be inserted into output variable names
when the template is multi-instantiated.
For example, if `$JOB_MATRIX_NAMESPACE` is defined (optional), produce instead an output variable `XYZ_${JOB_MATRIX_NAMESPACE}_COMPUTED_VARIABLE`. Then those variables can be used safely when multi-instanting your template.
### Forbid `parallel:matrix` keyword
Basically because if a user uses the `parallel:matrix` keyword, it will break your template implementation.
Instead, prefer defining a job prototype and explicit inheritance as many times as required.
Example:
```yaml
a-job-i-want-multiple-times:
script:
-echo "this is $MYVAR"
parallel:
matrix:
-MYVAR:case1
-MYVAR:case2
-MYVAR:case3
```
Can be easily replaced with:
```yaml
.job-prototype:
script:
-echo "this is $MYVAR"
job-case1:
extends:.job-prototype
variables:
MYVAR:case1
job-case2:
extends:.job-prototype
variables:
MYVAR:case2
job-case3:
extends:.job-prototype
variables:
MYVAR:case3
```
This is obviously longer, but preserves the ability for the user to [multi-instantiate](../usage.md#multiple-template-instantiation-advanced-usage) your template.