[Solved] How to prevent a stage from running during schedule or web pipeline source

Hi there,

I am fairly new to Gitlab and gitlab-ci. I am trying to use it to run Ansible playbook on schedule or on demand.
This is in the context of a personal homelab. I am using a self-hosted free version of gitlab-ee setup in a lxc and have a gitlab-runner setup in docker.

I have created a .gitlab-ci.yml that:

  • Verify my playbook on each commit / pipeline run (verify stage)
  • Run the playbook in check mode when commit are not on main (test stage)
  • Run the playbook on scheduled or web pipeline run. (production stage)

However, I have a little issue where the test stage runs on scheduled or web pipeline run. I have been tinkering around but not managed to fix this. Not a biggy but I would prefer to not have it run, from an optimization point of view.

Could any ci guru have a look at my pipeline setup below and advise what I am doing wrong?

image: ubuntu:latest

variables:
    ANSIBLE_HOST_KEY_CHECKING: 'false'
    ANSIBLE_FORCE_COLOR: 'true'
    ANSIBLE_PYTHON_INTERPRETER: '/usr/bin/env python3'
    ANSIBLE_CONNECTION: ssh
    ANSIBLE_VAULT_PASS: $ANSIBLE_VAULT_PASS

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

before_script:
    - apt-get update -q -y
    - echo "===> Installing and configuring tzdata"
    - export DEBIAN_FRONTEND=noninteractive
    - ln -fs /usr/share/zoneinfo/Pacific/Auckland /etc/localtime
    - apt-get install -y tzdata
    - dpkg-reconfigure --frontend noninteractive tzdata
    - echo "===> Installing Ansible..."
    - apt-get install -y ansible ansible-lint git python3 sshpass curl
    - git submodule update --init
    - ansible --version
    - ansible-lint --version

stages:
    - Build
    - Test
    - Production

verify:
    stage: Build
    script:
      - curl --remote-name-all https://url-obfuscated/{hosts,id_rsa.crypt,install_ssh_key.yml}
      - ansible-lint -v *.yml
      - ansible-playbook --inventory hosts --syntax-check *.yml

execute_test_ping:
    stage: Test
    script: 
        - curl --remote-name-all https://url-obfuscated/{hosts,id_rsa.crypt,install_ssh_key.yml}
        - echo $ANSIBLE_VAULT_PASS > vault_pass.txt
        - ansible-playbook install_ssh_key.yml --vault-password-file vault_pass.txt
        - ansible-playbook ping.yml --inventory hosts --vault-password-file vault_pass.txt --check
    rules:
    - if: $CI_COMMIT_BRANCH != "$CI_DEFAULT_BRANCH"
    - if: $CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: never
    - if: $CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: never


execute_ping:
    stage: Production
    script: 
        - curl --remote-name-all https://url-obfuscated//{hosts,id_rsa.crypt,install_ssh_key.yml}
        - echo $ANSIBLE_VAULT_PASS > vault_pass.txt
        - ansible-playbook install_ssh_key.yml --vault-password-file vault_pass.txt
        - ansible-playbook ping.yml --inventory hosts --vault-password-file vault_pass.txt
    rules:
      - if: $CI_PIPELINE_SOURCE == "merge_request_event"
        when: never
      - if: $CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      - if: $CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Cheers,

Hi @latchee

Is the indentation in your file really like that? I think you want:

execute_test_ping:
    ....
    rules:
        - if: $CI_COMMIT_BRANCH != "$CI_DEFAULT_BRANCH"
        - if: $CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
          when: never
        - if: $CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
          when: never

In terms of your question, which branch is this job running on?

Hi @snim2 ,

Thank you, I have corrected the indentation.
Scheduled and web pipeline runs are started from the main branch, which is the $CI_DEFAULT_BRANCH.
I want to exclude the test stage to be run when pipeline is from the main branch. Thinking while I am responding to you. Maybe this rule would work:

rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: never

Though are pipeline web or schedule runs considered as a commit?

Hi there,

I have resolved my issue by having a good read at the documentation: `.gitlab-ci.yml` keyword reference | GitLab and more importantly about the rules:

Rules are evaluated when the pipeline is created, and evaluated in order until the first match. When a match is found, the job is either included or excluded from the pipeline, depending on the configuration.

To fix my issue, I had to moved the excluding rules to the top, so that they are evaluated first!:

    rules:
        - if: $CI_PIPELINE_SOURCE == "schedule"
          when: never
        - if: $CI_PIPELINE_SOURCE == "web"
          when: never
        - if: $CI_COMMIT_BRANCH != "$CI_DEFAULT_BRANCH"

Again thank you for your help. I will mark this thread as solved :slight_smile:

1 Like