Skip to content

Cost Governance PolicyΒΆ

Subscription: GitHub Team ($4/user/mo) + Copilot Pro Plus ($39/mo) Budget: 3,000 Linux-equivalent Actions minutes/month Β· 2 GB artifact storage Policy version: 1.0 | Effective: 2026-03-14 | Owner: @mbaetiong OKR: OBJ-001 (POC: 2026-03-22 Β· Production: 2026-04-01)


1 β€” Why This Policy ExistsΒΆ

GitHub Team provides 3,000 Actions minutes per month at no extra cost for Linux runners. Minutes beyond that, non-standard runners (macOS = 10Γ—, Windows = 2Γ—, ubuntu-latest-m = 2Γ—), and GHCR data-transfer are billed directly. Without a gate, a single matrix build on a medium runner can consume 120+ effective minutes β€” 4% of the monthly budget in one run.

This policy installs a lightweight approval gate that: - Makes cost visible before a job runs - Blocks high-cost jobs until a stakeholder explicitly approves - Auto-approves low-cost jobs with zero friction - Keeps the repository within its subscription without requiring an Enterprise upgrade


2 β€” Runner Minute MultipliersΒΆ

Runner Cores Effective minutes multiplier Notes
ubuntu-latest 2 1Γ— Default β€” included in 3,000 min
ubuntu-latest-m 4 2Γ— Medium runner β€” costs 2 min per real min
ubuntu-latest-l 8 4Γ— Large runner β€” 4 min per real min
ubuntu-latest-xl 16 8Γ— XL β€” not recommended on Team plan
windows-latest 2 2Γ— Billed at 2Γ— Linux rate
macos-latest 3 10Γ— Most expensive β€” use sparingly
self-hosted any 0Γ— No Actions minutes billed

Source: GitHub Actions billing


3 β€” Cost TiersΒΆ

Effective minutes = timeout_minutes Γ— runner_multiplier Γ— matrix_job_count

GREEN  β†’ < 30 effective min, no GHCR push  β†’ Auto-approved
YELLOW β†’ 30–90 effective min               β†’ Warning posted; auto-proceeds after 60 s
RED    β†’ > 90 effective min OR GHCR push   β†’ Blocked until stakeholder checkbox ticked

Budget impact per tier (worst case, per run)ΒΆ

Tier Max effective min % of monthly budget
GREEN 30 1.0%
YELLOW 90 3.0%
RED 180+ 6.0%+

4 β€” Covered WorkflowsΒΆ

Workflow Tier Reason Added
build-preview-image.yml πŸ”΄ RED ubuntu-latest-m Γ— 30 min Γ— 2 matrix + GHCR push = 120 eff-min + transfer cost PR #3575
data-quality-suite.yml πŸ”΄ RED 3 jobs Γ— 60 min = 180 eff-min PR #3575
scheduled-archival.yml πŸ”΄ RED 3 jobs Γ— 60 min = 180 eff-min, runs on schedule PR #3575
rust_swarm_ci.yml πŸ”΄ RED 3 jobs Γ— 60 min = 180 eff-min PR #3575
embedding-index-rebuild.yml ⚠️ YELLOW 15 min, scheduled (frequent trigger risk) PR #3575

Workflows intentionally not gated (GREEN tier, < 30 effective min):

Workflow Effective min Reason not gated
deferral-language-gate.yml ~3 min Lightweight Python script
agent-auth-delegation.yml ~15 min active Most of 120 min is idle approval wait
pre-merge-validation.yml ~10 min Fast pytest subset
auto-fix-pr-check.yml ~8 min Script only

5 β€” Approval FlowΒΆ

