Pipeline does not run when using CI_COMMIT_MESSAGE - gitlab

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.

Related

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

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.

Sharing different repositories between jobs for Gitlab CI

In our project we have a number of repositories that are all needed to build a few different docker containers.
The Dockerfiles of all containers are located in a single repository.
I would like to be able to pull all repositories I need for the builds before building the containers. This would avoid pulling a repository multiple times which can take almost a minute for some of these.
Essentially what I would like to do is:
stages:
- initialize
- build
repo1 pull:
stage: initialize
script:
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.instance/group/repo1.git
repo2 pull:
stage: initialize
script:
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.instance/group/repo2.git
image1:
stage: build
script:
- cp repo1/ image1/
- cd image1
- docker build -t image1 --network=host .
- docker login -u gitlab-runner -p gitlab docker.registry
- docker push docker.registry/image1:latest
image2:
stage: build
script:
- cp repo2/ image2/
- cd image2
- docker build -t image2 --network=host .
- docker login -u gitlab-runner -p gitlab docker.registry
- docker push docker.registry/image2:latest
What is the best way to share the repositories over the stages while still allowing for parallel building within the stage?
I'm still learning Gitlab-ci but maybe cache would help?
Add this before you pull the repos and the runner should check if the repo is already in the cache.
cache:
paths:
- repo1/
- repo2/
Gitlab cache reference: https://docs.gitlab.com/ee/ci/caching/
Edit:
Or maybe using Git submodules for the dependant repos would be a good idea?
The runner can then be configured to fetch those submodules to the workspace and you should have access to them throughout the ci job.
You need to add a .gitmodules file that would looks something like this:
[submodule "repo1"]
path = repo1
url = ../repo1.git
[submodule "repo2"]
path = repo2
url = ../repo2.git
And then in your .gitlab-ci.yml
variables:
GIT_SUBMODULE_STRATEGY: normal
Gitlab submodule reference: https://docs.gitlab.com/ce/ci/git_submodules.html

Tagging docker image with tag from git repository

I am using Gitlab for repository and ci/cd.
Currently trying to set up pipeline that creates a docker image from a build stage.
All examples I have seen have a simple naming of image where e.g. the branch is used(master)
My question is if I want to tag the image based on the current tag in the repository how do I do this?
I am presuming I can use a Gitlab runner variable but do not see one to us
There are a lot of predefined variables in Gitlab CI. I think you are looking for CI_COMMIT_TAG.
So you could use it this way:
docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
So the image would look like registry.example.com/group/project:tag
As shell command is not possible yet with variables inside .gitlab-ci.yml, you may edit a build script that get the current tag and build the image inside that script
Both file at the root of your project :
build.sh :
#!/bin/sh
IMAGE="$CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_REF_NAME-$(git describe --abbrev=0 --tags)"
docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
docker build --pull -t $IMAGE .
docker push $IMAGE
.gitlab-ci.yml :
image: docker:latest
services:
- docker:dind
stages:
- release
release:
stage: release
script:
- apk update && apk add git
- ./build.sh

What are services in gitlab pipeline job?

I am using gitlab's pipeline for CI and CD to build images for my projects.
In every job there are configurations to be set like image and stage but I can't wrap my head around what services are. Can someone explain its functionality? Thanks
Here's a code snippet I use that I found
build-run:
image: docker:latest
stage: build
services:
- docker:dind
script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build -t "$CI_REGISTRY_IMAGE/my-project:$CI_COMMIT_SHA" .
- docker push "$CI_REGISTRY_IMAGE/my-project:$CI_COMMIT_SHA"
cache:
untracked: true
environment: build
The documentation says:
The services keyword defines just another Docker image that is run during your job and is linked to the Docker image that the image keyword defines. This allows you to access the service image during build time.

Using a private Docker Image from Gitlab Registry as the base image for CI

