Playbook — PR-Mode CI Economics (consumer cost guidance + reference workflow)
Purpose: pr-mode autonomy_level=auto_merge/autonomous + a GitHub merge queue multiplies CI runs (each PR runs CI, then each merge_group runs it again), so on a free private repo with a slow suite the 2000-min/mo Actions budget burns fast. This playbook gives the cost model, the fast-gate / full-suite split that keeps the autonomous loop affordable, and a copy-paste consumer CI workflow.
Read when: Enabling pr-mode auto-merge on a consumer repo, or a consumer's Actions minutes are running out.
Skip when: Working in coding-os itself (trunk, nightly-only CI — see [github-actions-cost note]) or any repo not on the autonomous loop.
Nav: Docs Index · pairs with pr-workflow.md §11 (one-time setup) and §12 (live validation).
1. The cost model (know these before arming auto-merge)
- Runner OS multiplier (billed minutes = wall-minutes × multiplier): Linux ×1, Windows ×2, macOS ×10. Keep the required check Linux-only — a macOS leg on every PR + every merge-group is the fastest way to exhaust the budget.
- Free Actions minutes: private repo Free plan 2000 min/mo (Pro 3000); public repo = UNLIMITED; self-hosted runner = UNLIMITED (self-hosted minutes are never billed against the quota).
- Merge-queue multiplication: with a merge queue, a single change can trigger CI on the PR and on one or more
merge_groupbatches. Budget for ~2× the naive per-PR cost, more under heavy concurrency. - Quota-exhausted failure mode: once minutes run out, workflows simply don't start —
cos pr statusreadspendingforever andcos pr preflightshould surface "no runner / quota". An autonomous loop then stalls silently; the fast-gate split below is what keeps you under the cap.
2. The fast-gate / full-suite split (the core economy)
Make the required check fast — only it gates merge, so only it runs on every PR + merge_group:
- Fast required check (gates merge, runs per-PR + per-merge_group): lint + targeted tests only. "Targeted tests" = the unit/contract layer that runs in a few minutes — explicitly NOT the slow/integration/e2e suite. This is the single status check the integration-branch ruleset requires.
- Full suite (does NOT gate merge): run on a nightly
schedulecron (and optionally manualworkflow_dispatch). Catches the slow/integration regressions off the hot path, on one run per day instead of one per PR.
A red nightly opens a normal issue/PR to heal; it never blocks the autonomous merge loop.
3. Reference consumer CI workflow (copy to .github/workflows/ci.yml)
Linux-only, fast required check on pull_request + merge_group, full suite on a nightly cron. Replace the run: lines with the repo's own commands (the repo's validate command is the SSOT — pr-workflow.md §4 step 2). This is a reference, not an auto-scaffolded file: pr-mode is opt-in, so the consumer copies and adapts it.
name: ci
on:
pull_request:
branches: [main]
merge_group: # required so the merge queue's batched check reports status
schedule:
- cron: "0 4 * * *" # nightly full suite (UTC) — does NOT gate merge
workflow_dispatch:
jobs:
# FAST required check — the ONLY job the integration ruleset requires.
# Keep it lint + targeted tests so every PR + merge_group stays cheap.
fast-check:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest # Linux ×1 — never macOS (×10) on the hot path
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- run: make lint # replace with the repo's lint
- run: make test-targeted # replace with the repo's fast/unit suite
# FULL suite — nightly only, never gates merge.
full-suite:
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- run: make test # the slow/integration/e2e suite
Then in the integration-branch ruleset (pr-workflow.md §11) require only the fast-check job as the status check, and enable the merge queue. The nightly full-suite is intentionally not a required check.
4. Decision guidance (the consumer's call — EXTERNAL)
| Situation | Recommended runner / plan |
|---|---|
| Open-source / public repo | Public repo → Actions unlimited; use GitHub-hosted Linux freely. |
| Private repo, light suite | Free 2000 min/mo is plenty with the fast-gate split; Linux-only. |
| Private repo, heavy suite / many agents | Self-hosted Linux runner (unlimited) — the only way the autonomous loop scales without a minute cap. |
| Any | Never put macOS (×10) or Windows (×2) on the required check; reserve them for nightly/matrix if truly needed. |
The actual billing tier and runner choice is the consumer's decision — this playbook only documents the economics so that choice is informed.
See also
- pr-workflow.md — the pr-mode contract (§11 ruleset setup, §12 live validation).
- ADR-0013 — why pr-mode is consumer-only.