flowchart TD
    PR["PR opened / push to branch"]
    COST["πŸ’° cost-gate job\ncost_estimator.py calculates tier"]
    GREEN["βœ… GREEN\nAuto-approved\nJob proceeds immediately"]
    YELLOW["⚠️ YELLOW\nWarning comment posted\nAuto-proceeds after 60 s"]
    RED["πŸ”΄ RED\nBlocking comment posted\nPolls PR body every 60 s"]
    CHECKBOX["Stakeholder ticks\n- [x] πŸ’° Cost Proposal Approved\nin PR description"]
    DISPATCH["Owner triggers via\nworkflow_dispatch\n(bypass)"]
    APPROVED["βœ… Gate passed\nExpensive job unblocked"]
    TIMEOUT["❌ Gate timed out\n(10 min with no approval)\nJob fails β€” re-run after ticking"]

    PR --> COST
    COST --> GREEN --> APPROVED
    COST --> YELLOW --> APPROVED
    COST --> RED
    RED -->|"checkbox detected"| APPROVED
    RED -->|"workflow_dispatch"| APPROVED
    DISPATCHER[Owner] --> DISPATCH --> APPROVED
    STAKEHOLDER[Stakeholder] --> CHECKBOX --> APPROVED
    RED -->|"10 min timeout"| TIMEOUT

    style GREEN fill:#98fb98
    style YELLOW fill:#ffd700
    style RED fill:#ff6b6b
    style APPROVED fill:#98fb98
    style TIMEOUT fill:#ff6b6b

6 β€” Stakeholder Approval InstructionsΒΆ

When the Cost Gate posts a πŸ”΄ RED comment on your PR:

  1. Read the comment β€” it shows the estimated effective minutes and cost tier reason
  2. Decide β€” is the spend justified for this PR?
  3. Approve β€” in the PR description, find the Cost Governance section and change:
    - [ ] πŸ’° Cost Proposal Approved
    
    to:
    - [x] πŸ’° Cost Proposal Approved
    
  4. Wait β€” the gate polls every 60 seconds and unblocks within ~60 s of your tick
  5. Alternative β€” trigger the workflow manually via Actions β†’ Run workflow to bypass the PR gate

7 β€” Subscription Boundaries (Do Not Cross)ΒΆ

Limit Value Action if approaching
Actions minutes 3,000 min/mo Alert at 2,500 min (83%); defer non-critical scheduled jobs
Artifact storage 2 GB Reduce retention-days to 7 for non-critical artifacts
GHCR transfer 10 GB/mo free Limit image push to main branch merges only
Copilot premium requests 1,500/mo Reserve for coding agent; use base model for completions
GHAS (CodeQL on branches) Not purchased CodeQL on feature branches = expected failure, not a bug

To increase limits without upgrading plan: - Reduce matrix job count from 3 β†’ 2 where test isolation allows - Move scheduled workflows from schedule: to workflow_dispatch: only - Set cancel-in-progress: true on all PR-triggered workflows


8 β€” Adding a New Workflow to the GateΒΆ

When adding a new workflow that may incur cost, add a cost-gate job as the first entry in jobs: using the reusable workflow:

jobs:
  cost-gate:
    name: "πŸ’° Cost Gate"
    uses: ./.github/workflows/cost-gate.yml
    with:
      workflow_name:   "My Expensive Workflow"
      runner:          "ubuntu-latest"    # adjust to actual runner
      timeout_minutes: 60                 # adjust to job timeout
      matrix_count:    2                  # set to number of parallel jobs
      pushes_to_ghcr:  false              # true if job pushes to GHCR
    permissions:
      contents:      read
      pull-requests: write

  my-expensive-job:
    needs: cost-gate                      # gate must pass first
    ...

9 β€” RoadmapΒΆ

Item OKR Task Due Status
Unit tests for cost_estimator.py OBJ-001 T-001 2026-03-20 ⬜
Branch protection: cost-gate as required check OBJ-001 T-003 2026-03-28 ⬜ (admin)
Monthly usage NDJSON logger OBJ-001 T-004 2026-03-28 ⬜
2,500-min budget alert in Self-Healing CI OBJ-001 T-005 2026-03-30 ⬜
Gate docker-build-push.yml (consistency) OBJ-001 T-006 2026-03-30 ⬜
Production sign-off @mbaetiong OBJ-001 T-007 2026-04-01 ⬜

Policy: docs/ops/COST_GOVERNANCE.md | v1.0 | 2026-03-14 Session 24 PR #3575 Subscription: GitHub Team + Copilot Pro Plus | OBJ-001