actions.yml reference

Every key .rezee/actions.yml accepts, what it does, and what happens when you leave it out.

The file lives at .rezee/actions.yml in the root of your repository and is read from the commit being built. For how a run behaves once it is created, see Pipelines.

name: CI                       # optional

on:                            # optional
  push:
    branches: [master]         # optional
    paths: ["src/**"]          # optional

jobs:                          # required
  <job-id>:
    name: Test                 # optional
    image: node:22-alpine      # optional
    tools:                     # optional
      bun: 1.2.24
    steps:                     # required
      - name: test
        run: bun test
    artifacts:                 # optional
      - coverage/**

Top level

KeyTypeDefault
namestringnone
onobjectevery branch
jobsmaprequired

name is accepted and is not shown anywhere yet - runs are identified by their commit and ref. Write it if it helps the next person reading the file; nothing depends on it.

A file with no jobs, or with an empty map, creates no run. So does a file that fails to parse - which is worth knowing, because the failure mode of a YAML typo is a push that quietly builds nothing rather than a run that goes red.

on.push

The only trigger. Tag pushes and pull requests do not start runs; a pull request's checks are the runs from the pushes to its branch.

branches

A list of glob patterns matched against the branch name, without the refs/heads/ prefix. Omitted or empty means every branch.

on:
  push:
    branches: [master, "release/*", "hotfix/**"]

paths

A list of glob patterns matched against the files this push actually changed. If nothing matches, no run is created - and the check costs one diff of file names, not a runner.

on:
  push:
    paths:
      - "apps/web/**"
      - "packages/ui/**"
      - "package.json"

When the diff cannot be taken - a branch being created, a base that no longer resolves - the run happens. The safe reading of an unknown answer is to build.

Glob syntax

The same three wildcards in branches, paths and artifacts. A pattern must match the whole string, not a piece of it.

PatternMatches
*any run of characters, stopping at /
**any run of characters, crossing /
?exactly one character, not /

So apps/aki/** is every file under the CLI, apps/*/package.json is one per app, and apps/aki/VERSION is exactly one file. There is no negation and no brace expansion.

jobs

A map, not a list. The key is the job's id, and jobs run in the order they appear in the file - there is no needs:, because there is nothing to sequence: the order is the sequence.

name

What the job is called in the UI and the CLI. Defaults to the job's key, so jobs.test with no name shows as test.

image

The container image every step in this job runs in. Any image your runner can pull. Without one, steps run in alpine:3.22.

With tools: alongside it, image becomes the base the toolchain image is built on rather than the image steps run in directly. Without image, that base is debian:trixie-slim - every toolchain ships a glibc binary, and musl is not where you want to find that out.

tools

A map of toolchain to exact version. Rezee generates an image with those versions in it, builds it once, and caches it.

tools:
  go: 1.25.6
  bun: 1.2.24
  node: 22.14.0
  gh: 2.65.0
  awscli: "2"
ToolVersion
gofull release, e.g. 1.25.6
bunrelease without the v, e.g. 1.2.24
noderelease without the v, e.g. 22.14.0
ghrelease without the v, e.g. 2.65.0
awscliv2 only. "2" resolves at image-build time

Naming a tool that is not on this list is an error that lists them, rather than a build that fails on a 404 from a generated URL.

Quote versions that look like numbers. YAML reads go: 1.25 as the number 1.25, and node: 22.10 the same way - which is not the release you meant. Rezee coerces what it is given back to a string, so this works more often than it should; write "1.25" anyway. A tool with no version at all is dropped, because latest is not something a cached image can mean.

steps

A list, in order. Each step is a name and a run, and run is a shell command - one line or a YAML block.

steps:
  - name: install
    run: bun install --frozen-lockfile
  - name: check
    run: |
      bun run lint
      bun run typecheck
      bun test

Each step is a fresh container over the same working directory. Files survive between steps; environment variables, shell functions, and anything installed into the image do not. A step whose run is empty is dropped - it would be a container started to run nothing.

The first non-zero exit ends the job. Steps after it are skipped, the job is marked failed, and the next job still runs.

artifacts

A list of glob patterns, relative to the working directory. Each pattern is collected and uploaded as its own zip, named after the pattern with the wildcards stripped - dist/** arrives as dist.zip.

artifacts:
  - dist/**
  - coverage.out
  - "**/*.junit.xml"

A pattern that matches nothing is skipped in silence. .git is always excluded. Artifacts are collected even when the job failed.

Environment

There is no env: key. A job's environment is the image's, plus this repository's secrets, which arrive as environment variables under the names you gave them. For anything else, export it in the step that needs it.

steps:
  - name: publish
    run: |
      export NODE_ENV=production
      npm publish   # NPM_TOKEN comes from the repo's secrets

A complete file

name: CI

on:
  push:
    branches: [master, "release/*"]
    paths:
      - "src/**"
      - "package.json"
      - ".rezee/actions.yml"

jobs:
  check:
    name: Lint and typecheck
    tools:
      bun: 1.2.24
    steps:
      - name: install
        run: bun install --frozen-lockfile
      - name: lint
        run: bun run lint
      - name: typecheck
        run: bun run typecheck

  test:
    name: Test
    tools:
      bun: 1.2.24
    steps:
      - name: install
        run: bun install --frozen-lockfile
      - name: test
        run: bun test --coverage
    artifacts:
      - coverage/**

  build:
    name: Build
    tools:
      go: 1.25.6
    steps:
      - name: build
        run: go build -o dist/server ./cmd/server
    artifacts:
      - dist/**

Next: Pipelines for how a run behaves, or the CLI reference for watching one from the terminal.