Skip to content
Browse the docs

CI/CD

GitLab CI

Use the .crunu job template or three install commands in GitLab CI, give jobs only their environments, and request an ID token for a token with OIDC.

Last updated

On this page

In GitLab CI, a job installs crunu before its script and runs your command with crunu run. You can write the three install commands yourself or extend a job template that does it for you. Read Any CI with a service token first for how to create the token.

CI/CD variables

Set these in Settings → CI/CD → Variables of the project:

VariableValue
CRUNU_TOKENthe service token crunu_svc_…, marked Masked and Protected
CRUNU_SERVERhttps://app.crunu.com, or your own server's address
CRUNU_VERSIONthe crunu version, for example 6.0.0
CRUNU_INSTALL_URLthe address of install.sh for this version. The binary is taken from the same directory
CRUNU_RELEASES_URLinstead of CRUNU_INSTALL_URL: the release directory, with each version in its own subdirectory
CRUNU_INSTALL_SHA256SHA-256 of install.sh
CRUNU_BINARY_SHA256SHA-256 of the binary: one checksum for Linux amd64, or one per platform such as amd64=… arm64=…
CRUNU_BIN_DIRoptional: where to put crunu. Defaults to /usr/local/bin as root and ~/.local/bin otherwise

The token page in the web app shows CRUNU_VERSION, CRUNU_INSTALL_URL and both checksums in its CI setup block. They come from the signed release manifest. The binary checksum there is for Linux amd64. For arm64 runners, give checksums per platform from the release's manifest.json.

The job image needs sh and curl or wget. The node, python and alpine images have them. On a plain ubuntu or debian image, run apt-get update && apt-get install -y curl ca-certificates first.

With three commands

YAML
test:
  image: node:24
  id_tokens:
    CRUNU_ID_TOKEN:
      aud: https://app.crunu.com   # only if the token has a CI binding
  script:
    - curl -sSf "$CRUNU_INSTALL_URL" -o /tmp/crunu-install.sh
    - echo "$CRUNU_INSTALL_SHA256  /tmp/crunu-install.sh" | sha256sum -c -
    - sh /tmp/crunu-install.sh --version "$CRUNU_VERSION" --sha256 "$CRUNU_BINARY_SHA256" --user-install
    - crunu run --env web-app/staging -- npm test

With the .crunu template

Crunu includes a template file, crunu.gitlab-ci.yml, in the deploy/ci/gitlab/ directory of its source. It defines two hidden jobs that run nothing by themselves. Your jobs inherit them with extends:

  • .crunu installs a pinned crunu in before_script, checks the SHA-256 of both install.sh and the binary, adds crunu to the job's PATH and prints crunu version.
  • .crunu-oidc does the same and also declares id_tokens. GitLab then gives the job a JWT whose audience is the Crunu server address, and crunu reads it from CRUNU_ID_TOKEN itself. Use it when the service token has a CI binding.

The template doesn't contact the Crunu server and doesn't publish anything. Include it from a copy in your repository, which is recommended because changes go through the same review as your code, or from another GitLab project pinned to a commit:

YAML
include:
  - local: ci/crunu.gitlab-ci.yml

test:
  image: node:24
  extends: .crunu
  script:
    - crunu run --env web-app/staging -- npm test

deploy:
  image: node:24
  extends: .crunu-oidc        # the production token has a CI binding
  environment: production
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  script:
    - crunu run --env web-app/production -- npm run deploy

If your job has its own before_script

A job's own before_script replaces the template's, because extends doesn't merge lists of commands. Add the template's steps explicitly:

YAML
test:
  extends: .crunu
  before_script:
    - !reference [.crunu, before_script]
    - npm ci
  script:
    - crunu run --env web-app/staging -- npm test

What is checked

  • The checksum of install.sh is verified before it runs. On a mismatch the job stops and crunu isn't installed.
  • install.sh checks the binary's checksum and that it starts. Only then is crunu put in place.
  • Invalid values, such as a missing checksum, an address that isn't https://, or stray characters in a checksum, are refused before anything is downloaded.

Where the token is visible

The command under crunu run doesn't get the credentials of crunu: CRUNU_TOKEN, CRUNU_ID_TOKEN, CRUNU_OIDC_TOKEN and CRUNU_ENROLL_CODE. Other lines of the job's script see them, like any job variable. Keep the token's grant small: only the environment the job needs, and production only for a token with a CI binding.

Binding the token to a project and branch

A typical rule for a production token: provider GitLab, project_path: kiteline/web-app, ref: main, ref_type: branch, environment: production, with the server address as the audience. On a self-managed GitLab, set the issuer to its address. See Bind a service token to CI with OIDC.