how to handle merge conflicts in gitlab-ci - gitlab

I have following problem with gitlab-ci: my jobs execute perfectly fine everything works as expected except when i have merge conflicts. Is there any effective way to handle merge conflicts in gitlab-ci and not trigger pipelines until the conflict get solved ???
here is a sample pipeline which could trigger merge conflict:
image: alpine:latest
workflow:
rules:
- if: $CI_COMMIT_BRANCH =~ /^(dev)$/ || $CI_MERGE_REQUEST_IID || $CI_PIPELINE_SOURCE =~ /^(web)/
stages:
- build
build software:
stage: build
script:
- printenv
- echo "Building code for $CI_COMMIT_BRANCH"
I appreciate any suggestion. Thank you :)

Related

Run all jobs on a gitlab ci MR pipeline, even if some don't have a merge_request_event rule, but do not run both MR and branch pipelines

In case the terminology is not standard, here is how I am using the below terms:
branch pipeline: A pipeline that is run when pushing to a branch.
MR pipeline: A pipeline that is run on a merge request, or pushes to a merge request branch.
I want to write a pipeline with two jobs, job_A and job_B. job_A should run on all pipelines. job_B should run only on merge request pipelines. One solution is to combine the workaround proposed in issue 194129, adding a workflow rule of - if: $CI with a merge_request_event rule, i.e.:
image: alpine
workflow:
rules:
- if: $CI
stages:
- stage_A
- stage_B
job_A:
stage: stage_A
script:
- echo "Hello from Job A"
job_B:
stage: stage_B
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
script:
- echo "Hello from Job B"
Now my pipeline runs in full on the MR -- which is what I wanted. However, two pipelines are being run now, the branch pipeline and the MR pipeline.
I want both job_A and job_B to run on MR pipelines even though job_A doesn't have the merge_request_event rule. But, I only want one pipeline to run when an MR is open -- the MR pipeline. How can I achieve this?
The correct answer is found in the gitlab docs.
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
Try using only:variables. I had the same issue when mixing only/except with rules in one pipeline.
job_B:
stage: stage_B
only:
variables:
- $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- echo "Hello from Job B"

How to run Gitlab-CI pipelines only branch and tag?

I just want to run pipelines when tagged from main branch. I tried using workflow but it doesn't work.
This is my .gitlab-ci.yml file.
workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
variables:
CHART_GIT_URL: $CHART_DEV_URL
CHART_VALUES_FILE: "values-dev.yaml"
DOCKER_IMAGE_TAG: "dev-$CI_COMMIT_SHORT_SHA"
- if: $CI_COMMIT_TAG && $CI_COMMIT_BRANCH == "main"
variables:
CHART_GIT_URL: $CHART_PROD_URL
CHART_VALUES_FILE: "values-prod.yaml"
DOCKER_IMAGE_TAG: "v$CI_COMMIT_TAG"
stages:
- build and push
- deploy
package Docker image:
stage: build and push
before_script:
- docker login $DOCKER_REGISTRY -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWD
script:
- docker build -t $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG .
- docker push $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
- if: $CI_COMMIT_TAG && $CI_COMMIT_BRANCH == "main"
Thanks for the help!
tagged from main branch
Unfortunately, this is not possible. Git tags are only associated with commits, not branches. Therefore, you cannot create a condition for a tag to be created "from" a branch because that's not how tags work. Also consider that a tagged ref can exist on many branches, or even no branch at all.
This is also the reason why the predefined variables CI_COMMIT_TAG and CI_COMMIT_BRANCH will never be present together. If a pipeline is associated with a tag, it cannot be associated with a branch and vice versa.
The best you might be able to do is to run only on tags, then check if the tagged ref exists in main in the job itself. Unfortunately this is not possible to do with rules:.

Gitlab CI runs test twice when pushing to master

