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.