Gitlab CI how to ignore directory using rules syntax?

Viewed 11143

I was able to ignore directory, file changes using the following syntax.

build:
  script: npm run build
  except:
    changes:
      - "*.md"
      - "src/**/*.ts"

With this configuration build job is going to run except git changes include only *.md extension file or *.ts files in src directory. They're ignored.

But then they deprecated this only:changes, except:changes syntax and warned to use rules syntax instead. Unfortunately, I cannot seem to find how to ignore directory, file changes using this new syntax.

3 Answers

Based on documents of rules: changes, it seems when: never must be used with rules: changes syntax. Like the following:

build:
  script: npm run build
  rules:
    - changes:
      - "*.md"
      - "src/**/*.ts"
      when: never

    - when: always

If changed paths in the repository match above regular expressions then the job will not be added to any pipeline. In other cases the job always will be run by pipelines.

Surprisingly enough, it seems that is currently not possible - neither with except/only, nor with rules. This seems to be the "best" open issue for this requested feature: https://gitlab.com/gitlab-org/gitlab/-/issues/198688

I guess you could only reverse the logic and enable the build when a relevant change has been detected (sample adapted from https://docs.gitlab.com/ee/ci/yaml/#ruleschanges ):

job:
  rules:
    - changes:
        - relevant/path/file
      when: on_success
    - changes:
        - path/to/config/file
      when: never
    - when: on_success

Excuse the brief answer, but I've just had some success with using the unix glob 'not syntax', ie:

    - changes:
      - '[^d][^o][^c][^s]**/**/*'
      - '*' # above matcher does not match files in base folder

This matches changes to all files not in ./docs/ , and seems to correctly trigger the step for any changes outside that folder, but not for chages within that folder.

As a result, other matching rules within the "rules" property will still trigger the job. As a result, my whole rules statement needed to be set up to not trigger the job on any other rule:

  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH     # Run for merges
      when: never
      variables:
        BUILD_ENVIRONMENT: "production"
    - if: $CI_MERGE_REQUEST_ID                          # Run for merge requests
      when: never
      variables:
        BUILD_ENVIRONMENT: "staging"
    - changes:
      - '[^d][^o][^c][^s]**/**/*'
      - '*'

This isn't well tested yet though!

edit:fixed a little, with inspiration from Jan Spets: https://gitlab.com/gitlab-org/gitlab/-/issues/32673

and the gitLab source code for the Changes feature: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/build/rules/rule/clause/changes.rb

Related