fix: read the wrapped compressed-payload envelope - #571
Conversation
The GitHub trigger is wrapping compressed payloads in a double-encoded envelope so that run-name - evaluated before any step exists, and so unreachable from this action - still parses instead of failing the whole workflow at startup. We detected compression by sniffing gzip magic bytes on the raw input, so the wrapped form missed the sniff, fell through to the raw branch and treated the envelope itself as the payload. That failed silently: empty github_token (checkout falls back to github.token), empty url (git remote add upstream '' fails) and has_cm_repo=false, so the cm repo is never checked out and no rules are evaluated. Exit code 0 throughout. Resolve by parsing first and switching on the value of `type`. Both compressed forms are permanent, not a migration step - Bitbucket has no run-name and keeps sending the bare form, so neither branch can be retired. `type` is matched by value rather than presence because a raw payload can carry its own `type`: Bitbucket builds it from the webhook context. Such a payload must fall through to the raw branch. A compressed-payload envelope whose data is not gzip now fails loudly rather than silently resolving to empty fields. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The stash holds the payload rather than the envelope, and its form depends on whether compression won: bare base64(gzip) if it did, raw JSON if not. Both were already covered; this pins the third case, so a stash body that is neither can never start falling through to empty fields. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A relative payloadUrl failed with a bare "TypeError: Invalid URL", which tells whoever is on call nothing. Fail with the URL and the likely cause instead. The trigger guarantees an absolute URL - payloadUrl and resolver_url are built from the same public API base, and resolver_url ships on every dispatch, so an empty base would take out result reporting for every run long before a stashed payload could expose it. This stays a diagnostic, not relative-URL support: accepting relative URLs would add resolution leniency for a state that cannot be reached quietly. Also document that the host in payloadUrl is discarded always, not only when it disagrees with the resolver, so the immunity to redirection through that field is not later "fixed" away. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Orca Security Scan Summary
| Status | Check | Issues by priority | |
|---|---|---|---|
| Infrastructure as Code | View in Orca | ||
| OSS Licenses | View in Orca | ||
| SAST | View in Orca | ||
| Secrets | View in Orca | ||
| Vulnerabilities | View in Orca |
There was a problem hiding this comment.
✨ PR Review
The PR cleanly handles the new wrapped-envelope wire format by parsing first and switching on the type value, which correctly preserves backward compatibility with Bitbucket's raw payloads that carry their own type. Logic, tests, and documentation are all consistent with the described behaviour.
1 issues detected:
🐞 Bug - "carries no gzip data" is only accurate when `data` is absent; when `data` is present but not gzip the message is factually incorrect. 🛠️
Details: The error thrown when inflateIfGzipped returns null says "carries no gzip data", but this same branch fires when data is present yet simply not valid gzip (e.g. data: 'not-gzip'). The message implies the field is absent rather than malformed, which can mislead operators diagnosing a bad envelope.
File: scripts/resolve-payload-fields.js (144-144)
🛠️ A suggested code correction is included in the review comments.
Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Review using Guidelines Learn how
There was a problem hiding this comment.
Pull request overview
This PR updates the v2 action’s client payload resolver to correctly handle the new GitHub trigger wire format where compressed payloads are wrapped in a double-encoded compressed-payload envelope, while preserving support for the existing “bare base64(gzip)” format (e.g., Bitbucket) and oversized payload references.
Changes:
- Added envelope-first parsing with
tryParsePayload()and switched payload handling based on the value oftype(reference vs wrapped compressed vs plain). - Introduced explicit failure for malformed
compressed-payloadenvelopes whosedatais not gzip. - Expanded tests to cover wrapped compressed envelopes, double-encoded reference envelopes, and additional failure/validation cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| scripts/resolve-payload-fields.js | Adds envelope-aware payload resolution and a distinct compressed-envelope mode with stricter error handling. |
| tests/resolve-payload-fields.test.ts | Adds coverage for wrapped compressed-payload and double-encoded envelope scenarios plus new failure cases. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Supersedes #570 — that PR was auto-closed when the branch was renamed to
LINBEE-27157-wrapped-compressed-envelope. Same commits, same head.Problem
The GitHub trigger is changing the wire format: compressed payloads stop being a bare base64 string and get wrapped in a double-encoded envelope, so that
run-name— evaluated before any job or step exists, and therefore unreachable from this action — parses instead of failing the whole workflow at startup.Live
@v2(2.0.258) mishandles that envelope, and does so silently. We detect compression by sniffing gzip magic bytes on the raw input, so the wrapped form misses the sniff, falls through to the raw branch, and treats the envelope itself as the payload. Measured against the proposed format:gitStream would appear to run and evaluate nothing.
Change
Parse first, then switch on the value of
type.Matching on the value rather than the presence of
typematters: a raw payload can legitimately carry its owntype, because Bitbucket builds it from the webhook context. Such a payload must fall through to the raw branch — there's a test for exactly that.Both compressed forms are permanent, not a migration step. Bitbucket has no
run-nameto protect and keeps sending the barebase64(gzip)form indefinitely, so neither branch can ever be retired. Supporting both also makes the rollout order-independent: customers pick up@v2on their own schedule, so the action and the trigger cannot be deployed in a guaranteed order.A
compressed-payloadenvelope whosedataisn't gzip now fails loudly instead of silently resolving to empty fields.The wrapped compressed tier reports
mode=compressed-enveloperather thanmode=compressed, so logs distinguish which trigger version produced a run while both formats are in flight.Verification
All seven wire shapes, plus the malformed envelope:
plainplaintype: 'push'plainbase64(gzip)— Bitbucket, permanentcompressedcompressed-payload— GitHub, newcompressed-envelopereferencereferencecompressed-payloadwith non-gzipdata19 tests pass (15 before, +4), lint and prettier clean.
Coordination
Format agreed with the trigger side (gitstream-sls-pipeline). Key names are unchanged from #566 —
oversized-payload-reference/payloadUrl/resolverToken, pluscompressed-payload/data.dataisbase64(gzip(JSON.stringify(payload))).The same change is on the two sibling PRs: #568 (v1) and #569 (v2-lite). The trigger side is holding its merge until all three refs can read the new format.
🤖 Generated with Claude Code
✨ PR Description
Purpose: Add support for reading wrapped compressed-payload envelopes and improve payload resolution logic with better error handling.
Main changes:
tryParsePayload()to safely parse JSON envelopes and replacereadStashReference()with unified payload type detectionCOMPRESSED_PAYLOADenvelope type handling that decompresses base64-encoded gzip data within parsed objectsstashUrl()with try-catch error handling and add comprehensive test coverage for envelope scenariosChangelog
✨ New Features
🔧 Improvements
Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how