GitLab CI and other pipelines
A GitLab CI job that reports a deployment as it starts and as it ends, with the pipeline id as the idempotency key, and the two calls that do the same from Bitbucket Pipelines, Jenkins or any other runner.
By the end of this page a GitLab CI job will report every deployment it makes, and you will have the two calls that do the same from any other runner. The calls are the ones on CI/CD ingestion; this page puts them where a pipeline file expects them.
Before you begin
| You need | Why |
|---|---|
| An ingestion token | A token with ci:deploy, confined to the project; see CI/CD ingestion. |
| The project and environment ids | Both are in the address bar of their pages. |
curl and jq in the job's image | Most images carry curl; add jq to read the deployment id out of the answer. |
Add the variables
Under the project's CI/CD settings at GitLab, add the token as a masked variable and the rest as plain variables:
| Name | Masked | Value |
|---|---|---|
BIFROST_TOKEN | yes | The ingestion token, shown once when it was minted. |
BIFROST_API | no | The API base address your workspace answers on. |
BIFROST_PROJECT | no | The project's id. |
BIFROST_ENVIRONMENT | no | The environment's id; one per environment deployed. |
Report as the job starts and ends
deploy-staging:
stage: deploy
image: alpine:3.20
before_script:
- apk add --no-cache curl jq
- |
DEPLOYMENT_ID=$(curl -sS --fail-with-body -X POST "$BIFROST_API/v1/projects/$BIFROST_PROJECT/deployments" \
-H "Authorization: Bearer $BIFROST_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $CI_PIPELINE_ID-$CI_JOB_ID-start" \
-d "{\"environment_id\": \"$BIFROST_ENVIRONMENT\", \"version\": \"$CI_COMMIT_SHORT_SHA\", \"status\": \"running\", \"commit_sha\": \"$CI_COMMIT_SHA\", \"branch\": \"$CI_COMMIT_REF_NAME\", \"pipeline_url\": \"$CI_JOB_URL\"}" \
| jq -r '.data.id')
echo "DEPLOYMENT_ID=$DEPLOYMENT_ID" > deployment.env
script:
- ./scripts/deploy.sh staging
after_script:
- |
. ./deployment.env
case "$CI_JOB_STATUS" in
success) STATUS=succeeded ;;
canceled) STATUS=cancelled ;;
*) STATUS=failed ;;
esac
curl -sS --fail-with-body -X PATCH "$BIFROST_API/v1/deployments/$DEPLOYMENT_ID" \
-H "Authorization: Bearer $BIFROST_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $CI_PIPELINE_ID-$CI_JOB_ID-finish" \
-d "{\"status\": \"$STATUS\"}" > /dev/null
environment:
name: stagingThe after_script runs whatever happened to script, and CI_JOB_STATUS says how it went, so
the deployment is finished the way the job ended. Use a tag as the version on a release job
($CI_COMMIT_TAG); the commit is reported beside it either way. The pipeline id and the job id
make the idempotency key, so a retried job records a fresh deployment and a replayed request
records nothing twice.
Report in one call instead
A job that only wants the outcome on record sends one request from after_script:
after_script:
- |
case "$CI_JOB_STATUS" in success) STATUS=succeeded ;; *) STATUS=failed ;; esac
curl -sS --fail-with-body -X POST "$BIFROST_API/v1/projects/$BIFROST_PROJECT/deployments" \
-H "Authorization: Bearer $BIFROST_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $CI_PIPELINE_ID-$CI_JOB_ID" \
-d "{\"environment_id\": \"$BIFROST_ENVIRONMENT\", \"version\": \"$CI_COMMIT_SHORT_SHA\", \"status\": \"$STATUS\", \"commit_sha\": \"$CI_COMMIT_SHA\", \"branch\": \"$CI_COMMIT_REF_NAME\", \"pipeline_url\": \"$CI_JOB_URL\"}" > /dev/nullAny other pipeline
Bitbucket Pipelines, Jenkins, CircleCI, Buildkite or a shell script on a server all report the
same way: a POST that opens the deployment as running and keeps the id, a PATCH that finishes
it with the job's outcome, each with an Idempotency-Key made of the run's own id. The two calls,
with every field, are on CI/CD ingestion. Whatever the runner, the
rules are the same: the token carries ci:deploy alone, the version is what you would say to a
colleague, and the finish step runs whether the deployment went well or badly.
A deployment done by hand
A deployment nobody's pipeline made is recorded the same way, with a staff
token or by asking Heimdall, with "status": "succeeded" and the time it
happened in finished_at; the source is recorded as by hand.
Related
- CI/CD ingestion: the token and the calls.
- GitHub Actions: a composite action for GitHub workflows.
- CI and deployments: what the record looks like inside the application.
How is this guide?
Last updated on
GitHub Actions
A composite action you copy into your repository that reports a deployment as the job starts and as it ends, the workflow that uses it, the secrets and variables it needs, and the GitHub deployments alternative that needs no step at all.
Telegram
Link your account to the Zuse Bifrost bot with a one-time code, receive alerts in a private chat, and ask the bot who you are linked as.