Skip to content

GitHub Action

Use Betamax Terminal Previews to run tapes in CI and upload recordings, an HTML gallery, and diagnostic logs. The render job links the gallery in its summary. Add the separate joshka/betamax-action/report action to create or update one pull request comment with gallery links.

The actions support GitHub.com and Ubuntu 24.04 GitHub-hosted runners on x64 and ARM64. The examples use @v1, which tracks compatible action releases. Full-version tags such as v1.0.0 stay fixed. The action version is separate from the Betamax CLI version. See the source repository for the implementation and release history.

For an immutable dependency, replace @v1 in both workflows with the full release commit SHA. For v1.0.0, use:

# Renderer (in the read-only PR workflow):
- uses: joshka/betamax-action@bc6fa6bfb5e20dd342b588601f4e1a945661d5fe # v1.0.0
# Reporter (in the separate trusted workflow):
- uses: joshka/betamax-action/report@bc6fa6bfb5e20dd342b588601f4e1a945661d5fe # v1.0.0

Save this as .github/workflows/betamax.yml. Replace demos/**/*.tape with your tape paths and add any toolchain installation and application build steps before the render action.

name: Betamax
on: pull_request
permissions: {}
concurrency:
group: betamax-${{ github.ref }}
cancel-in-progress: true
jobs:
render:
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Install your application's toolchain and build it here.
- uses: joshka/betamax-action@v1
with:
tapes: demos/**/*.tape
formats: gif,png

The action downloads checksum-verified Betamax CLI 0.1.22 and installs fonts and ffmpeg by default. It adds output directives for the requested formats without changing your checked-in tapes. Build your application in an earlier step to keep build time outside each tape’s timeout.

Tapes execute shell commands with the render job’s privileges. Use a fresh runner with read-only permissions and no secrets throughout this job, including steps after rendering.

The tape shell starts in the directory Betamax runs from. The action runs Betamax from the checkout root, or the directory selected by working-directory, so project-relative commands work without extra setup. The action also sets BETAMAX_WORKING_DIRECTORY to that directory for tapes that change directory and need to return.

Betamax CLI 0.1.22 and earlier start the tape shell in the home directory instead. For those versions, change directory at the start of your tape:

Hide
Type@0ms "cd \"$BETAMAX_WORKING_DIRECTORY\""
Enter
Show

Then add the commands, waits, and captures for your application. See Tape files for authoring guidance.

Save this as .github/workflows/betamax-report.yml on your default branch. The trigger selects the render workflow’s name (Betamax); the workflow input selects its filename (betamax.yml). Reporting only becomes active once this workflow is on the default branch.

name: Betamax report
on:
workflow_run:
workflows: [Betamax]
types: [completed]
permissions: {}
concurrency:
group:
betamax-report-${{ github.event.workflow_run.head_repository.id }}-${{
github.event.workflow_run.head_branch }}
cancel-in-progress: false
jobs:
report:
if: github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
actions: read
pull-requests: write
steps:
- uses: joshka/betamax-action/report@v1
with:
workflow: betamax.yml

Keep reporting on a fresh runner without checking out PR code or restoring PR caches. Its write permission is used to update the comment; rendering remains in the separate read-only job. The default artifact-link mode uses GITHUB_TOKEN and requires no additional secret.

New commits update the same comment. The reporter skips closed PRs, superseded heads, and older run attempts. Fork PRs can receive comments subject to the repository’s contributor-workflow approval policy. Gallery downloads require GitHub sign-in and repository access. Artifacts expire, so use release assets or a web host for permanent documentation media.

Common render inputs are listed below. See the action reference for the full contract.

Input Default Purpose
tapes **/*.tape Newline-separated paths or globs; prefix exclusions with !.
working-directory . Base directory for tape discovery and output paths inside the checkout.
formats gif,png Comma-separated gif, png, webp, mp4, or webm.
timeout-seconds 120 Per-tape timeout, from 1 to 1800 seconds.
retention-days 14 Artifact retention, capped by repository policy.
extra-outputs Empty Newline-separated globs for checkpoints or existing media.
version 0.1.22 Betamax CLI release; separate from the action tag.
binary Empty Use a local Betamax executable instead of downloading a release.
comment-key betamax Shared identifier for render artifacts and the report comment.
variant default Unique identifier for each render job in a matrix.

For a matrix, give each render job a distinct variant and share one comment-key. One report job collects the variants after the workflow completes. Independent workflows should use different keys.

To collect screenshot checkpoints, set extra-outputs to their paths, such as target/review/**/*.png. Use a fresh output directory because matching pre-existing files are also collected. Each render invocation accepts up to 20 tapes and 20 media files, with at most 10 MiB per file and 40 MiB of media total.

To select another CLI release, set version. If it has no bundled checksum, also supply its release archive SHA-256 through sha256.

If you build Betamax itself before the action, set binary: target/debug/betamax. The path must name an executable inside working-directory with no symlink components. It overrides version and sha256; dependency installation remains enabled unless install-dependencies: false is set.

Native inline attachments are optional and best effort. They use an undocumented GitHub upload endpoint that may change; an individual upload failure leaves an artifact link and a warning.

The report action supports mode: attachments for inline media. This requires a separate repository-scoped user token, passed only to the reporter through attachment-token. Store it in an environment restricted to the trusted default branch and select that environment on the report job. Follow the attachment setup guide for token provisioning and branch rules before enabling this mode. Keep the reporter’s token input at its default so the Actions bot owns the comment.

If a tape fails or times out, the action continues with the remaining tapes and uploads available media and diagnostics before failing the step. Download the diagnostics artifact to inspect process logs. Setup or discovery errors stop rendering immediately.

Betamax also saves a failure bundle for each failed tape under target/betamax-failures in the working-directory. The action does not upload it; add an upload step with if: ${{ failure() }} after the action.

If no comment appears, check that the report workflow is on the default branch, the workflow name and filename match, and the reporter has both required permissions. If a gallery has expired, rerun the render workflow for the current PR head. For missing inline attachments, inspect report warnings and rerun rendering after correcting the issue; rerunning only the reporter does not retry an already published attempt.

Inspect the recordings as well as the job status. A successful tape can still show an application error; keep terminal assertions alongside the previews.