0d3cb498a3
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Waiting to run
Test and Publish Multi-arch Docker Image / test (push) Waiting to run
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Blocked by required conditions
CI / Shell Format Check (push) Waiting to run
CI / Check Ruby (3.4) (push) Waiting to run
CI / CI Config (push) Waiting to run
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Blocked by required conditions
CI / Build on Node ${{ matrix.node }} (push) Blocked by required conditions
CI / Style Check (push) Waiting to run
CI / Generate Assets (push) Waiting to run
CI / Check Python (3.14) (push) Waiting to run
CI / Check Python (3.9) (push) Waiting to run
CI / Build Docs (push) Waiting to run
CI / Code Scan Action (push) Waiting to run
CI / Site tests (push) Waiting to run
CI / webui tests (push) Waiting to run
CI / Run Integration Tests (push) Waiting to run
CI / Run Smoke Tests (push) Waiting to run
CI / Go Tests (push) Waiting to run
CI / Share Test (push) Waiting to run
CI / Redteam (Production API) (push) Waiting to run
CI / Redteam (Staging API) (push) Waiting to run
CI / GitHub Actions Lint (push) Waiting to run
CI / Check Ruby (3.0) (push) Waiting to run
release-please / release-please (push) Waiting to run
release-please / build (push) Blocked by required conditions
release-please / publish-npm (push) Blocked by required conditions
release-please / publish-npm-backfill (push) Waiting to run
release-please / docker (push) Blocked by required conditions
release-please / publish-code-scan-action (push) Blocked by required conditions
release-please / attest-code-scan-action (push) Blocked by required conditions
Validate Renovate Config / Validate Renovate Configuration (push) Waiting to run
5.5 KiB
5.5 KiB
AGENTS.md
Guidance for AI agents working on GitHub Actions workflows.
Workflow Security
- Keep actions SHA-pinned. Never use floating tags (
@v4) or branches (@main). - Do not expose write-capable tokens to third-party or PR-controlled code. If any step runs untrusted code (
npm install,npx <tool>, a formatter, a build tool), that step'senv:must not containGH_TOKEN,GITHUB_TOKEN,NODE_AUTH_TOKEN, or equivalent. Split the job into a tokenless do-the-work phase and a credentialed push/API phase. - Mint credentials after — not before — running PR-controlled code. In any job that both runs PR-controlled code (
npm install,npx <tool>, formatters, build tools) and mints an App token, placeactions/create-github-app-tokenin a later step gated byif:so the token does not exist in the workflow context during untrusted execution. If that isn't feasible (e.g.,googleapis/release-please-actionneeds the token at entry to open the PR), split into two jobs: a tokenless do-the-work job that produces artifacts, and a credentialed push job that consumes them — and do not run other untrusted code in the credentialed job. - Disable git hooks for every credentialed git invocation.
gitexecutes.git/hooks/*by default, and a PR can plantpre-push/pre-commithooks that run with the surrounding step's env. Usegit -c core.hooksPath=/dev/null commit …andgit -c core.hooksPath=/dev/null push …whenever a hook would otherwise run under a step that holds a credential. - Treat PR-controlled formatter/tool config as untrusted code.
.prettierrc.js,.eslint.config.js,.babelrc.js, and many others are JavaScript and will execute. Run formatters with--no-config --no-editorconfig(or equivalent) so PR-controlled config is ignored. Fornpm install, always pass--registry=https://registry.npmjs.org/explicitly so a PR-controlled.npmrccannot redirect the install, and prefer installing into an isolated directory (e.g.,$RUNNER_TEMP/tool-install) before checking out the PR tree. - Use
persist-credentials: falseonactions/checkoutwhen the workflow subsequently runs code or installs packages on a PR branch. Otherwise.git/configholds the token and any code can read it. Reattach credentials just-in-time on the specific git command with GitHub Git smart HTTP's Basic auth header, e.g. computebasic_auth="$(printf 'x-access-token:%s' "${GH_TOKEN}" | base64 | tr -d '\n')"and passgit -c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${basic_auth}" …. - Verify the commit scope before pushing. When a formatter commits on your behalf, assert
git diff-tree --no-commit-id --name-only -r HEADcontains only the expected paths before the push step runs. - Treat PR fields as untrusted input. Branch names, titles, labels, file paths, etc. may contain shell metacharacters. Assign them to env vars (e.g.,
HEAD_REF: ${{ github.event.pull_request.head.ref }}) before referencing inrun:— never interpolate${{ … }}directly into a shell command. actionlint enforces this. - Avoid
pull_request_targetunless the workflow does not check out or execute PR-controlled code. Preferpull_requestwith narrow permissions andpersist-credentials: false. - Gate privileged workflows tighter than a branch-name prefix. Require same-repo (
head.repo.full_name == github.repository), the expected bot author (user.type == 'Bot'or a specificuser.login), and only then the branch-naming convention. - Set job-level
permissions: contents: readby default; narrow GITHUB_TOKEN so write is only available via a separately-issued App token scoped to a single step. - Add
timeout-minutesto every job.
Release Workflows
- Release/publish workflows must use workflow-level
concurrencywithcancel-in-progress: falseso two pushes tomainserialize rather than race a publish. - Do not run CHANGELOG formatting inside
release-please.yml. Release-please force-pushes its PR branch when new commits land onmain, which wipes any formatter commit created inline in the release-please job. Keep release PR formatting in a separatepull_request-triggered workflow that self-heals after every force-push — and apply all the Workflow Security rules above, since the PR body/branch is user-controllable. - For npm trusted publishing, set
permissions: id-token: writeon the publish job and do not configure long-lived npm tokens. Whenactions/setup-nodeis configured withregistry-url, it writes a${NODE_AUTH_TOKEN}placeholder into.npmrcthat prevents OIDC fallthrough — setNODE_AUTH_TOKEN: ''on the publish step to neutralize it (see actions/setup-node#1440). - Pin exact versions for any tooling installed at workflow runtime (e.g.,
prettier@3.8.1, notprettier@^3.8.1;npm install -g npm@11.11.0, not@latest). Semver ranges mean a future compromised patch release can alter published artifacts. - Least-privilege every job.
publish-npmdoes not needpackages: write; only Docker jobs pushing to ghcr.io do. actions/create-github-app-tokenpermission-*inputs are a subset-request, not a grant. GitHub returns 422 if you request a permission the App installation was not already granted — even a permission release-please-action appears to use (e.g.,issues: writefor label creation). Before addingpermission-*inputs, confirm every requested permission is already granted to the App installation in the GitHub App settings; otherwise inherit the installation's granted set by omitting the inputs.