A common GitLab CI failure is not that the deploy script is wrong.
It is that the pipeline expects a variable nobody documented.
Example:
stages:
- deploy
deploy_production:
stage: deploy
image: alpine:3.20
script:
- test -n "$DEPLOY_TOKEN"
- echo "Deploying $NEXT_PUBLIC_APP_URL"
- ./scripts/deploy.sh --token "$DEPLOY_TOKEN"
And the repo contract says only this:
NEXT_PUBLIC_APP_URL=
DEPLOY_TOKEN exists as an assumption in the pipeline, but not in .env.example or .env.dist.
That means a reviewer can approve the pipeline change without realizing that someone still needs to configure a GitLab CI/CD Variable before deploy.
Why this is deployment drift
The actual secret value belongs in GitLab CI/CD Variables.
The variable name belongs in the repo's environment contract.
When those drift apart, the failure usually appears late:
- a merge request updates
.gitlab-ci.yml; - the deploy job references
$DEPLOY_TOKEN; - the env template does not mention it;
- the pipeline reaches deploy time and fails with missing configuration.
This is especially easy to miss when an AI coding agent or quick cleanup PR changes CI YAML and the review focuses on application code.
A small review habit that catches it
When a merge request changes .gitlab-ci.yml, deploy scripts, or Docker commands, scan for new env references:
$VARIABLE${VARIABLE}process.env.VARIABLE- deploy CLI flags such as
--token "$DEPLOY_TOKEN"
Then check whether the variable name is present in the env contract:
NEXT_PUBLIC_APP_URL=
DEPLOY_TOKEN=
The template should not contain the real value. It only documents that the variable is required.
Automated check
With Secret Coverage, the local check looks like this:
pnpm dlx @leviro-ai/secret-coverage scan --path . --ci
For a pnpm script wrapper inside the repo:
pnpm scan -- --path . --ci
The useful finding is the variable name and location, not the secret value:
DEPLOY_TOKEN is referenced in .gitlab-ci.yml but missing from the env template.
That is the point: metadata-only deployment readiness, before CI or production discovers the missing contract.
Safe fix
- Add
DEPLOY_TOKEN=to.env.exampleor.env.dist. - Configure the real value in GitLab CI/CD Variables.
- Re-run the scan.
- Keep the check in the merge request or CI path so future pipeline edits do not silently add new assumptions.
PR checklist
For any GitLab pipeline change, ask:
- Did this MR add a new
$VARIABLEreference? - Is the variable name documented in
.env.exampleor.env.dist? - Is the real value configured in GitLab CI/CD Variables before merge?
- Should the check fail the MR with
--ciif a required deployment variable is missing?
It is a small habit, but it prevents the frustrating class of deploys that fail because the repo and CI environment stopped agreeing.
Secret Coverage is a local-first, metadata-only environment/deployment readiness scanner: it checks variable names and config references, not raw secret values.
Repo/package: @leviro-ai/secret-coverage
Top comments (0)