Gitlab CI - run a task with only TAG & specific BRANCH - gitlab

how can I start a job with gitlab-ci only when I create a new tag with a specific branch?
I try everything but it still doesn't work.
stages:
- shov server
test:
stage: shov server
rules:
- if: '$CI_COMMIT_TAG && $CI_COMMIT_BRANCH == "CI_merge"'
when: always
tags:
- runner
script:
- docker-compose -f docker-compose.yml down
- docker-compose -f docker-compose.yml build
- docker-compose -f docker-compose.yml up -d

AFAIK this is not possible. When the Pipeline runs for a tag, there is no variable defined that indicates the branch. You see this for yourself by looking through all available variables with export. Gitlab Documentation
You could perhaps try to find the branch, which the commit is on. Something like git branch -a --contains $CI_COMMIT_SHA or something similar. However you probably can't do that in the rules, and have to do it in the script, or in the before_script with custom logic to stop the rest of the script from running.
Hope this helps.

Related

Pipeline does not run when using CI_COMMIT_MESSAGE

I want to run a pipeline that builds a docker image from an app and deploys it to Gitlab Registry and Docker Hub.
I'd like this pipeline to run only when the main branch gets a commit and when that commit has a message that is a "version". Examples of versions:
1.0.0
3.4.0
10.1.6
I have made the following gitlab-ci.yml, however, my pipeline never triggers. What am I doing wrong? I've already checked the regex and it's ok, so I'm guessing I'm doing something wrong with the Gitlab config?
image: docker:stable
variables:
PROJECT_NAME: "project"
BRANCH_NAME: "main"
IMAGE_NAME: "$PROJECT_NAME:$CI_COMMIT_MESSAGE"
LATEST_IMAGE_NAME: "$PROJECT_NAME:latest"
services:
- docker:19.03.12-dind
build_image:
script:
# Push to Gitlab registry
- docker build -t $CI_REGISTRY/username/$PROJECT_NAME/$IMAGE_NAME .
- docker build -t $CI_REGISTRY/username/$PROJECT_NAME/$LATEST_IMAGE_NAME .
- docker login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
- docker push $CI_REGISTRY/username/$PROJECT_NAME/$IMAGE_NAME
- docker push $CI_REGISTRY/username/$PROJECT_NAME/$LATEST_IMAGE_NAME
# Push to Docker hub
- docker build -t username/$IMAGE_NAME .
- docker build -t username/$LATEST_IMAGE_NAME .
- docker login -u username-p $DOCKER_HUB_TOKEN
- docker push username/$IMAGE_NAME
- docker push username/$LATEST_IMAGE_NAME
rules:
- if: $CI_COMMIT_MESSAGE =~ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/
- if: $CI_PIPELINE_SOURCE == "$BRANCH_NAME"
The problem you're having is likely due to the $ marker. Often commit messages get formatted with additional newlines, which would make the pattern not match.
Alternatively, your pattern may work if using CI_COMMIT_TITLE which only includes the first line of the commit message.
I propose to you an alternative, that is tags.
A tag is a label that you attach on git commits. Examples of tags are: 1.0.1, 1.1.2, latest.
In order to tag a commit with a version, just issue:
git tag <version> (the newest commit is subtended here)
In order to trigger your pipeline for any tag, just use this:
rules:
- if: $CI_COMMIT_TAG
In this solution, we have decoupled the version issue from the message concern.

Gitlab CI doesnt trigger pipelines on commit to the specified branch

I am trying to trigger a pipeline on any type of change/commit (push/merge/webIDE etc) to a specific branch called test branch. Not sure why it doesn't trigger at all even after I make a change to a file in that specific branch.
default:
tags:
- specs
stages:
- validate
Trigger job:
stage: validate
script:
- curl -X POST -F token=$ENTDV_PL_TRIGGER_TOKEN -F "ref=master" https://gitlab.com/api/v4/projects/1252972/trigger/pipeline
variables:
CI_DEBUG_TRACE: "true"
rules:
- if: '$CI_COMMIT_BRANCH == "testbranch"'
If you want Trigger job to only be run when changes are made on testbranch, you can modify your Trigger job to the following:
Trigger job:
stage: validate
script:
- curl -X POST -F token=$ENTDV_PL_TRIGGER_TOKEN -F "ref=master" https://gitlab.com/api/v4/projects/1252972/trigger/pipeline
variables:
CI_DEBUG_TRACE: "true"
only:
- testbranch
The Gitlab CI documentation is actually quite good. Here is a link to how "only" works: https://docs.gitlab.com/ee/ci/yaml/index.html#only--except
From the docs: "Use the only:refs and except:refs keywords to control when to add jobs to a pipeline based on branch names or pipeline types."
You can do some other neat things like specifying only merge_requests or using regex for triggering jobs and what not.

