read

It is common for a CI/CD pipeline to run a build on Github when a certain tag is pushed. For example, if I want to release v1.2 of an app, I can simply tag v1.2, push, and that will trigger my Github workflow. I will not be covering the basics.

Triggering a workflow from a tag push is easy, but if we want that to happen only on a specific protected branch eg. main, then it is not simple.

Github provides the scenarios for tags and branches.

However, that is tag OR branch. Either one will trigger.

For my scenrio, I want to trigger for a tag AND a branch. Github Action does not support that out-of-the-box.

Using GITHUB_REF ?

Some solutions on stackoverflow are wrong. If you read up on their doc, this is what it says about GITHUB_REF:

For workflows triggered by push, this is the branch or tag ref that was pushed.
The ref given is fully-formed, meaning that for branches the format is refs/heads/branch_name, … and for tags it is refs/tags/tag_name.

Which means if a workflow is triggered by tag, the ref is the tag name.

Many assumed GITHUB_REF is the branch name. It is not, and it is not easy to know the branch name.

How to know the branch(es) a tag is on?

It is possible to know with this git command:

git branch -r --contains tags/v1.2

It will list line-by-line of all the branches that a tag is on. A tag can be on multiple branches.

Though in a CI/CD scenario, the tag is likely pushed immediately, therefore it should be only on a single branch. Nonetheless, I will assume the tag could be in multiple branches.

Solution in a bash script

My final solution is to write in a bash script to check that the tag is on my protected branches (main & release branches). If it isn’t, then abort the build process.

onProtectedBranch=false
branches=$(git branch -r --contains tags/$GITHUB_REF_NAME)
for branch in $branches; do
  if [[ $branch == "origin/main" ]] || [[ $branch == "origin/release/"* ]]; then
    onProtectedBranch=true
  fi
done

if [ "$onProtectedBranch" == false ]; then
  echo "Tag is not on protected branch. Abort build."
  exit 1
fi

Note that GITHUB_REF_NAME will be the tag name eg. v1.2.

I am not an expert with bash, so it is not elegant, but it works.


Image

@samwize

¯\_(ツ)_/¯

Back to Home