GitLab CI/CD¶
Two CI/CD components record one run event per pipeline execution. Add an include and the value report builds itself from your pipelines.
Which one to use¶
report-run adds its own job, in the .post stage, running an image that has
curl and jq. Use it when you want reporting that doesn't care what your other
jobs run in, or when you want the pipeline's outcome rather than one job's.
after-script contributes a hidden job you extend from the job you want
measured. Reporting happens in that job's after_script, where $CI_JOB_STATUS
holds the real outcome, so one include covers success and failure together. The
job's own image needs curl and jq.
Every GitLab pipeline can also report through plain HTTP with a curl step, and the components mostly save you writing that curl.
The API key¶
Set LUMATRACK_API_KEY under Settings, CI/CD, Variables, masked. Protect it too
if you only report from protected branches.
Neither component takes the key as an input. include: inputs are part of the
pipeline configuration, so anyone who can read the config would be able to read
the key.
An ingest-only key is enough to record runs and is the one to use in a pipeline: if it leaks, an attacker can post junk runs, and they cannot read or restate your ledger.
report-run¶
include:
- component: $CI_SERVER_FQDN/lumatrack/gitlab-components/report-run@1.0.0
inputs:
base-url: https://lumatrack.io
automation: deploy-pipeline
job-name: lumatrack-success
when: on_success
status: success
- component: $CI_SERVER_FQDN/lumatrack/gitlab-components/report-run@1.0.0
inputs:
base-url: https://lumatrack.io
automation: deploy-pipeline
job-name: lumatrack-failure
when: on_failure
status: failure
| Input | Notes |
|---|---|
base-url |
Your LumaTrack host, e.g. https://lumatrack.example.com |
automation |
The slug this pipeline reports as; create it in the app or over the API |
status |
success, failure, skipped or cancelled. GitLab's own failed and canceled are accepted and mapped |
when |
on_success, on_failure or always |
job-name |
Name of the generated job. Each include needs its own |
stage |
Defaults to .post, which runs after everything else |
failure-reason |
Root cause, e.g. deploy/timeout. Powers the failure-reason Pareto |
duration-seconds |
Wall-clock runtime. Leave it empty rather than sending a guess |
units |
Records the run processed; drives per-unit valuation. Empty leaves the server default of 1 |
external-id |
Defaults to the pipeline id and job id, which makes a retried job idempotent |
metadata |
JSON object kept with the run |
source |
Stored on the run, gitlab-ci by default |
image |
Needs curl and jq |
fail-on-error |
false by default, so a LumaTrack outage never fails a deploy that worked |
after-script¶
include:
- component: $CI_SERVER_FQDN/lumatrack/gitlab-components/after-script@1.0.0
inputs:
base-url: https://lumatrack.io
automation: deploy-pipeline
deploy:
extends: .lumatrack-report-run
stage: deploy
script:
- ./deploy.sh
$CI_JOB_STATUS maps to a status of its own: failed books as failure and
canceled books as cancelled. Neither skipped nor cancelled earns value,
and neither is ever reported as a failure. A cancelled job was interrupted part
way; whether it carries the automation's per-run cost is set per automation in
LumaTrack. Each keeps its own reason, ci/failed or ci/cancelled, so the
Pareto can tell them apart.
Reporting from after_script can't fail the job it measures. Every failure path
prints what went wrong and exits 0, because an after_script that exits non-zero
marks a green deploy red.
Wire the failure path too¶
One include on the success path is half the integration. Failed pipelines cost
money and save nothing, and reporting them is what makes the reliability chart
and the net numbers credible. With report-run that means the second include
with when: on_failure. With after-script you get it for free, since
$CI_JOB_STATUS reports whatever actually happened.
Batches and loops¶
A pipeline that processes 240 records should report one run with units: 240,
not 240 runs. The ledger prices per-unit work as fixed setup plus marginal
minutes per record, which is the number that survives a CFO's review. Separate
runs would each consume an event against your plan's monthly cap and tell you the
same thing.
If a parallel matrix job runs 8 times, each instance has its own $CI_JOB_ID, so
the default external id books 8 runs. That's usually right, because each one
genuinely succeeded or failed on its own. Set external-id to
$CI_PIPELINE_ID if you'd rather have one run for the whole matrix; the first
job records it and the other 7 dedupe.
Many pipelines, one automation?¶
Map them the way your accounting works. If three pipelines together replace one manual task, point all three at the same slug. If one pipeline does two unrelated jobs, either split it or pick the slug per include.
Terraform pipelines¶
If the pipeline runs Terraform, the Terraform provider reports from inside the config instead, which lets a single apply report the units it actually touched. The two work together: the component reports the job, and the provider reports what the apply did.