How should I authenticate if I want to use an image from the Gitlab Registry as a base image of another CI build?
According to https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry I first have to manually login on the runner machine. Somehow it feels strange to login with an existing Gitlab user.
Is there a way to use the CI variable "CI_BUILD_TOKEN" (which is described as "Token used for authenticating with the GitLab Container Registry") for authentication to pull the base image from Gitlab Registry?
EDIT: I found out that I can use images from public projects. But I don't really want to make my docker projects public.
UPDATE: Starting with Gitlab 8.14 you can just use the docker images from the build in docker registry. See https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#support-for-gitlab-integrated-registry
All of the above answers including the acepted one are deprecated, This is possible in 2021:
https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#access-an-image-from-a-private-container-registry
TL;DR
Set the CI/CD variable DOCKER_AUTH_CONFIG value with appropriate authentication information in following format:
Step 1:
# The use of "-n" - prevents encoding a newline in the password.
echo -n "my_username:my_password" | base64
# Example output to copy
bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
Step 2 (This JSON is the value to be set for DOCKER_AUTH_CONFIG variable):
{
"auths": {
"registry.example.com:5000": {
"auth": "(Base64 content from above)"
}
}
}
Now it's possible, they have included that option months ago.
Use gitlab-ci-tokenas user and the variable $CI_BUILD_TOKEN as password.
This example works on GitLab 8.13.6. It builds the test image if needed, and in the next stage uses it to perform syntax checks:
build_test:
stage: build_test_image
script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:test -f dockerfiles/test/Dockerfile .
- docker push $CI_REGISTRY_IMAGE:test
tags:
- docker_build
environment: test
test_syntax:
image: $CI_REGISTRY_IMAGE:test
stage: test
script:
- flake8 --ignore=E501,E265,E402 .
UPDATE: Re-reading the question, the accepted answer is correct. In my example, the job test_syntax will fail to authenticate to the registry, unless the user logins manually from the runner machine. Although, it can work if the 2 runners are on the same host, but it's not the best solution anyway.
In gitlab-ci-multi-runner 1.8 there's an option to add the Registry credentials as a variable, so you only need to login once to get the encoded credentials. See documentation.
No, this is currently not possible in any elegant way. GitLab should implement explicit credentials for the base images, it will be the most straight-forward and correct solution.
You need to docker login on the GitLab Runner machine. You can't use the gitlab-ci-token since they expire and also project-dependant, so you can't actually use one token for every project. Using your own login is pretty much the only solution available right now (happy to get corrected on this one).
This is absolutely possible as of September 2018. I'll post my naive implementation here.
Context:
You'll need to leverage the docker:dind service, which lets you run the docker command inside of a docker container.
This will require you to use a valid docker login, which you can do using GitLab's builtin variables (gitlab-ci-token, $CI-JOB-TOKEN).
You should then be able to authenticate to your repo's registry (example $REGISTRY value: registry.gitlab.com/$USER/$REPO:$TAG), which will allow you to push or pull docker containers from inside the CI/CD context, as well as from any authenticated docker server.
Implementation:
Create this block at top level to ensure it runs before the following jobs:
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $REGISTRY
Job to build and save images to your registry:
build_container:
image: docker:latest
stage: build
services:
- docker:dind
script:
- docker build -t $REGISTRY .
- docker push $REGISTRY
Job that uses the custom image:
build_app:
image: $REGISTRY
stage: deploy
script:
- npm run build
Regarding Cross-Repo Jobs:
I accomplish this by creating a "bot" GitLab user and assigning them access to repos/groups as appropriate. Then it's just a matter of replacing gitlab-ci-token and $CI_JOB_TOKEN with appropriate environment variables. This is only necessary if the base image is private.
Its possible you first have to login to gitlab container registry of the image you want to use, kindly see below example. Notice the
before_script: which basically auths you before using the image.
image: docker:latest
services:
- docker:dind
stages:
- build
variables:
CONTAINER_RELEASE_IMAGE: registry.gitlab.com/obonyojimmy/node-mono-clr:latest
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_BUILD_TOKEN registry.gitlab.com
build-app:
stage: build
image: $CONTAINER_RELEASE_IMAGE
script:
- npm run build
I had a similar situation. My Java application uses Testcontainers lib in tests and this lib runs Docker container from private registry. I spent a lot of time trying to figure this out and I managed to handle this by creating a ~/.docker/config.json file in before_script section. I hope it'll help somebody:
image: openjdk:11-jdk-slim
stages:
- build
before_script:
- mkdir ~/".docker"
- echo "{\"auths\":{\"$REGISTRY_HOST\":{\"auth\":\"$(printf "$REGISTRY_USER:$REGISTRY_PASSWORD" | openssl base64 -A)\"}}}" > ~/".docker/config.json"
build:
stage: build
services:
- docker:dind
script:
- ./gradlew build

Resources