Skip to main content

Documentation Index

Fetch the complete documentation index at: https://bintzgavin-apastra-14.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Apastra ships 13 GitHub Actions workflows in .github/workflows/. They cover eval gating, releases, promotion, delivery, governance, and operational scanning.
You do not need all 13 workflows. Start with the two basic CI workflows (prompt-eval.yml and prompt-release.yml) and add the full enterprise set when you need fine-grained control.

Basic CI (start here)

These two workflows give you regression gating and immutable releases with minimal setup.

prompt-eval.yml

Runs on every pull request that touches promptops/**. Evaluates changed prompts and blocks merge if a regression is detected. Trigger:
on:
  pull_request:
    paths:
      - 'promptops/**'
What it does: delegates to regression-gate.yml via workflow_call.
jobs:
  eval:
    uses: ./.github/workflows/regression-gate.yml
Branch protection setup: add eval (or the check name from regression-gate.yml) as a required status check on your main branch. PRs that fail the gate cannot merge.

prompt-release.yml

Runs when any tag is pushed. Creates an immutable GitHub Release with SLSA provenance. Trigger:
on:
  push:
    tags:
      - '*'
What it does: delegates to immutable-release.yml via workflow_call.
jobs:
  release:
    uses: ./.github/workflows/immutable-release.yml

Full CI (enterprise)

Use these when you need separate regression gating, manual promotion, governed delivery, auto-merge, and human approval recording.

regression-gate.yml

Dedicated regression gating job. Can be called directly or via workflow_call from prompt-eval.yml. Triggers:
on:
  pull_request:
    branches: [main]
  workflow_call:
Key job steps:
  1. Checkout the repository with fetch-depth: 2.
  2. Detect changed files — checks promptops/harnesses/**, promptops/prompts/**, promptops/datasets/**, and promptops/policies/*.yaml.
  3. Skip if no evaluable changes — exits cleanly when only non-promptops files changed.
  4. Fetch artifacts branch — checks out regression_report.json and run_manifest.json from origin/promptops-artifacts.
  5. Check regression report status — reads reports/regression_report.json:
    • If the file is missing, fails with ::error::Regression report missing. Merges are blocked.
    • Prints a summary table of evidence rows (metric, status, candidate, baseline, delta, message) to $GITHUB_STEP_SUMMARY.
    • Emits ::error annotations for any failing metrics.
    • Reads status field: exits 0 on pass, exits 1 on any other value.
  6. Check cost budget — if run_manifest.json contains total_cost, validates it against budgets.cost_budget in every suite file.
This workflow reads from origin/promptops-artifacts. Your harness must write the regression report to that branch before the gate runs. If you use an agent-based harness, the agent writes reports/regression_report.json to the artifacts branch as part of the eval workflow.

promote.yml

Creates an append-only promotion record binding an approved digest to a delivery channel, then triggers deliver.yml. Triggers:
on:
  workflow_dispatch:
    inputs:
      digest:         # content digest of the promoted package
      channel:        # e.g., prod, staging
      evidence_refs:  # comma-separated URIs to regression reports
  release:
    types: [published]
Key job steps (record-promotion):
  1. Checkout the promptops-artifacts branch.
  2. Enforce approval — reads approvals/*.json from the artifacts branch and verifies a matching approval record (matching revision_ref and decision == "approved" and checks_passed == true) exists. Fails if no approval is found.
  3. Generate promotion record — writes a JSON file to promotions/<timestamp>-<id>.json on the artifacts branch:
    {
      "id": "...",
      "timestamp": "...",
      "digest": "...",
      "channel": "prod",
      "approver": "...",
      "evidence_refs": ["..."]
    }
    
  4. Commit and push the promotion record to promptops-artifacts.
  5. Trigger deliver.yml — passes the promotion record path as an input.
When triggered by a release event, the digest is set to release-tag:<tag_name> and the channel is set to release.

deliver.yml

Syncs an approved version to delivery targets. Called by promote.yml via workflow_call. Trigger: workflow_call only (not triggered directly). Input: promotion_record_path — path to the promotion record on the artifacts branch. Key job steps:
  1. Checkout the main branch.
  2. Fetch promotion record from origin/promptops-artifacts.
  3. Sync to targets — reads channel and digest from the promotion record. Iterates over all promptops/delivery/*.yaml files and finds targets whose channel matches. For each match, reads type and repo and executes the appropriate sync.
Supported target types (from delivery-target.schema.json): github_pr, oci_registry.

immutable-release.yml

Creates a GitHub Release with a content-addressed tarball and SLSA build provenance attestation. Triggers:
on:
  push:
    tags:
      - '*'
  workflow_call:
Key job steps:
  1. Checkout the repository.
  2. Package prompts — creates promptops.tar.gz from the promptops/ directory and computes its SHA-256 digest.
  3. Attest build provenance — uses actions/attest-build-provenance to attach a SLSA provenance attestation to the tarball.
  4. Create GitHub Release — uses gh release create with the tag name, attaches promptops.tar.gz, and includes the digest in the release notes.
Required permissions: contents: write, id-token: write, attestations: write, artifact-metadata: write.

auto-merge.yml

Automatically enables squash merge for PRs opened by authorized users (Jules and the repo owner). Resolves docs/PROGRESS.md merge conflicts using a union merge strategy. Trigger:
on:
  pull_request:
    types: [opened, reopened, synchronize]
Condition: only runs for PRs from google-labs-jules, google-labs-jules[bot], or BintzGavin. Key job steps (resolve-progress-conflicts):
  1. Checks out the PR branch.
  2. Fetches the base branch.
  3. Attempts a merge; if docs/PROGRESS.md has conflicts, resolves them by concatenating both versions (union merge).
  4. Pushes the resolved branch.
Key job steps (enable-auto-merge):
  1. Marks the PR as ready for review.
  2. Calls gh pr merge --auto --squash with a retry loop (5 attempts, backoff) to handle rate limits.

record-approval.yml

Records a human approval or rejection decision as an append-only JSON file on the promptops-artifacts branch. Trigger:
on:
  workflow_dispatch:
    inputs:
      revision_ref:   # digest or ID of the revision/package
      decision:       # approved | rejected | abstained
Key job steps:
  1. Checkout the promptops-artifacts branch.
  2. Generate approval state record — writes to approvals/<timestamp>-<id>.json:
    {
      "revision_ref": "...",
      "checks_passed": true,
      "decision": "approved",
      "human_review": {
        "reviewer": "...",
        "timestamp": "..."
      }
    }
    
  3. Commit and push the approval record to promptops-artifacts.
The promote.yml workflow reads these records to enforce approval before creating a promotion record.

Operational workflows

schema-validation.yml

Validates changed prompt and dataset files against JSON schemas on every pull request. Trigger:
on:
  pull_request:
    paths:
      - 'promptops/prompts/**'
      - 'promptops/datasets/**'
Key job steps:
  1. Detect changed files using tj-actions/changed-files.
  2. Install dependenciesnpm install -g ajv-formats ajv-cli.
  3. Validate changed files:
    • Prompt files: runs promptops/validators/validate-prompt-spec.sh <file>.
    • Dataset files: runs promptops/validators/validate-dataset.sh <manifest> <cases> for each dataset directory with both a manifest and a cases.jsonl. Skips incomplete datasets with a warning.
    • Emits ::error annotations for any validation failures and exits with code 1.

canary-drift-detection.yml

Runs canary suites on a schedule to detect post-ship quality erosion when model providers update silently. Triggers:
on:
  schedule:
    - cron: '0 * * * *'   # every hour
  workflow_dispatch:
Key job steps:
  1. Checkout the repository.
  2. Run the canary suite harness.
  3. Parse reports/drift_report.json.
  4. Check the drift_detected field.
  5. Trigger an alert and auto-rollback if drift_detected == true.
The canary harness integration is a placeholder in the current implementation. You supply your own harness command in step 2.

community-reporting.yml

Triages community moderation reports submitted as GitHub Issues with the moderation-report label. Trigger:
on:
  issues:
    types: [opened]
Condition: only runs if the issue has the moderation-report label. Key job steps:
  1. Add acknowledgment comment — posts a standard acknowledgment to the issue.
  2. Assign to governance admins — adds apastra and governance-admins as assignees.

moderation-scan.yml

Scans changed prompt and dataset files for blocked keywords on every pull request. Trigger:
on:
  pull_request:
    paths:
      - 'promptops/prompts/**'
      - 'promptops/datasets/**'
Key job steps:
  1. Runs a grep scan for blocked keywords across promptops/prompts/ and promptops/datasets/.
  2. Exits 1 (failing the check) if any blocked keywords are found.
Replace the placeholder keyword pattern with your organization’s content policy patterns.

secret-scan.yml

Detects secrets accidentally embedded in prompt files or datasets. Trigger:
on:
  pull_request:
    paths:
      - 'promptops/prompts/**'
      - 'promptops/datasets/**'
Key job steps:
  1. Scans all prompt and dataset files for patterns matching api_key:, secret:, password:, or token:.
  2. Exits 1 if any matches are found.
This is a lightweight pattern scan, not a full secret-scanning solution. For production use, consider adding a dedicated secret scanning tool (e.g., truffleHog, GitHub’s built-in secret scanning, or gitleaks) alongside this workflow.

Branch protection setup

To enforce required status checks on main:
1

Go to branch protection settings

In your GitHub repo, go to Settings → Branches → Add branch protection rule for main.
2

Enable required status checks

Check Require status checks to pass before merging. Search for and add the check names you want to require.For basic CI, add:
  • eval / gate (from regression-gate.yml)
  • validate-schemas / validate-schemas (from schema-validation.yml)
For full CI, also add:
  • scan / scan-secrets (from secret-scan.yml)
  • scan / scan (from moderation-scan.yml)
3

Enable required reviews

Optionally require at least one approving review from a CODEOWNERS reviewer before merge.
4

Set up CODEOWNERS

Add a CODEOWNERS file to define who must review which parts of the repo:
promptops/prompts/   @your-org/prompt-authors
promptops/policies/  @your-org/platform-team
.github/workflows/   @your-org/platform-team

Workflow summary table

WorkflowTriggerGroup
prompt-eval.ymlPR touching promptops/**Basic CI
prompt-release.ymlTag pushBasic CI
regression-gate.ymlPR to main / workflow_callFull CI
promote.ymlManual dispatch / release publishedFull CI
deliver.ymlworkflow_call from promote.ymlFull CI
immutable-release.ymlTag push / workflow_callFull CI
auto-merge.ymlPR opened/updatedFull CI
record-approval.ymlManual dispatchFull CI
schema-validation.ymlPR touching prompts or datasetsOperational
canary-drift-detection.ymlHourly schedule / manual dispatchOperational
community-reporting.ymlIssue opened with moderation-report labelOperational
moderation-scan.ymlPR touching prompts or datasetsOperational
secret-scan.ymlPR touching prompts or datasetsOperational