QA plan: Infracost PR comment (#32)
Story: Infracost PR comment — per-env breakdown (#32)
Capability: Cost guardrails and observability (#31)
Test scope
Section titled “Test scope”| Type | Coverage |
|---|---|
| Pipeline behavior | Infracost CI step runs on every PR that touches *.tf files (or unconditionally) and posts a cost-diff comment |
| Pipeline behavior | Cost breakdown shows QA and Prod as separate line items |
| Pipeline behavior | The comment steps do not block merge, and a missing or failed comment does not fail the PR |
| Accuracy | Adding a new AWS resource in a PR shows a non-zero delta in the Infracost comment |
| Regression guard | A step in the Terraform PR job asserts each environment’s monthly total against a $5 ceiling and fails the PR when a total exceeds it. The ceiling bounds fixed-price provisioned resources, not the bill: Infracost prices the Terraform plan, so Bedrock appears in no plan at all, and Aurora Serverless v2 prices to zero because ACU consumption is usage-based. What the ceiling guards against is adding fixed-price infrastructure, a NAT Gateway or a PrivateLink endpoint being the cases that matter here |
Entry criteria
Section titled “Entry criteria”- Infracost installed in CI (Story #29 pipeline)
infracost.ymlconfiguration file exists with per-env workspace paths
Exit criteria
Section titled “Exit criteria”- CI step runs on a test PR with a Terraform change and posts a comment containing a cost breakdown
- Comment shows QA and Prod line items separately
- Infracost comment updated (not duplicated) on subsequent pushes to the same PR
- The Terraform PR job asserts each environment’s monthly total against the $5 ceiling and fails the PR when a total exceeds it
- A Terraform change that adds a fixed-price resource above the ceiling (a NAT Gateway, a PrivateLink endpoint) makes that assertion fail; reverting it makes the assertion pass
- A failed or missing cost comment does not fail the PR; the ceiling assertion is the only step that does
- No Infracost job runs in the deploy workflow
Environments
Section titled “Environments”CI only. Infracost uses Terraform plan JSON; no live AWS resource calls.
Tooling
Section titled “Tooling”Infracost CLI, GitHub Actions.
How tests are written
Section titled “How tests are written”The comment half is observational: a PR with a known Terraform change (adding a CloudWatch alarm, say) is pushed to CI, and the reviewer confirms the Infracost comment appears and the delta is non-zero.
# Given a PR adding a new CloudWatch alarm resource# When Infracost runs in CIinfracost diff --path infra/roots/qa --format json | python3 -c "import sys, json; r=json.load(sys.stdin)delta=float(r['projects'][0]['diff']['totalMonthlyCost'])assert delta != 0, 'Expected non-zero cost delta for new alarm'print(f'Cost delta: ${delta:.4f}/mo')"# Then the delta is non-zero and printed to the CI logThe ceiling half is checked by hand this way, and the PR job makes the same comparison, failing the PR when a total exceeds the ceiling:
# When the monthly total is priced per environmentinfracost breakdown --config-file infracost.yml --format json \ | jq -r '.projects[] | "\(.name): \(.breakdown.totalMonthlyCost)"'# Then each total is at or below the $5 ceiling- Infracost API key must be stored as a GitHub Actions secret; if the key expires or is absent, the step fails silently. Add an explicit check for the env var before the Infracost invocation.
- Infracost prices only the fixed-price subset of this stack. Aurora Serverless v2 is usage-based and prices to zero, so most of what the environment costs is invisible to the tool. Document the limitation in the Infracost configuration comment, and read the ceiling as a bound on provisioned infrastructure rather than on spend. This is also why the accuracy criterion is a one-sided ceiling: a two-sided band would assert a bill figure the tool never produces.
- The comment steps are best-effort so an Infracost outage cannot block a merge, but the ceiling step is not, so an outage that takes down the assertion fails the PR. That is the intended trade: a check that cannot fail is not a gate. Distinguish the two failure modes in the step’s output so a tool outage is not mistaken for a cost regression.
- A ceiling set too far above the stack’s fixed-price total never fires. $5 sits clear of that total while falling below the cheapest thing worth catching, a PrivateLink endpoint at roughly $7.30 per AZ per month. Re-derive it from an
infracost breakdownrun againstmainwhenever the stack gains a fixed-price component. - Two PRs that each price under the ceiling can merge to a
mainthat does not, since each is priced against its own base. Requiring branches to be up to date before merge closes this; a post-merge cost job does not, because failing it reports a regression already onmain.
Capability acceptance criteria link
Section titled “Capability acceptance criteria link”Cost guardrails: PRs that increase AWS spend are visible before merge. This plan’s exit criteria cover visibility (comment posted) and the ceiling assertion, both pre-merge. Under RAG016 the comment stays informational and a cost-delta budget gate stays rejected; the ceiling is a conformance check on fixed-price provisioned resources, and it does block the merge.
© 2026 Benjamin Arunski