Make it clear what CI jobs are needed by the other CI jobs from rules
Goal
Instead of writing rules like this via changes
:
.rails:rules:setup-test-env:
rules:
- <<: *if-default-refs
changes: *setup-test-env-patterns
- <<: *if-merge-request-labels-run-all-rspec
Write rules like this via other rules
:
.rails:rules:setup-test-env:
rules:
- !reference [".rails:rules:ee-and-foss-default-rules", rules]
- !reference [".rails:rules:system-default-rules", rules]
- !reference [".rails:rules:previous-failed-tests-default-rules", rules]
# - So on!
Why?
More verbose, and can be tedious, but it's more clear and less brittle. It's too easy to break the CI configurations when we're fully relying on changes
to be the union of other changes
. See the last one how we broke CI again: #414760 (closed) (and there were a ton of issues like this)
There's a catch though. We need to be extremely careful with when: never
in those rules we're referencing from. We want the rules to be a union of other rules, not a sequential flow to run through.
Background
It's been a pain to review and verify if we're breaking the CI configuration for some of the workflows, because it's never clear what jobs are needed by other jobs when we're only looking at the rules.
A lot of time, what we really want to say is, this job is needed by X, Y, and Z, so the rules for this job should be the union of the rules of X, Y, Z.
We sort of achieved this by using the patterns, like:
.rails:rules:setup-test-env:
rules:
- <<: *if-default-refs
changes: *setup-test-env-patterns
- <<: *if-merge-request-labels-run-all-rspec
And we can look into what are inside setup-test-env-patterns
:
# .code-backstage-qa-patterns + .workhorse-patterns
# NOTE: `setup-test-env-patterns` intentionally does not include docs files, because this would
# result in docs-only pipelines having failures of jobs which use `setup-test-env-patterns`
# in their rules and thus require `setup-test-env`, which isn't present in docs-only pipelines.
.setup-test-env-patterns: &setup-test-env-patterns
# - Blah blah blah
# CI changes
# - Blah blah blah
# Backstage changes
# - Blah blah blah
# QA changes
# - Blah blah blah
# Mapped patterns (see tests.yml)
# - Blah blah blah
# Workhorse changes
# - Blah blah blah
# CI Templates changes
# - Blah blah blah
# GLFM specification changes
# - Blah blah blah
And let's just look at one example, the job templates-shellcheck
needs setup-test-env
and uses rules .ci-templates:rules:shellcheck
. This is likely why we can see that we have # CI Templates changes
in setup-test-env-patterns
because we do need to run setup-test-env
when we want to run templates-shellcheck
, so whatever sits inside .ci-templates:rules:shellcheck
we need to make sure it's included in .rails:rules:setup-test-env
.
However, using changes "patterns" to union changes is very difficult to follow and verify, mostly because there's no way we can merge arrays in YAML, or GitLab CI. We have to repeat over and over and over in the changes and we see the comments we're inserting to make that easier, but it's never easy.
We do try to flatten arrays in some places, so that we can also merge arrays. Like in before_script
and script
as far as I know, we can merge and flatten arrays, but probably not for changes
. We can request this one by one, like #371832, but we can also somehow enable this globally, like: #389322
If we have that, we might not need to use rules
. We use rules
because, well, I think rules
do support flatten arrays!