Skip to content

CI recipes

All recipes run actup from the repo via Bun. They rely on the exit codes: 0 ok, 1 actionable, 2 unresolvable, 3 network/auth/rate-limit.

PR check gate

Fail a pull request when any action ref is outdated, floating or unresolvable. The non-zero exit code (1, 2 or 3) fails the step automatically.

yaml
name: actions-up-to-date
on:
  pull_request:

jobs:
  actup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: 1.3.13
      - run: bun install --frozen-lockfile
      - name: Check action versions
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: bun run actup check

To allow outdated refs but still fail on unresolvable/network problems, gate on the exact code:

yaml
- name: Check (warn on outdated, fail on errors)
  env:
    GITHUB_TOKEN: ${{ github.token }}
  run: |
    bun run actup check || code=$?
    if [ "${code:-0}" -ge 2 ]; then exit "$code"; fi

SARIF upload to code scanning

Emit SARIF and upload it so findings appear in the Security tab. actup returns a non-zero exit for findings, so capture the code and still upload.

yaml
name: actup-sarif
on:
  push:
  schedule:
    - cron: "0 6 * * 1"

permissions:
  contents: read
  security-events: write

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: 1.3.13
      - run: bun install --frozen-lockfile
      - name: Run actup (SARIF)
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: bun run actup check --format sarif > actup.sarif || true
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: actup.sarif

The SARIF document uses schema sarif-2.1.0, tool name actup, rule ids actup/<finding-kind>, and maps severities to error / warning / note. up to date refs are excluded from SARIF output.

::warning annotations

--github-annotations prepends GitHub workflow-command lines (::warning file=…,line=…,col=…::… and ::error …) before the chosen format, so annotations appear inline on the PR diff.

yaml
- name: Annotate outdated actions
  env:
    GITHUB_TOKEN: ${{ github.token }}
  run: bun run actup check --github-annotations

Combine with --format to also produce machine output:

yaml
- run: bun run actup check --github-annotations --format json

up to date and pinned refs are not annotated.

Scheduled update / pin job

Run update (or pin) on a schedule and open a PR with the changes. The update command rewrites files in place; commit and push them. After a successful write actup exits 0, so the step does not fail the job.

yaml
name: actup-update
on:
  schedule:
    - cron: "0 4 * * 1"
  workflow_dispatch:

permissions:
  contents: write
  pull-requests: write

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: 1.3.13
      - run: bun install --frozen-lockfile
      - name: Update action refs
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: bun run actup update
      - name: Open PR
        uses: peter-evans/create-pull-request@v6
        with:
          commit-message: "ci: bump GitHub Actions refs"
          title: "ci: bump GitHub Actions refs"
          branch: actup/update

For supply-chain hardening, swap update for pin to rewrite every ref to an immutable SHA with a recoverable # <tag> comment:

yaml
- run: bun run actup pin

Notes

  • Always provide a token (GITHUB_TOKEN: ${{ github.token }}); the default GitHub GraphQL API mode requires one. Auth/rate-limit failures exit 3.
  • Use --offline only when a warm cache is restored (e.g. via actions/cache on ~/.cache/actup); a cache miss offline is reported as unresolvable (exit 2).