ci(meridian-api): annotate envelope regression-lock PR runs (expected vs unexpected)#496
Open
dorisadams wants to merge 1 commit into
Open
ci(meridian-api): annotate envelope regression-lock PR runs (expected vs unexpected)#496dorisadams wants to merge 1 commit into
dorisadams wants to merge 1 commit into
Conversation
… vs unexpected) Follow-up to MERIDIAN-CITY#491. Adds a CI workflow that runs the four envelope regression-lock specs on every PR that touches them, classifies each failure as expected-by-design (lock firing against the pre-MERIDIAN-CITY#488 main branch) vs real regression, posts a PR comment that puts the two sets in separate sections, and fails the job only when a real regression or a jest crash is detected. ### Why Before this PR, PR MERIDIAN-CITY#491 ships envelope regression-lock specs that fail ~28 of 31 cases intentionally until PR MERIDIAN-CITY#488 (the interceptor fix for issue MERIDIAN-CITY#426) lands on main. Reviewers would mistake the 28 expected failures for test rot without this annotation layer. ### Pipeline 1. Run jest with --json output against the four envelope specs. 2. Validate the JSON is non-empty and reports >0 tests (otherwise the upstream step hard-fails before classification). 3. Classify each failing assertion via scripts/classify-envelope-results.mjs — walk testResults[*].assertionResults[*], classify based on whether fullName or any ancestorTitles match /issue\s*#\s*426\s+regression\s+lock/i. 4. Render a compact Markdown summary into $GITHUB_STEP_SUMMARY. 5. Post or update a bot-authored PR comment via scripts/ci-post-pr-comment.mjs (uses `gh api`, file-based body to avoid URL-encoding truncation of large Markdown bodies, 403-safe for fork PRs with read-only tokens). 6. Decide pass/fail via scripts/ci-fail-job.mjs — exit 0 when every failure is expected-by-design, exit 1 on real regression or crash. ### Files added - .github/workflows/envelope-lock-ci.yml — GH Actions workflow, narrowly-scoped permissions, all `run:` blocks use `|` literal scalars to avoid YAML-folding edge cases, step names with `: ` literals are quoted to escape flow-mapping traps. - scripts/classify-envelope-results.mjs — Node classifier. Keeps the first 5 lines of failureMessages (full Expected/Received diff) capped at 600 chars; surfaces `summary.crashed: true` on jest crashes. - scripts/render-envelope-summary.mjs — Markdown summary writer for the workflow run page. - scripts/ci-post-pr-comment.mjs — Posts/updates the PR comment via `gh api`. Bot-author-scoped to avoid clobbering human comments; 403-safe (fork PRs); uses temp file body to avoid URL- encoding truncation; live stderr inheritance for debugging. - scripts/ci-fail-job.mjs — Pass/fail decider. Exits 0 (green) on expected-only failures, 1 (red) on crash or unexpected failures. ### Validation - YAML parses clean (`python3 -c "import yaml; yaml.safe_load(...)"`). - All 4 scripts pass `node --check`. - Full pipeline run: 28 expected-by-design failures, 0 unexpected (sanity: this is the pre-MERIDIAN-CITY#488 main branch). - ci-fail-job.mjs sanity: - REAL (28 expected, 0 unexpected) -> exit 0 - CLEAN (0 failed) -> exit 0 - CRASHED (0 tests) -> exit 1 - UNEXPECTED (3 unexpected) -> exit 1 - ci-post-pr-comment.mjs dry-run: bodyFile created and cleaned up. Depends on MERIDIAN-CITY#488 (interceptor fix), MERIDIAN-CITY#491 (envelope regression-lock specs). Land MERIDIAN-CITY#488 first; then MERIDIAN-CITY#491; then this PR.
This was referenced Jun 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Recommended deployment order
The three PRs in this dependency chain must land in this order for the green-certification outcome to mean anything:
fix(api): harden DataResponseInterceptor for non-array responses(closes Fix DataResponseInterceptor for Non-Array Responses in meridian-api folder #426). Must land first. Fixes theapiversriontypo +Array.isArraynon-array branching that the lock specs target.test(api): envelope regression lock. Lands the four envelope regression-lock e2e specs +helpers/envelope-assert.helper.ts+test/jest-e2e.jsontweaks. Required onmainso this workflow has specs to lint.Reverse order is silently safe (the classifier handles all three pre-/mid-/post-land states) but the green-certification outcome requires all three PRs merged.
What this PR ships
.github/workflows/envelope-lock-ci.ymlissues: write+pull-requests: write. Triggers on PRs touching the four envelope specs, jest setup, jest config,package.json, the interceptor source, decorator + DTO +main.ts, and the four CI scripts themselves.scripts/classify-envelope-results.mjsfullName/ancestorTitles[]match/Issue\s*#\s*426\s+regression\s+lock/i. Keeps 5 lines offailureMessagescapped at 600 chars (full Expected/Received diff). Surfacessummary.crashed: truefor empty/invalid JSON.scripts/render-envelope-summary.mjs$GITHUB_STEP_SUMMARY— mirrors the PR-comment tables + worst-5 detail blocks.scripts/ci-post-pr-comment.mjs<!-- envelope-lock-ci -->-marked bot-authored PR comment viagh api. File-based body (avoids URL-encoding truncation on long failures). Live stderr streaming viastdio: ['ignore', 'pipe', 'inherit'].cleanupBodyFile()removes the temp file viatry { unlinkSync } catch { }in afinallyblock. Silences on fork PRs via 403 short-circuit.scripts/ci-fail-job.mjs::error::annotations on stderr for GH UI rendering.Classifier semantics
expected-by-design(≥1)unexpectedsummary.crashed: truerendered + classifier stderr capturedReviewer checklist
main..github/workflows/envelope-lock-ci.ymlpath filters include all four spec files + interceptor source + jest config + the four scripts.ENVELOPE_RESULTS_JSON/GITHUB_STEP_SUMMARY/GITHUB_TOKENenv wiring matches the workflow YAML.