Gitlab-CI run Stage conditionally

As you see below I have two stages.
1- Build
2- Deploy
And I have 3 kind of branches
1- master
2- test
3- Other branches which created by developers. (Development)
I want to run build for all branches but I have a condition for deploy
1- If branch is test run deploy.
2- If branch is other branches don't run deploy.
3- if branch is master run deploy only manual.
But this three condition doesn't works properly with my gitlab-ci.yml
stages:
- build
- deploy
default:
image: node:latest
before_script:
- |
if [ "$CI_BUILD_REF_NAME" == "master" ]; then
ENV="prod"
elif [ "$CI_BUILD_REF_NAME" == "test" ]; then
ENV="test"
else
ENV="dev"
fi
- npm install
build:
stage: build
script:
- cp ./src/env-${ENV}.js ./src/env.js
- npm run build-compressed
deploy:
stage: deploy
rules: //this section doesn't work properly
- if: '$ENV == "test"'
when: always
- if: '$ENV == "prod"'
when: manual
- when: never
script:
- cp ./src/env-${ENV}.js ./src/env.js
- npm run build-compressed
- npm run publish:${ENV}
I recommend doing such a differentiation via Rules. As you can easily override variables with rules, see GitLab CI Doc.
Below you can find a short example
rules
- if: $CI_COMMIT_BRANCH =~ /test/
variables: # Override ENV defined
ENV: "test" # at the job level.
- if: $CI_COMMIT_BRANCH =~ /master/
variables: # Override ENV defined
ENV: "prod" # at the job level.
- variables: # not 100% sure about this one, as when can stand without a if clause, i assume variables can too :D
ENV: "dev"
Furthermore i would also do the rule check based on the branch within the deploy stage. - as it is easier to verify the branch, than to ensure at a later stage, that the Env variable is still set properly.
Also important to notice is the order of evaluation. Just because there is a before_script in the default section, does not mean it is evaluated just once for the whole. The before_script is evaluated once per Job.
Additionally the rules are evaluated, before the JOB runs, as it needs to determine if the job should be executed or not. This means you are not able to reference the variable from the before_script.
If you want to pass on the variable from the first job to the second job, you need to persist it in a dotenv-artifact - this way, the variables are available before the second stage start. (I am still not sure if you can use them for evaluation in rules, that is something you need to check)
I hope my additional clarifications, based on your comments, help you to find the best way.

How to run a pipeline only on changes in a specific branch?

I am looking through the documentation back and forth and cannot find how to configure my .gitlab-ci.yml so that the content is executed only on a change in the branch mqtt_based and not in the default master.
I was hoping that adding an only entry for each section would be enough (I was hoping for a global setting), but this did not help (the pipeline was not started when the mqtt_based branch was changed)
variables:
BRANCH: "mqtt_based"
stages:
- build
- deploy
job:build-back:
stage: build
script:
- cd back
- docker build --build-arg COMMIT=${CI_COMMIT_SHORT_SHA} --build-arg DATE=$(date --iso-8601=seconds) -t registry.XXX/homemonitor-back:latest -t registry.XXX/homemonitor-back:${CI_COMMIT_SHORT_SHA} -f Dockerfile .
only:
- $BRANCH
(...)
You need to use 'refs' after 'only'. Something like this
only:
refs:
- mqtt_based
Documentation: https://docs.gitlab.com/ce/ci/yaml/#onlyexcept-advanced

How to run a gitlab-ci.yml job only on a tagged branch?

