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
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.
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 (
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
GITHUB_REF_NAME will be the tag name eg.
I am not an expert with bash, so it is not elegant, but it works.