Skip to content

fix: read the wrapped compressed-payload envelope - #571

Merged
yeelali14 merged 4 commits into
developfrom
LINBEE-27157-wrapped-compressed-envelope
Aug 13, 2026
Merged

fix: read the wrapped compressed-payload envelope#571
yeelali14 merged 4 commits into
developfrom
LINBEE-27157-wrapped-compressed-envelope

Conversation

@yeelali14

@yeelali14 yeelali14 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

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:

github_token = ""      → checkout falls back to github.token (breaks private/cross-repo)
url          = ""      → git remote add upstream '' fails
has_cm_repo  = "false" → cm repo never checked out → no rules evaluated
                         no setFailed, exit 0

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 type matters: a raw payload can legitimately carry its own type, 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-name to protect and keeps sending the bare base64(gzip) form indefinitely, so neither branch can ever be retired. Supporting both also makes the rollout order-independent: customers pick up @v2 on their own schedule, so the action and the trigger cannot be deployed in a guaranteed order.

A compressed-payload envelope whose data isn't gzip now fails loudly instead of silently resolving to empty fields.

The wrapped compressed tier reports mode=compressed-envelope rather than mode=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:

shape mode
raw single-encoded plain
raw double-encoded plain
raw carrying its own type: 'push' plain
bare base64(gzip) — Bitbucket, permanent compressed
wrapped compressed-payload — GitHub, new compressed-envelope
bare reference — today's format reference
wrapped reference — GitHub, new reference
compressed-payload with non-gzip data fails loudly

19 tests pass (15 before, +4), lint and prettier clean.

Coordination

Format agreed with the trigger side (gitstream-sls-pipeline). Key names are unchanged from #566oversized-payload-reference / payloadUrl / resolverToken, plus compressed-payload / data. data is base64(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:

  • Implement tryParsePayload() to safely parse JSON envelopes and replace readStashReference() with unified payload type detection
  • Add COMPRESSED_PAYLOAD envelope type handling that decompresses base64-encoded gzip data within parsed objects
  • Enhance URL validation in stashUrl() with try-catch error handling and add comprehensive test coverage for envelope scenarios

Changelog

✨ New Features

  • Support oversized payloads via server-side stashing
  • Handle gzip-compressed payloads to reduce transmission size

🔧 Improvements

  • Simplified payload parsing with centralized resolution logic
  • Replaced repetitive JSON double-decoding with cleaner step outputs

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

yeelali14 and others added 3 commits August 13, 2026 14:21
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>

@orca-security-us orca-security-us Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Orca Security Scan Summary

Status Check Issues by priority
Passed Passed Infrastructure as Code high 0   medium 0   low 0   info 0 View in Orca
Passed Passed OSS Licenses high 0   medium 0   low 0   info 0 View in Orca
Passed Passed SAST high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Secrets high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Vulnerabilities high 0   medium 0   low 0   info 0 View in Orca

@linearb linearb Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✨ 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

Comment thread scripts/resolve-payload-fields.js
@MishaKav
MishaKav requested a lite review from Copilot August 13, 2026 13:49
@yeelali14 yeelali14 added the auto-deploy when exists in PR, will auto make release and auto deploy to prod label Aug 13, 2026

@MishaKav MishaKav left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 of type (reference vs wrapped compressed vs plain).
  • Introduced explicit failure for malformed compressed-payload envelopes whose data is 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.

@yeelali14
yeelali14 merged commit f7c4f27 into develop Aug 13, 2026
15 checks passed
@yeelali14
yeelali14 deleted the LINBEE-27157-wrapped-compressed-envelope branch August 13, 2026 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

10 min review auto-deploy when exists in PR, will auto make release and auto deploy to prod 🤖 Claude Code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants