CI "rules:changes" does not work as expected for Merge Request Pipelines
I have the following simplified GitLab CI yaml:
image: node:14.16.1-alpine
include:
- template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
.modules_setup:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
policy: pull
before_script:
- [...REMOVED...]
stages:
- prepare
- lint
build_deps:
stage: prepare
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
before_script:
- npm config set unsafe-perm true
- apk update && apk upgrade
- apk add --no-cache --virtual .build-deps alpine-sdk python libc6-compat gcompat
script:
- npm install -g node-gyp node-pre-gyp
- npm ci
rules:
- changes:
- package-lock.json
when: always
- when: never
lint_code:
stage: lint
extends: .modules_setup
script:
- npm run lint:code
The goal is that I have a build step for the dependencies which puts the resulting node_modules folder in the cache for later steps to use. This only needs to happen when new dependencies are added. In the context of a Merge Request I would expect the build_deps job to be added to the pipeline only if it's either a new merge request (so irrespective of changes to package-lock.json on the first run in a MR) or if a later commit in this MR changes the package-lock.json. For commits on this MR branch that are neither the first nor edit package-lock.json I would expect this job not to be added.
So it looks like this:
- Create MR: Runs
build_deps - Add new commit that does not change
package-lock.json: Does NOT runbuild_deps - Add new commit that DOES change
package-lock.json: DOES runbuild_deps - Add new commit that does not change
package-lock.json: Does NOT runbuild_deps
This does not happen though. Every new commit to the MR branch will lead to the build_deps job to be added to the pipeline.
I do have a recovery script in the .modules_setup to regenerate the node_modules in the jobs if the cache is ever unavailable (as it's only best effort) but that's not the focus of this issue.
Previously I had a similar setup just without the include directive and instead of the rules on the build_deps job I had:
only:
changes:
- package-lock.json
Configured like this, I get exactly the behaviour I outlined and want. But since enabling the Merge Request pipelines with the included template and switching over to rules:changes, it ALWAYS runs the build_deps job in a detached pipeline.
Sadly the meaning and implications of a detached pipeline is not clearly documented it seems.
Is there any way to get to my desired behaviour using Merge Request pipelines or will I have to revert?