---
applyTo: ".github/workflows/**,.github/actions/**"
description: Rules for CI workflows
---

# GitHub Actions workflows

- Top-level `permissions: contents: read`; grant more per job only as needed (`pull-requests: write`, `id-token: write`).
- Pin third-party actions to a full commit SHA with a version comment.
- Untrusted context (`github.event.*.title`, `body`, `head_ref`) never goes inside `run:` directly. Map it to `env:` and use `"$VAR"`.
- Don't combine `pull_request_target` with checking out and running PR code.
- Use OIDC for cloud credentials; no long-lived cloud keys in secrets.
- Every job has `timeout-minutes`. PR workflows have `concurrency` with `cancel-in-progress: true`.
- Use setup actions' built-in caching before custom caches.
- Matrix builds for supported runtime versions; keep the matrix small.
- Share logic via reusable workflows (`workflow_call`) or composite actions.
- Steps have `name:`s that read well in the UI.

## Check
`actionlint` passes; for security-sensitive workflows also run `zizmor`.