How do I run a .gitlab-ci.yml job only on a tagged Master branch?
job:
script:
- echo "Do something"
only:
- master
- tags
The above code will run if either condition exists: a Master branch or a tagged commit.
My goal is to have this run for a production deploy, but it would require that it be on the Master branch and that it be tagged (with a version). Otherwise, I'll have another job that will push to staging if its missing a tag.
This behavior will be introduced in version 12.
Open issue was recently update:
Jason Lenny #jlenny changed title from {-Update .gitlab-ci.yml to
support conjunction logic for build conditions-} to Conjunction logic
for build conditions MVC · 2 days ago
Jason Lenny #jlenny changed milestone to 12.0 · 2 days ago
(fingers crossed)
A solution is to use the except keyword to exclude all the branches, in conjunction with only to run on tags, in this way you run your pipeline only on tag in master branch:
only:
- tags
except:
- branches
I'm using version 11.3.4
Thanks to others like Matt Alioto who posted about the open issue (which is labeled Product Vision 2019 so hopefully they knock it out this year).
Specific to Carlson Cole's question, this would work:
job_for_master_no_tags:
stage: deploy
script:
- echo "Release to Staging"
only:
- master
job_for_master_tags_only:
stage: deploy
script:
- echo "Release to Production"
only:
- tags
except:
- /^(?!master).+#/ # Ruby RegEx for anything not starting with 'master'
To see how this RegEx works check out https://rubular.com/r/1en2eblDzRP5Ha
I tested this on GitLab version 11.7.0 and it works
Note: If you try to use - /^(?!master).+/ (without the #) it doesn't work - learned that the hard way 😕
I made it work with this working code snippet, all others were not working for me
only:
- tags # please mention the 's' compared to Sergio Tomasello's solution
except:
- branches
I use 11.4.3
I had the same problem. I wanted to trigger a deploy to our staging-environment on a push or merge, and only when applying a tag deploy it our production-environment.
We need 2 variables for this: $CI_COMMIT_BRANCH and $CI_COMMIT_TAG. With these variables we could deduct if the pipeline was triggered by a commit or a tag. Unfortunately the first variable is only set when committing on a branch, while the second variable only is set on applying a Tag. So this was no solution...
So I went for the next-best setup by only do a production-release when a tag is set by specified conventions and by a manual trigger.
This is my .gitlab-ci.yml file:
stages:
- deploy:staging
- deploy:prod
deploy-to-staging:
stage: deploy:staging
rules:
- if: $CI_COMMIT_BRANCH == 'master'
script:
- echo "Deploying to Staging..."
deploy-to-production:
stage: deploy:prod
rules:
- if: $CI_COMMIT_TAG =~ /^v(?:\d+.){2}(?:\d+)$/
when: manual
script:
- echo "Deploying to Production..."
If you really want to automate this, you have to do a little scripting to find out if the applied tag actually belongs to a commit that is on the master-branch. Check this comment on the GitLab issuetracker for more information: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/31305#note_28580169
This behavior is not yet supported by gitlab-ci, although there is an open issue to add it.
In the meantime I've also heard anecdotal reports that
only:
- master
only:
- tags
will get the job done (as well as anecdotal reports that it won't).
Years later, still trying to launch a job on tags on master branch...
The issue at Gitlab has been closed : https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27818
It's not possible to spot a tag on master branch as Git does not work this way. Branches and tags are separate references, each pointing to a commit. So, a tag has no relation with a branch.
My solution is to check the tag name to detect that it represents a PRODUCTION release :
deploy-prod:
stage: deploy-manual
only:
variables:
- $CI_COMMIT_TAG =~ /^v\d+.\d+.\d+-?.*$/
when: manual
The regexp matches semver tag names like :
v1.2.0
v2.0.0-beta.1
...
There is no proper build in solution in gitlab so far for this problem. To keep track of the development of a proper solution and to keep a working workaround updated I created: Gitlab CI: Run Pipeline job only for tagged commits that exist on protected branches
I have faced the same issue, this is how I tried to solve it
my_job:
stage: build
services:
- name: docker:dind
image: docker:latest
script:
- ...
rules:
- if: $CI_COMMIT_BRANCH == 'master' && $CI_COMMIT_TAG == null
cache: {}
this job runs only when there is a commit on the master branch (excluding any other commit on personal/feature branch). In the very same way I trigger builds on tags:
script:
- ...
rules:
- if: $CI_COMMIT_BRANCH == 'master' && $CI_COMMIT_TAG != null
Docs actually say that only and except are not being developed and that users should use rules instead.
Here is an example which will only run on a tag.
deploy-to-prod:
stage: deploy
rules:
- if: $CI_COMMIT_TAG
environment:
name: production
variables:
API_ENVIRONMENT: prod
when: manual
I have found workaround for this.
.gitlab-ci.yml
build-image-prod:
stage: image
only:
refs:
- tags
variables:
- $CI_COMMIT_TAG =~ /^v.*$/
script:
- ./scripts/not-on-main $CI_COMMIT_TAG && exit 0
- echo "Image building..."
scripts/not-on-main:
#!/bin/sh
if [ -z "$1" ]; then
echo "Missing argument with commit ref."
exit 0
fi
git fetch origin main
if git branch -r --contains "$1" | grep -q main; then
echo "Ref $1 is on main branch."
exit 1
else
echo "Ref $1 is not on main branch - exiting."
exit 0
fi
The job runs for each tag in repository if name of tag starts with "v". The helper script fetches main and checks if tag is on it. If the tag is not on main branch then the job exits without building.

Resources