rules:changes always evaluates as true in MR pipeline

Viewed 1272

I have a monorepo where each package should be built as a docker image.

I created a trigger job for each package that triggers a child pipeline.

In the MR, my changes rule is being ignored and all child pipelines are triggered.

.gitlab-ci.yml

---
workflow:
  rules:
     - if: $CI_MERGE_REQUEST_ID || $CI_COMMIT_BRANCH

trigger-package-a:
  stage: build
  trigger:
    include: .gitlab/ci/packages/package-gitlab-ci.yml
    strategy: depend
  rules:
   - changes:
      - "packages/package-a/**/*"
  variables:
    PACKAGE: package-a

trigger-package-b:
  stage: build
  trigger:
    include: .gitlab/ci/packages/package-gitlab-ci.yml
    strategy: depend
  rules:
    - changes:
      - "packages/package-b/**/*"
  variables:
    PACKAGE: package-b

done_job:
  stage: deploy
  script:
    - "echo DONE"
    - "cat config.json"
stages:
  - build
  - deploy

package-gitlab-ci.yml

workflow:
   rules:
     - if: $CI_MERGE_REQUEST_ID
     - changes:
         - "packages/${PACKAGE}/**/*"

stages:
  - bootstrap
  - validate

cache:
  key: "${PACKAGE}_${CI_COMMIT_REF_SLUG}"
  paths:
    - packages/${PACKAGE}/node_modules/
  policy: pull

install-package:
  stage: bootstrap
  script:
    - echo ${PACKAGE}}
    - echo '{"package":${PACKAGE}}' > config.json
    - "cd packages/${PACKAGE}/"
    - yarn install --frozen-lockfile
  artifacts:
    paths:
      - config.json
  cache:
    key: "${PACKAGE}_${CI_COMMIT_REF_SLUG}"
    paths:
     - packages/${PACKAGE}/node_modules/
    policy: pull-push

lint-package:
  script:
   - yarn lint
  stage: validate
  needs: [install-package]
  before_script:
   - "cd packages/${PACKAGE}/"

test-package:
  stage: validate
  needs: [lint-package]
  before_script:
     - "echo working on ${PACKAGE}"
     - "cd packages/${PACKAGE}/"
  rules:
     - if: $CI_MERGE_REQUEST_ID
  script:
     -  yarn test
1 Answers

It looks like your downstream pipeline is defining a workflow with 2 independent rules: if and changes. This may cause the jobs to be included if the first condition in the if is met, i.e. if it is a MR pipeline. Try removing the dash in front of changes, as in the example here, to treat this as a single rule:

workflow:
   rules:
     - if: $CI_MERGE_REQUEST_ID
       changes:
         - "packages/${PACKAGE}/**/*"

EDIT: This recent issue states rules:changes does not work as expected with trigger. So you may actually need to remove the changes from the upstream pipeline and solve this in the downstream pipeline.

Side note, not directly related to your issue: the GitLab Docs provide a workflow template to run branch or MR pipelines without creating duplicates. You can use this in your upstream pipeline if it helps:

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
      when: never
    - if: '$CI_COMMIT_BRANCH'
Related