How to run a job only when on tags, AND if specific folder has changed?

Hello,

I have a gitlab CI/CD pipeline which has a couple manual jobs that I want to run only on specific conditions

The jobs should only appear in the pipeline if the pipeline running is a tag, AND if there have been changes to a specific folder that we’ll call tests.

I have a .gitlab-ci.yml that looks like this:

stages:
  - build
  - test
  - deploy

build:
  stage: build
  image and stuff...

test:
  stage: test
  when: manual
  allow_failure: false
  needs:
    - build
  only:
    changes:
      - tests/*
    refs:
      - tags

deploy:
  stage: deploy
  needs:
    - test
  only:
    changes:
      - tests/*
    refs:
      - tags

I’m omitting other jobs here that are not relevant to my question.

With this configuration, if I have a tag but no changes in the tests folder, the test job still appears, and because I have it set as not allowed to fail, the pipeline gets stuck. So I have to comment out the allow_failure: false line if I want it to work. It seems to me that only makes the job appear if the pipeline is a tag OR if there’s been changes to the tests folder, and I’d like it to make the job appear if the pipeline is a tag AND if there’s been changes to the tests folder.

I see in the documentation that only is not developed anymore, and that it’s encouraged to use rules instead, but I’ve searched in the documentation and couldn’t find a way to make a job only appear in the pipeline if it’s a tag. The only things tag related I could find was to create a tag, but I create my tags manually.

How could I get the behaviour I want, with only or with rules ? Is it even possible with current gitlab or will I have to keep my manual jobs as allowed to fail, and skip them ?

Thanks

Hi @araly welcome to the forum. I think you want something like this:

workflow:
  rules:
    - if: $CI_MERGE_REQUEST_ID
      when: never
    - when: always

stages:
  - build
  - test
  - deploy

build:
  stage: build
  image and stuff...

test:
  stage: test
  rules:
    - if: '$CI_COMMIT_TAG'
      changes:
        - tests/*
      when: manual
    - when: never
  script:
    - echo "test"

deploy:
  stage: deploy
  needs:
    - test
  rules:
    - if: '$CI_COMMIT_TAG'
      changes:
        - tests/*
      when: on_success
    - when: never
  script:
    - echo "deploy"

That workflow key at the top prevents you having two pipelines for every merge request.

I’m not sure whether you wanted the test job to run manually when tests/* has changed and a tag has been pushed. If you want that to happen automatically, but the job to run manually otherwise, you want:

test:
  stage: test
  rules:
    - if: '$CI_COMMIT_TAG'
      changes:
        - tests/*
      when: on_success
    - when: manual
  script:
    - echo "test"

BTW when you’re using rules it’s always useful to have the predefined variables page open.

HTH,

Sarah

3 Likes

@snim2

Sorry to bump an old thread. But this is the only one I could find.

Im also trying to do this, I only want my stage to run, if its a tag and changes have been made.

but the above doesnt work?

If i tag it, it still shows all my jobs, even though changes have not been made.

helm-apply:
  extends: [.kube-context]
  stage: helm-deploy
  image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v1.3.2"
  environment:
    name: staging
  script:
    - gl-ensure-namespace $HELM_CHART_NAMESPACE
    - gl-helmfile --file $CI_PROJECT_DIR/helmfile.yaml apply --suppress-secrets
  rules:
    - if: '$CI_COMMIT_TAG'
      changes:
        - helm-chart/**/*
        - values.yaml
        - helmfile.yaml
      when: on_success
    - when: never

i havnt made any changes to
- helm-chart/**/*
- values.yaml
- helmfile.yaml

in the commit the tag is based off, yet it still trys to run this job

any ideas?

Hi @thegreatone1111

So, the docs say that rules:changes work exactly like only/except, which only work in some circumstances. These docs say:

Use changes in pipelines with the following refs:

This note in an old issue explains that because tag jobs don’t have any context around which commits should be considered as related to the tag, GitLab assumes that any changes clause evaluates to true.

Ah, kinda makes sense.

But this means what im trying to do is not possible then.

Well, it’s not possible in the way you’re trying to do it :wink:

Another option would be to have a job that runs on tag pipelines only, and runs a script to iterate through the commits between “this” tag and the last one, and looks for changes in the relevant directories.

It’s clearly a lot more work to do this yourself, but it does give you some flexibility over your workflow.

isn’t a tag just a fancy branch ? couldn’t you check the changes for the branch that has the same name as the tag ?

A tag is just a reference to a specific commit, there’s no need for there to be a branch that has the same name as a branch. If that’s your workflow, then it might make writing a script to deal with this a little easier.

1 Like