Skip to content

test(e2e): cover label-scoped budgets in the release curl matrix - #597

Merged
SantiagoDePolonia merged 2 commits into
mainfrom
test/e2e-label-budget-scenarios
Jul 26, 2026
Merged

test(e2e): cover label-scoped budgets in the release curl matrix#597
SantiagoDePolonia merged 2 commits into
mainfrom
test/e2e-label-budget-scenarios

Conversation

@SantiagoDePolonia

@SantiagoDePolonia SantiagoDePolonia commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Adds S197–S204 to the release curl matrix (196 → 204), covering budgets scoped to a request label rather than a user_path subtree, as shipped in #590.

ID Covers
S197 Admin CRUD round-trip plus validation negatives: user_path alongside subject, missing subject, unknown scope, delete-absent 404
S198 Tagging-header enforcement: first request charged, second blocked with budget_exceeded, and a different-case spelling not blocked — label matching never folds case
S199 One request carrying two labels charges both budgets
S200 A managed key's labels charge a label budget with no tagging rule configured
S201 A request matched by both a user_path and a label budget
S202 reset-one clears a label budget's spend
S203 PostgreSQL and MongoDB parity
S204 Auth gating on the admin budgets API for label scope

Two assertions brought up to their prose

While verifying these against the implementation I found two scenarios whose descriptions promised more than the code checked. Both are now asserted:

  • S199 said the block names "the exhausted label rather than the healthy one", but only checked the exhausted one was present. It now also checks the healthy label is absent.
  • S201 said the user-path budget "still has ample room", but never looked at it. It now checks that budget was charged by the same request and still has room — which is what makes it evidence that the label budget alone caused the block.

Why S200 runs on the auth-enabled gateway