I have a Gitlab CI config that kinda looks like this:
stages:
- test
- deploy
test:
stage: test
only:
- merge_request
- master
script:
- jest --coverage
deploy:
stage: deploy
only:
- master
dependencies:
- test
script:
- make deploy
I only want the tests to be run when a merge request is opened or if we merge to master because I'm only on the free plan on gitlab.com and I'd like to conserve my runner minutes.
If the unit tests ran for every commit we made, we'd always run out of minutes on the 3rd or 4th week.
For the most part, it works. The problem comes from pushing to master directly (which can happen every now and then); test runs twice and at the same time.
I couldn't find anything on Gitlab docs on how to properly approach this. Any help would be great.
I actually don't see why a direct push to master will run your tests twice except when you have an open merge-request which master as source branch.
You can prevent this from happening by using workflow. Furthermore you should use rules instead of only/except as they are not actively developed any more.
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: '$CI_COMMIT_BRANCH'
stages:
- test
- deploy
test:
stage: test
script:
- jest --coverage
rules:
- if: '$CI_COMMIT_BRANCH == "master" || $CI_PIPELINE_SOURCE == "merge_request_event"'
deploy:
stage: deploy
dependencies:
- test
script:
- make deploy
rules:
- if: '$CI_COMMIT_BRANCH == "master"'

Gitlab run a pipeline job when a merge request is merged

I have a gitlab pipeline where there are two stages, one is build and the other one is deploy. The build stage is run when a commit is made. I want a way to run the deploy job when the merge request is merged to master. I tried several things but no luck. Can anyone help?
stages:
- build
- deploy
dotnet:
script: "echo This builds!"
stage: build
production:
script: "echo This deploys!"
stage: deploy
only:
refs:
- master
Try using the gitlab-ci.yml "rules" feature to check for the merge request event.
Your current gitlab-ci.yml will run your "dotnet" job every commit, merge request, schedule, and manually triggered pipeline.
https://docs.gitlab.com/ee/ci/yaml/#workflowrules
dotnet:
script: "echo This builds!"
stage: build
rules:
- if: '$CI_COMMIT_REF_NAME != "master" && $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"'
production:
script: "echo This deploys!"
stage: deploy
rules:
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_REF_NAME == "master"'
If you want your job run on only after merging the merge request, then you can trigger a job based on the commit message, as shown below.
rules:
- if: '$CI_COMMIT_MESSAGE =~ /See merge request/'
Basically, all the merge request comes with a "See merge request" commit message so you can depend on that message to trigger your job.
You can run the pipeline after merge by using Gitlab ci predefined variable $CI_MERGE_REQUEST_APPROVED this will return true after merge and available from gitlab v14.1.
If you want to run the pipeline when merge request is created to main branch you can use $CI_MERGE_REQUEST_TARGET_BRANCH_NAME with $CI_MERGE_REQUEST_APPROVED.
you can add the rule like this in your job.
rules:
- if: $CI_MERGE_REQUEST_APPROVED && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
CI_MERGE_REQUEST_APPROVED variable seems to be designed for check approve status, not for triggering pipeline. (Issue, https://gitlab.com/gitlab-org/gitlab/-/issues/375908)
When you use merge request predefined variables, gitlab creates pipeline at merge request created, not at merge request approved.
Instead, use CI_COMMIT_BRANCH predefined variables with regular expression and restrict commit at master branch using branch access rights.
stages:
- build
- deploy
dotnet:
stage: build
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "master"
script: "echo This builds!"
production:
stage: deploy
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "master"
script: "echo This deploys!"
Edit answer for incorrect example. (edited at 2023. 01. 26)
Assume that we have rc and master branch.
We can configure master branch as protected, and use only for merge request.
In this case, we can define gitlab-ci file like below.
stages:
- build
- deploy
dotnet:
stage: build
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "rc"
script: "echo This builds!"
production:
stage: deploy
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "master"
script: "echo This deploys!"
Thanks for notification #Kappacake

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