Conditional variables
The ability to conditionally modify variable can be handy in many places. By default, variable could have a value and based on a condition, it could have a different value.
By writing this rule within workflow we get this conditional variable value for all jobs.
variables:
DOCKER_TAG: $CI_COMMIT_REF_NAMEworkflow:
rules:
- if: $CI_COMMIT_REF_NAME == "main"
variables:
DOCKER_TAG: "latest" # Override
Test in local system before pushing code
At times, we would like to run the gitlab build locally to avoid silly mistakes and spending lot of time waiting for the build flow.
If we have lot of external dependency like connecting to AWS etc., testing in local may be too hard. The following is a handy way to test in local, if we have simple straightforward gitlab CICD flow.
We can run the gitlab cicd flow, the flows that actually gets executed inside a runner in local. We can use gitlab-runner docker image and execute the flow.
From the base directory of our repository,
- mount the whole application into gitlab-runner
- attach our local system’s
docker.sock. This helps to reuse docker images that we already have in host system.
docker run --rm \ --name gitlab-runner \ -v $PWD:$PWD \ -v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
Pytest with poetry
Here is an example that showcases pytest execution in gitlab-ci
image: python:3.10-slimservices:
- docker:stable-dindstages:
- unit_testunit_test:
stage: unit_test
before_script:
- pip install poetry
- poetry export --dev -f requirements.txt --output requirements.txt --without-hashes
- pip install -r requirements.txt
script:
- pytest
allow_failure: false
Multi line scripts
Many time gitlab-ci.yaml is hard to read because some of the commands are too long. But gitlab-ci yaml uses generic yaml parser. So we can break long lines into multiple lines without any hassle. No escape characters like \ or / or \n etc is needed. Following works without any issues
docker_publish:
stage: docker
script:
- DOCKER_BUILDKIT=1 docker build
--build-arg argument_1=some_thing
--build-arg argument_2=some_thing_else
-t $DOCKER_REGISTRY/awesome_app:latest .
Debug variables
There are times we use a variable but gitlab pipeline get’s unexpected value. May be, the value is overriden in the hierrachy of the project group.
To quickly debug, create a temporary repo at the same level and have a simple .gitlab-ci.yaml with following content. This will print all env
print:
script:
- env
- '& echo "$MY_VARIABLE"'
Reducing duplication
There are different strategies to reduce duplication in .gitlab-ci file.
Using extends
.tests:
script: rake test
stage: test
only:
refs:
- branchesrspec:
extends: .tests
script: rake rspec
only:
variables:
- $RSPEC
Using includes
include:
remote: '[https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'](https://gitlab.com/awesome-project/raw/main/.before-script-template.yml')
or
include: '/templates/.after-script-template.yml
'
If we have multiple projects which share similar continuous integration flow, extracting it out as separate common repo and including it improves the whole ecosystem.
References
- gitlab ci — docker in docker (dind) flow well explained — [here](https://blog.nestybox.com/2020/10/21/gitlab-dind.html)
- gitlab rules & variables — [Documentation](https://docs.gitlab.com/ee/ci/yaml/#rulesvariables)
- Choose when to run jobs — [Documentation](https://docs.gitlab.com/ee/ci/jobs/job_control.html)
- gitlab — workflow — rules — variables — [Documentation](https://docs.gitlab.com/ee/ci/yaml/#workflowrulesvariables)