Skip to content

Conjunction logic for build conditions

Description

There are two specific conditions that I want to be true for when our libraries are deployed for a specific commit:

  1. The commit must be to the master branch.
  2. The commit is a tag.

When I read through the documentation, I thought I might be able to define this in our .gitlab-ci.yml file like so:

job:
  stage: publish
  script:
    - ./do-publish.sh  
  only:
    - tags
    - master

However, these conditions under the only clause are not conjunctive, but rather disjunctive. In other words, the build will be triggered for tag commits or commits to master - not when both conditions are true. This is undesirable and, frankly, surprising. It makes sense if your conditions are a collection of branch names as a commit cannot be in two branches at the same time, but not for any situation when you combine different types of constraints.

From our perspective, if someone happens to make a tag in a feature branch for others to reference, that should not cause a deployment. Additionally, not all commits to master should result in a deployment. We may be merging several features together before we consider it a completed version we wish to deploy.

Proposal

I have two ideas here, the first being a nonbreaking change and less discoverable, the second being a breaking change but, in my humble opinion, easier to understand:

Suggestion 1 - Nonbreaking, but less discoverable

Since multiple lines under the only (and potentially except?) clauses are already locked into disjunctive OR logic, you could reuse the well known && operator from a variety of scripting languages to combine clauses together. The end result would look something like this:

job:
  stage: publish
  script:
    - ./do-publish.sh  
  only:
    - tags && master
Suggestion 2 - Breaking, but more explicit and discoverable
  1. Make only and except more explicit, such that each type of constraint is conjunctive, but the conditions for each type is disjunctive. For example, something like this for my situation:
job:
  stage: publish
  script:
    - ./do-publish.sh  
  only:
    tags: true
    branches: 
      - master

But if you wanted the old functionality, you could do the following:

job:
  stage: publish
  script:
    - ./do-publish.sh  
  only:
    tags: false
    branches: 
      - release
      - master
Suggestion 3 - Easier to understand and reason about

This version is inspired by Travis conditions

only: source:triggers AND ref:master AND var($TRIGGER_ACTION == "index") AND var($APP_ID) AND var($API_KEY)

or

only: ref:master AND NOT $SOME_VAR == 'some value'

as discussed in #57231 (moved)

Links / references

This has been discussed in length over on GitHub as the community has scrounged for solutions and workarounds, but apparently that was not the place to discuss it. At a request of @zj on this GitHub issue, it sounds like this is the place to open this issue.

Edited by Brendan O'Leary