DEV Community

Darius Hermes
Darius Hermes

Posted on

GitLab CI deploy failed because one token was never documented

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"
Enter fullscreen mode Exit fullscreen mode

And the repo contract says only this:

NEXT_PUBLIC_APP_URL=
Enter fullscreen mode Exit fullscreen mode

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=
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

For a pnpm script wrapper inside the repo:

pnpm scan -- --path . --ci
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

That is the point: metadata-only deployment readiness, before CI or production discovers the missing contract.

Safe fix

  1. Add DEPLOY_TOKEN= to .env.example or .env.dist.
  2. Configure the real value in GitLab CI/CD Variables.
  3. Re-run the scan.
  4. 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 $VARIABLE reference?
  • Is the variable name documented in .env.example or .env.dist?
  • Is the real value configured in GitLab CI/CD Variables before merge?
  • Should the check fail the MR with --ci if 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)