When to upgrade from local to CI
If you’re a solo builder or in early prototyping, local evals are sufficient. Upgrade to CI when the team or stakes grow.
Basic CI: two workflows
For most teams, two workflows cover the full loop — eval on pull requests, release on tag push.- prompt-eval.yml
- prompt-release.yml
Trigger: Pull requests with changes to This workflow delegates to
promptops/**What it does: Runs the regression gate on every PR that touches prompt specs, datasets, evaluators, or policies. Blocks merge if a regression is detected.regression-gate.yml (the reusable workflow), which:- Detects changed files in
promptops/harnesses/**,promptops/prompts/**,promptops/datasets/**, andpromptops/policies/*.yaml - Skips if no evaluable files changed
- Fetches the latest regression report from the
promptops-artifactsbranch - Evaluates the report status and posts a step summary with per-metric evidence
- Checks cost budgets against suite
budgets.cost_budgetlimits - Exits non-zero (blocking merge) if the report status is not
pass
Full CI: six workflows
For enterprise teams needing fine-grained control, apastra ships six individual workflows. Each has a distinct responsibility:regression-gate.yml, immutable-release.yml, and deliver.yml are reusable workflows (they declare workflow_call as a trigger). This means you can call them from other workflows in the same repo or from workflows in other repos, which lets a platform team standardize PromptOps across many repositories.What the regression gate does in detail
The regression gate is the most important workflow for day-to-day governance. Here is what happens step by step when a PR is opened:1
Detect changed files
The workflow uses
tj-actions/changed-files to detect whether any of the following changed:promptops/harnesses/**promptops/prompts/**promptops/datasets/**promptops/policies/*.yaml
2
Fetch the artifacts branch
When evaluable files changed, the workflow fetches
reports/regression_report.json and reports/run_manifest.json from the promptops-artifacts branch. These were written by the most recent eval run.3
Evaluate the regression report
The workflow reads the report and posts a step summary table with columns: Metric, Status, Candidate, Baseline, Delta, Message. Any failing metrics are annotated as errors in the PR.
4
Check cost budgets
If a
run_manifest.json includes a total_cost field, the workflow compares it against the budgets.cost_budget declared in each suite file. A cost overrun fails the gate.5
Block or pass
If
report.status == "pass", the workflow exits 0 (green check). Otherwise it exits 1 (red check), which fails the required status check and blocks merge on protected branches.CODEOWNERS for prompt governance
Use aCODEOWNERS file to require human review of any prompt, policy, or evaluator change:
- Any PR that modifies a file in
promptops/prompts/requires at least one approved review from@your-org/ai-qualitybefore merge. - This is enforced by GitHub branch protection rules — not just convention.
Branch protection: required status checks
Configure branch protection onmain to require the regression gate before merge:
- Go to Settings → Branches → Branch protection rules.
- Add a rule for
main. - Enable Require status checks to pass before merging.
- Add
gate(the job name fromregression-gate.yml) as a required check. - Optionally enable Require a pull request before merging and Require review from Code Owners.
main unless:
- The regression gate job passed (no regression detected, no cost budget exceeded)
- At least one CODEOWNERS reviewer approved (if CODEOWNERS is configured)
Auto-merge for passing PRs
Theauto-merge.yml workflow enables squash auto-merge for PRs that pass all required checks. It fires on pull_request events (opened, reopened, synchronized) and:
- Resolves any
PROGRESS.mdmerge conflicts automatically using a union merge strategy. - Calls
gh pr merge --auto --squashto enable auto-merge once all required checks are green.
In the apastra repo, auto-merge is scoped to PRs from
google-labs-jules and BintzGavin. For your own repo, update the if: conditions to match your autonomous agent’s login or a specific label.Artifacts branch: keeping derived data out of main
Regression reports, run manifests, promotion records, and baselines are derived data — they should not live onmain alongside your source files. Apastra uses a separate promptops-artifacts branch as an append-only store: