# Pipelines
- Terminology
- Connecting the project to CI / CD
- General recommendations
- Tags
- Multiplatform image build
- Push images to private docker registry
- How to push git tag on CI / CD launch
- DRY
- How to improve pipeline throughput
- How to replace entrypoint in image
- How to debug failed jobs?
- Static Analyzers, dep scanners, and linters
# Terminology
Runner
orGitlab Runner
is the server on which the CI commands are executed.Runner executor
is how the runner executes commands.Pipeline
is a set of stages through which a project is built or tested.Job
is some action in the Pipeline, e.g. the launch of unit tests.Stage
is a Pipeline stage that can simultaneously execute somejobs
.CI / CD
is shortened from Continuous Integration and Continuous Deployment.
# Connecting the project to CI / CD
Read official documentation (opens new window).
# General recommendations
- Recommended folder for all CI/CD related files is
ci/
. - If for the tests launch you need to deploy the database or any other services use [services] (https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#define-image-and-services-from-gitlab-ciyml (opens new window))
- Do not use Makefile to run commands in gitlab-ci. Makefile is used only as a developer tool.
- If you need to write conditions or a multi-line
script
, move the code into a separate bash file and put it inci / bin /
. - If you need to transfer artifacts from one stage to another, use
artifacts
anddependencies
. - Be sure to set a reasonable
expires_in
for artifacts. At least for a few hours. Documentation (opens new window). - Write stage and job names in lowercase snake style (opens new window).
# Tags
docker
- container execution, documentation (opens new window).shell
- execution in a shell. You can use only those utilities that were preinstalled for the runner.ansible
- if you need to run Ansible.ruby
- if ruby is required. We recommend usingdocker
with theimage: ruby
declaration.sourceguardian
- server with sourceguardian.ioncube
- server with ioncube.
# Multiplatform image build
Build images for both x64 and ARM CPU architectures:
build:
tags: [docker]
image: docker:20.10.22-dind
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2376
DOCKER_CERT_PATH: /certs/client
DOCKER_TLS_VERIFY: 1
scripts:
- docker login -u "$CI_DEPLOY_USER" -p "$CI_DEPLOY_PASSWORD" "$CI_REGISTRY" || true
- export VERSION=$(cat VERSION | tr -d "[:space:]")
- export MAJOR_VERSION=$(echo $VERSION | cut -d. -f1)
- export MINOR_VERSION=$(echo $VERSION | cut -d. -f2)
- docker context create tls-environment
- docker buildx create --name multiarch-builder --driver docker-container --use tls-environment
- docker buildx build --platform=linux/arm64,linux/amd64
--tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME"
--tag "$CI_REGISTRY_IMAGE:$VERSION"
--tag "$CI_REGISTRY_IMAGE:$MAJOR_VERSION"
--tag "$CI_REGISTRY_IMAGE:${MAJOR_VERSION}.${MINOR_VERSION}"
--tag "$CI_REGISTRY_IMAGE:latest"
--file "ci/Dockerfile"
--build-arg PHP_VERSION=${PHP_VERSION} "."
--push
--provenance=false
# Push images to private docker registry
Authorization
before_script: docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY};
CI_JOB_TOKEN
and CI_REGISTRY
- are already available (opens new window) when running a pipeline in CI / CD.
Publish with a tag containing the full address of the image, doc (opens new window):
docker build -t GITLAB_REGISTRY:1443/group/subgroup/project . docker push GITLAB_REGISTRY:1443/group/subgroup/project
# How to push git tag on CI / CD launch
Gitlab has not yet implemented (opens new window) a mechanism for creating tags via CI, but you can use the API:
#!/usr/bin/env bash
set -e -x -o pipefail
curl -X POST --show-error --fail "https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/repository/tags?ref=${CI_COMMIT_SHA}&tag_name=${APP_VERSION}&private_token=${GITLAB_TOKEN}"
GITLAB_URL
- GitLab URL.CI_PROJECT_ID
- project ID. Forwarded by Gitlab CI itself.CI_COMMIT_SHA
- commits SHA. Forwarded by Gitlab CI itself.APP_VERSION
- product or deployment version.GITLAB_TOKEN
- Personal Access Tokens. It is advisable not to use your own token, but create the token for theBot
user.
# DRY
- Use extends (opens new window)and includes (opens new window)
- Define default section (opens new window)
- Use the
apliteni/shared-tools
project toolkit.
# How to improve pipeline throughput
Run independent jobs in parallel simultaneously:
stages:
- checks
check_1: stage: checks script: ... check_2: stage: checks script: ...
Use cache (opens new window) and artifacts/dependencies (opens new window). Cache to cache the result and reuse it in the same job. Artifacts - for using the result in other jobs.
Use parallel (opens new window) when possible.
Add
interruptible: true
to the jobs.Find jobs that depend on the same artifact and combine them to one.
# How to replace entrypoint in image
White empty entrypoint
:
image:
name: "${APP_IMAGE}"
entrypoint: [ "" ]
# How to debug failed jobs?
Read the logs
Go to a Project > CI / CD > Jobs
Try debug mode
- Add to
script
on failed jobsleep 10000
. - Run pipeline.
- Press
Debug
button on the running job page.
Debug ENVs
Add to the .gitlab-ci.yml
:
do_something:
variables:
CI_DEBUG_TRACE: "true"
Run gitlab-runner locally
You can run gitlab-runner locally, but it has a number of things to mention:
- The pod must be committed, because checkout is done during the execution.
extends
are not supported.- Global
(before|after)_script
,image
,services
are not supported. - Local cache is not supported. Connection to minio/s3 (opens new window) can be configured.
Installation https://docs.gitlab.com/runner/install (opens new window)
Then you can run jobs locally.
An example with docker-executor:
gitlab-runner exec docker do_something
An example with shell-executor:
gitlab-runner exec shell do_something
# Static Analyzers, dep scanners, and linters
Check Pipeline components (opens new window) for additional images.
# Golangci-lint (*.go)
See shared-tools
repo for .golang-ci.yml
configuration file.
golangci_lint:
stage: quality_checks
tags: [docker]
image: golangci/golangci-lint
script:
- golangci-lint run -v -c .golang-ci.yml
# DependencyCheck (*.go)
TODO: jeremylong/DependencyCheck (opens new window).
# Yamllint (*.yaml)
See shared-tools
repo for .yamllint.yaml
configuration file.
yaml_lint:
stage: quality_checks
tags: [docker]
image: registry.gitlab.com/pipeline-components/yamllint:0.19.3
script:
- yamllint .
# Styelint (*.css, *.scss)
stylelint:
stage: quality_checkss
tags: [docker]
image: registry.gitlab.com/pipeline-components/stylelint:latest
script:
- stylelint --color 'src/**/*.(css|sass|scss)'
# NPM audit
npm_audit:
stage: quality_checks
tags: [docker]
image: node:16
script:
- npm audit --audit-level=high
cache:
paths:
- node_modules
dependencies:
- npm
# Rubycop (*.rb)
rubocop:
stage: quality_checks
tags: [docker]
image: GITLAB_DOMAIN:1443/apliteni/third-party/ruby:rubocop
script:
- rubocop -E -P
Replace GITLAB_DOMAIN
.
# Remark-lint (*.md)
remark-lint:
stage: quality_checks
tags: [docker]
image: GITLAB_DOMAIN:1443/apliteni/third-party/remark-lint:latest
script:
- remark --no-stdout --color .
Replace GITLAB_DOMAIN
.
# Textlint (*.md)
textlint:
stage: quality_checks
tags: [docker]
image: GITLAB_DOMAIN:1443/apliteni/third-party/textlint:latest
script:
- .
Replace GITLAB_DOMAIN
.
# bundler-audit
TODO: stage example with rubysec/bundler-audit
.
# Psalm (*.php)
TODO stage example with psalm
# local-php-security-checker (*.php)
TODO: stage example with local-php-security-checker (opens new window).
# Tslint (*.ts)
TODO
# Trivy (docker, kubernetes)
TODO: stage example with [Trivy][https://github.com/aquasecurity/trivy].
# Snyk (.)
TODO: stage example with Snyk (opens new window) code vulnerability scanning.
← Guidelines Docker →