Skip to content
Browse the docs

CI/CD

Bitbucket Pipelines

Install crunu in a Bitbucket Pipelines step or use the crunu pipe, keep CRUNU_TOKEN in secured variables, and bind a step's OIDC token to your own audience.

Last updated

On this page

In Bitbucket Pipelines, a step either installs crunu with three commands and runs your command in the step's own image, or uses the crunu run pipe, which runs your command inside the pipe's container. Read Any CI with a service token first for how to create the token.

Repository variables

Add these under Repository variables:

  • CRUNU_TOKEN, the service token crunu_svc_…, marked Secured;
  • CRUNU_SERVER, https://app.crunu.com or your own server's address;
  • CRUNU_VERSION, CRUNU_INSTALL_URL, CRUNU_INSTALL_SHA256 and CRUNU_BINARY_SHA256, from the CI setup block on the token's page.

With three commands

YAML
image: node:24

definitions:
  steps:
    - step: &test
        name: Tests with staging variables
        oidc:                 # only if the token has a CI binding
          audiences:
            - https://app.crunu.com   # your server address: an audience of its own
        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

pipelines:
  default:
    - step: *test

The command runs in the step's image with all of its tools.

With the crunu run pipe

The pipe installs a pinned crunu, checks both checksums and runs:

Shell
crunu run --env <project/environment> -- sh -c "$COMMAND"

Variables are decrypted in the memory of the crunu process and passed to the command through its environment. They aren't written to disk. The pipe's exit code is the command's exit code. If crunu couldn't get the variables, the exit code is its own and the command doesn't run.

The command runs inside the pipe's container, not in the step's image. The default base image is Node.js 24, with node, npm and npx. If the command needs other programs, build the pipe on another Debian, Ubuntu or Alpine base image.

YAML
pipelines:
  default:
    - step:
        name: Tests with staging variables
        script:
          - pipe: docker://<registry>/<name>:<tag>
            variables:
              CRUNU_TOKEN: $CRUNU_TOKEN
              CRUNU_SERVER: $CRUNU_SERVER
              CRUNU_ENV: 'web-app/staging'
              CRUNU_VERSION: $CRUNU_VERSION
              CRUNU_INSTALL_URL: $CRUNU_INSTALL_URL
              CRUNU_INSTALL_SHA256: $CRUNU_INSTALL_SHA256
              CRUNU_BINARY_SHA256: $CRUNU_BINARY_SHA256
              COMMAND: 'npm ci && npm test'
VariableRequiredValue
CRUNU_TOKENyesthe service token
CRUNU_SERVERyesthe server address
COMMANDyesa shell command, for example npm test
CRUNU_ENVnoone environment as project/environment. Without it and without CRUNU_ENVS, all environments granted to the token
CRUNU_ENVSnoseveral environments as a list
CRUNU_VERSIONyesthe crunu version
CRUNU_INSTALL_URLyes, unless CRUNU_RELEASES_URL is setthe address of install.sh for this version
CRUNU_INSTALL_SHA256, CRUNU_BINARY_SHA256yeschecksums from the CI setup block
OIDCno'true' when the token has a CI binding
INHERIT_ENVno'true' passes the whole environment of the pipe's container to the command, including BITBUCKET_*
DEBUGno'true' for a detailed crunu log. Secret values never appear in it

By default the command gets only PATH, HOME, USER, LOGNAME, LANG, LC_ALL, TERM, TZ, SHELL, TMPDIR and the environment's variables. It runs in the clone directory of the repository.

OIDC in a Bitbucket step

A step with OIDC turned on gets a token in BITBUCKET_STEP_OIDC_TOKEN, and crunu picks it up itself. Bitbucket gives a step one token for all of its audiences. Add your server address as a custom audience under oidc: audiences:. The default audience, ari:cloud:bitbucket::workspace/<uuid>, also works, but every service in the workspace receives the same token, so your own audience is safer. Up to 10 audiences are allowed per step.

With the pipe, also pass OIDC: 'true'. The pipe then checks that the step's token exists and stops before installing crunu if it doesn't. Without OIDC: 'true' the pipe passes the step's token neither to crunu nor to the command. If the command needs an OIDC token for another cloud, run it in a separate step.

Bitbucket tokens have no jti claim. The server treats presenting the same token twice as a replay, so crunu signs in once per step and keeps that session.

A typical rule: provider Bitbucket, your workspace name and UUID, the repository UUID, branchName: main and, for production, the deployment environment UUID. See Bind a service token to CI with OIDC.

Where the token is visible

The pipe starts crunu with exec, so no other process in the pipe's container holds CRUNU_TOKEN, and on Linux crunu closes its own environment. That was checked with Docker's default container permissions: the command runs as root but without CAP_SYS_PTRACE. A process with that capability could read the environment of crunu. Repository variables are still visible to every other line of the step and to every step of the pipeline, so keep the token's grant small.