Skip to content
Browse the docs

CI/CD

GitHub Actions

Install a pinned crunu in a GitHub Actions job with the setup-crunu action or three commands, run tests with staging variables, and bind the token with OIDC.

Last updated

On this page

In GitHub Actions, a job installs crunu, then runs your command with crunu run. The service token goes into repository secrets and the other values into repository variables. Read Any CI with a service token first for how to create the token.

Repository settings

NameWhereValue
CRUNU_TOKENsecretsthe service token crunu_svc_…
CRUNU_SERVERvariableshttps://app.crunu.com, or your own server's address
CRUNU_VERSIONvariablesfrom the CI setup block on the token's page
CRUNU_INSTALL_URLvariablesfrom the same block
CRUNU_INSTALL_SHA256variablesfrom the same block
CRUNU_BINARY_SHA256variablesfrom the same block

With three commands

YAML
jobs:
  test:
    runs-on: ubuntu-latest
    permissions:
      id-token: write     # only if the token has a CI binding
      contents: read
    steps:
      - uses: actions/checkout@v4
      - name: Install crunu
        run: |
          curl -sSf "${{ vars.CRUNU_INSTALL_URL }}" -o /tmp/crunu-install.sh
          echo "${{ vars.CRUNU_INSTALL_SHA256 }}  /tmp/crunu-install.sh" | sha256sum -c -
          sh /tmp/crunu-install.sh --version "${{ vars.CRUNU_VERSION }}" --sha256 "${{ vars.CRUNU_BINARY_SHA256 }}" --user-install
      - name: Tests
        env:
          CRUNU_TOKEN: ${{ secrets.CRUNU_TOKEN }}
          CRUNU_SERVER: ${{ vars.CRUNU_SERVER }}
        run: exec crunu run --env web-app/staging -- npm test

With the setup-crunu action

Crunu includes an action, setup-crunu, in the deploy/ci/github-action/ directory of its source. It installs a pinned crunu, checks the SHA-256 of both the install script and the binary, and adds crunu to PATH for the following steps. It doesn't contact the Crunu server and doesn't publish anything.

The action isn't published in the GitHub Marketplace. Where to keep it is up to you:

  1. A copy in your repository (recommended). Copy action.yml and setup-crunu.sh into .github/actions/setup-crunu/ and use it as uses: ./.github/actions/setup-crunu. The code that gets access to your pipeline's secrets then sits next to your code and goes through the same review.
  2. A separate repository. Publish the directory as its own repository and pin it by the full commit SHA, not by a tag, because a tag can be moved.
YAML
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup-crunu
        with:
          version: ${{ vars.CRUNU_VERSION }}
          install-url: ${{ vars.CRUNU_INSTALL_URL }}
          install-sha256: ${{ vars.CRUNU_INSTALL_SHA256 }}
          sha256: ${{ vars.CRUNU_BINARY_SHA256 }}
      - name: Tests with staging variables
        env:
          CRUNU_TOKEN: ${{ secrets.CRUNU_TOKEN }}
          CRUNU_SERVER: ${{ vars.CRUNU_SERVER }}
        run: exec crunu run --env web-app/staging -- npm test
InputRequiredValue
versionyesthe crunu version, for example 6.0.0
install-urlyes, unless releases-url is setthe address of install.sh for this version
releases-urlinstead of install-urlthe release directory. Files of a version are in a subdirectory named after it
install-sha256yesSHA-256 of install.sh
sha256yesSHA-256 of the binary. One checksum for Linux amd64, or one per platform such as amd64=… arm64=… for Linux and darwin-arm64=… for macOS
bin-dirnoan absolute directory for crunu. Defaults to a temporary directory of the job

Outputs: path, the full path to crunu, and version, what crunu version reported. Input values reach the script as environment variables, never as text inside a shell command.

The action works on Linux and macOS runners, amd64 and arm64, including self-hosted ones. Windows isn't supported, because crunu is built only for Linux and macOS.

What is checked

  • The checksum of install.sh is verified before it runs. On a mismatch nothing is installed and the step fails with exit code 1.
  • install.sh downloads the binary for the runner's platform, checks its checksum, checks that it starts, and only then puts it in place.
  • crunu version must report the version you asked for.
  • Invalid inputs, such as a missing checksum, an address that isn't https://, or a relative bin-dir, fail with exit code 2 before anything is downloaded.

Where the token is visible

Put CRUNU_TOKEN in the env of the one step that runs crunu. Job-level and workflow-level variables reach every step and every process.

The command under crunu run doesn't get CRUNU_TOKEN. On Linux, crunu also closes its own environment in /proc to other processes of the same user. The shell of the step still holds the token, so start crunu with exec as the last command of the run block.

GitHub-hosted runners allow sudo without a password, and a process running as root can read any other process's environment. Against a malicious dependency in the job, the protection is a small grant: only the environment the job needs, without production.

Binding the token to a repository and branch

With a CI binding, the token works only together with a JWT that GitHub issues to the job. Add permissions: id-token: write to the job. crunu requests the JWT itself, with the server address as the audience.

A typical rule for a production token: provider GitHub, repository: kiteline/web-app, ref: refs/heads/main, environment: production, audience https://app.crunu.com. See Bind a service token to CI with OIDC for every field.