On a gateway with no GOMODEL_MASTER_KEY, creating a managed key switches every endpoint — /v1/* included — to require bearer auth from then on, and managed keys have no delete endpoint (deactivate does not undo the switch, which counts stored keys rather than active ones). Registering one on the open SQLite gateway would leave it locked down for every later scenario. The auth-enabled gateway also has the exact response cache on, so both chat replies carry $QA_BUDGET_SUFFIX: a fixed reply string would be served from a prior run's cache on a rerun, bypassing usage tracking and leaving the budget permanently at zero spend.

Verification

All eight pass against the live release stack on a fresh QA_SUFFIX, so they are rerunnable and order-independent as documented:

S197 0  S198 0  S199 0  S200 0  S201 0  S202 0  S203 0  S204 0

S199 and S201 were re-run after the assertion changes and still pass.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Expanded release testing documentation with scenarios for budgets scoped to request labels.
    • Added coverage for label matching, multiple labels, managed API key labels, budget resets, validation errors, and authentication requirements.
    • Documented behavior across PostgreSQL and MongoDB backends.
  • Tests

    • Increased the release scenario matrix from 196 to 204 scenarios.
    • Added enforcement and conflict-resolution checks for label-based budgets.

Adds S197-S204 for budgets scoped to a request label rather than a
user_path subtree: admin CRUD and validation negatives, tagging-header
enforcement with verbatim case-sensitive matching, multi-label charging,
managed-key label charging, a request matched by both a user_path and a
label budget, reset-one, PostgreSQL/MongoDB parity, and auth gating.

S200 runs on the auth-enabled gateway rather than the main SQLite one:
creating a managed key on a gateway with no GOMODEL_MASTER_KEY switches
every endpoint to require bearer auth, and managed keys have no delete
endpoint, so registering one there would lock the gateway down for every
later scenario.

Two scenarios promised more than they checked, so the assertions were
brought up to the prose: S199 now checks the block names the exhausted
label and *not* the healthy one, and S201 checks the user-path budget
that matched the same request was charged and still has room — which is
what makes it evidence that the label budget alone caused the block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 26, 2026 20:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@SantiagoDePolonia, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1a746b96-d686-4231-8006-8b1a63d6d5cc

📥 Commits

Reviewing files that changed from the base of the PR and between 4a36c7f and de832b9.

📒 Files selected for processing (1)
  • tests/e2e/release-e2e-scenarios.md
📝 Walkthrough

Walkthrough

The release E2E scenario matrix now covers 204 scenarios. New scenarios S197–S204 document label-scoped budget administration, enforcement, matching, reset behavior, backend parity, and authentication gating.

Changes

Label-scoped budget E2E coverage

Layer / File(s) Summary
Release matrix and stateful coverage
tests/e2e/release-e2e-scenarios.md
Updates the scenario count and stateful-rerun notes for S197–S204, including auth-enabled gateway execution for S200.
Label budget scenario flows
tests/e2e/release-e2e-scenarios.md
Adds scenarios covering label-budget CRUD, validation, exhaustion, case-sensitive and multi-label matching, mixed budget scopes, reset-one, backend parity, and authentication gating.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Possibly related PRs

Suggested reviewers: copilot

Poem

I’m a rabbit with labels to spare,
Budgets now hop through the matrix with care.
S197 to S204 take flight,
Matching and resets land just right.
Across gateways and databases too,
The release checks multiply anew.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding label-scoped budget coverage to the release e2e matrix.
Description check ✅ Passed The description matches the template and clearly explains the change, rationale, and verification details.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/e2e-label-budget-scenarios

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/e2e/release-e2e-scenarios.md`:
- Around line 4793-4796: Update the S197–S204 preamble to distinguish scenarios
that use tagging headers from admin-only scenarios and S200’s managed-key
labels. State that only scenarios configuring tagging rules restore the tagging
rule set, while preserving the existing self-contained cleanup description for
budgets.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3df02967-70d3-48ae-a371-57be731406db

📥 Commits

Reviewing files that changed from the base of the PR and between f46b955 and 4a36c7f.

📒 Files selected for processing (1)
  • tests/e2e/release-e2e-scenarios.md

Comment thread tests/e2e/release-e2e-scenarios.md Outdated
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jul 26, 2026

Copy link
Copy Markdown

Confidence Score: 3/5

The stateful scenario cleanup needs to survive assertion failures before this PR is safe to merge.

The new scenarios create tiny daily budgets and global tagging rules but clean them up only at the end; an earlier command failure leaves spent state that causes documented same-suffix reruns to fail immediately.

Files Needing Attention: tests/e2e/release-e2e-scenarios.md

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex attempted a contract validation against the real release stack, but the stack manager reported all gateways and supporting services down, blocking startup due to the missing psql executable.
  • The real S198 runner ran with a fixed QA_SUFFIX but failed during environment setup because the .env file was missing, so budget creation or spending could not occur.
  • Because core services and credentials were unavailable (PostgreSQL, MongoDB, Redis, Docker), the cleanup-skip and same-suffix retained-state behavior could not be exercised.
  • The exact command, working directory, exit code, and stack-manager output were captured in a log, confirming the unmet dependency psql.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "test(e2e): cover label-scoped budgets in..." | Re-trigger Greptile

Comment on lines +4857 to +4861
curl -fsS -X PUT "$BASE_URL/admin/tagging/settings" \
-H 'Content-Type: application/json' -d "{\"headers\":[{\"header\":\"$TAG_HDR\"}]}" >/dev/null
curl -fsS -X PUT "$BASE_URL/admin/budgets" \
-H 'Content-Type: application/json' \
-d "{\"scope\":\"label\",\"subject\":\"$QA_LBL\",\"budget_key\":{\"period\":\"daily\"},\"amount\":$QA_BUDGET_AMOUNT}" >/dev/null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Failed scenarios retain budget state

When S198–S203 exit on any request or assertion failure, set -e skips their end-of-scenario budget and tagging cleanup. Rerunning with the documented same QA_SUFFIX then reuses an already-spent tiny daily budget, causing the first request to return 429 and making the release scenario fail repeatedly until that state is manually cleared.

Review follow-ups.

Budget spend is a SUM over usage rows, so deleting and recreating a
budget does not forget what an earlier run charged against the same
label. A scenario that exits part-way on a failed assertion skips its own
cleanup, and the same-suffix rerun this file recommends for partial
reruns would then meet an already-exhausted tiny budget and 429 on its
first request — failing for a reason unrelated to what it tests, until
someone cleared the state by hand.

reset_release_budget resets a budget right after creation, so that first
request behaves the same on the first run and the fifth. Confirmed by
leaving an exhausted budget behind and rerunning S198 with the same
suffix: exit 1 without the reset, exit 0 with it, same leftover state
both times.

The section preamble also claimed every scenario used tagging headers.
S197 and S204 are admin-only and send no model traffic, and S200 relies
on managed-key labels precisely because no tagging rule is configured, so
it now says which scenarios do what.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 26, 2026 20:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor Author

Both addressed.

Failed scenarios retain budget state (P1) — confirmed and fixed. The key detail is that deleting and recreating a budget does not clear it: spend is a SUM over usage rows, so a fresh PUT inherits whatever the previous run charged against the same label. Cleanup at the end of a scenario can't help when the scenario is what failed.

New reset_release_budget helper resets each budget right after creation, so the first request behaves the same on the first run and the fifth. Verified by reproducing the exact situation — leave an exhausted budget behind, then rerun S198 with the same --qa-suffix:

leftover budget: {"spent":0.0000019,"remaining":-0.000001899}
without the reset:  S198 rerun exit: 1
with the reset:     S198 rerun exit: 0

Identical leftover state in both runs, so the reset is doing the work.

Worth noting the same exposure exists in the pre-existing run_release_budget_enforcement helper behind S87–S89 — it also cleans up only at the end. I left it alone to keep this PR scoped, but it would want the same treatment.

Preamble overclaims — correct, and it was wrong in both directions. Rewritten to say which scenarios configure tagging headers and restore the rule set (S198, S199, S201, S203), which uses managed-key labels instead (S200), and which are admin-only with no model traffic (S197, S204).

Full set re-run after both changes:

S197 0  S198 0  S199 0  S200 0  S201 0  S202 0  S203 0  S204 0

@SantiagoDePolonia
SantiagoDePolonia merged commit 7289207 into main Jul 26, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants