4

I am trying to write a gitlab ci job rule that does not run when only CHANGELOG.md is committed into the default branch. However, if CHANGELOG.md is updated along with other files in the commit, then run the job. Is this possible? Thank you!

The background for this is that I am using the backmerge plugin for semantic-release. If the commit being backmerged is only updating the CHANGELOG.md, then don’t run a pipeline. But if there are other files being backmerged, then do run the pipeline.

For gitlab ci rules, I am struggling to come up with something that does the task.

jwdonahue
  • 6,199
  • 2
  • 21
  • 43
J W
  • 107
  • 1
  • 10
  • 1
    This has nothing to do with semantic-versioning and maybe something to do with semantic-release. – jwdonahue May 05 '23 at 16:32
  • Have you read [the docs](https://docs.gitlab.com/ee/ci/yaml/index.html#ruleschanges)? A quick scan doesn't indicate a pattern for ignoring changes, so you might have to organize your project tree to allow for triggering on intended content in specified folders. I would try listing the file in rules:changes block with a ! in front of it. Could be a poorly or undocumented feature. – jwdonahue May 05 '23 at 16:37
  • You could also try listing all the *.ext you do want to trigger on and leave out the md file. – jwdonahue May 05 '23 at 16:40

2 Answers2

1

You might need to use a before_script in order to check if your condition is met:

stages:
  - build

run_pipeline:
  stage: build
  script:
    - echo "Running pipeline"
  rules:
    - exists:
        - "*"
      when: always
  before_script:
    - |
      CHANGELOG_UPDATED=$(git diff --name-only HEAD~1 | grep -E '^CHANGELOG.md$' | wc -l)
      OTHER_FILES_CHANGED=$(git diff --name-only HEAD~1 | grep -v -E '^CHANGELOG.md$' | wc -l)
      if [ "$CHANGELOG_UPDATED" -eq 1 ] && [ "$OTHER_FILES_CHANGED" -eq 0 ]; then
        echo "Only CHANGELOG.md was updated, skipping the job"
        exit 0
      else
        echo "Other files were updated, running the job"
      fi

Here, we use the rules keyword with exists and when: always to ensure that the job runs when any file exists in the repository.

The before_script section checks if the CHANGELOG.md file was updated and if any other files have been changed in the last commit.

If only the CHANGELOG.md file is updated, the script will exit with a status code of 0, causing the job to be skipped.
If other files have been changed, the job will run.

(rules:changes is fairly recent, 15.2, and I did not manage to make it work for excluding CHANGELOG.md alone)

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
1

It's a bit odd, but you can make a rule like this:

rules:
  changes:
  - '**/{[^C]*,C,C[^H]*,CH,CH[^A]*,CHA,CHA[^N]*,CHAN,CHAN[^G]*,CHANG,CHANG[^E]*,CHANGE,CHANGE[^L]*,CHANGEL,CHANGEL[^O]*,CHANGELO,CHANGELO[^G]*,CHANGELOG,CHANGELOG[^.]*,CHANGELOG.,CHANGELOG.[^m]*,CHANGELOG.m,CHANGELOG.m[^d]*,CHANGELOG.md?*}'

And it would have the intended effect.

This is basically the workaround for the fact that ruby's fnmatch (used by rules:changes:) does not support the ! glob metacharacter. Otherwise you could just use the glob pattern !CHANGELOG.md.

Reference: https://stackoverflow.com/a/69906355/5747944

sytech
  • 29,298
  • 3
  • 45
  • 86