Skip to content

fix(ci): announce Skill releases without free-form text and verify the result - #13

Merged
yunze7373 merged 1 commit into
mainfrom
fix/skill-release-announcement-hardening
Aug 12, 2026
Merged

fix(ci): announce Skill releases without free-form text and verify the result#13
yunze7373 merged 1 commit into
mainfrom
fix/skill-release-announcement-hardening

Conversation

@yunze7373

Copy link
Copy Markdown
Member

Problem

The Skill release job forwarded the entire GitHub release object to the package
receiver, so whether a release could be announced depended on how its notes were
worded. For skill-v1.1.7 the notes contained a shell pipeline in a code span,
the receiver's edge protection answered 403, and both announcement paths failed:

15:37:19  release/published  403   <- skill-v1.1.7
12:00:06  release/published  202   <- skill-v1.1.6

Two things then made a transient rejection into a lasting one. The package cache
has no expiry, so the endpoint kept serving the previous Skill indefinitely with
no signal that anything was wrong. And the step trusted its own 2xx instead of
checking the outcome, so nothing failed to reveal it.

Changes

  • Announce only the fields the receiver reads: action, release.tag_name, and each asset's name and browser_download_url. Release notes and other free-form text no longer enter the request body. The receiver needs no change.
  • Report a 4xx immediately rather than retrying it. --retry-all-errors previously retried the 403 four times and then reported an opaque failure.
  • Add a gate that polls GET /v1/skill/package?format=... for both formats until the 302 redirect target ends in the released tag, failing the job on timeout. The redirect already carries the served version, so this costs one request per poll and downloads nothing.

Verification

Measured against the live endpoint, same headers, same deliberately invalid signature:

Request body Result
Whole release object, notes containing a shell pipeline 403 blocked at the edge
Minimal payload built from that same release 401 reaches the application
Minimal payload built from the real release 401 reaches the application

401 is the receiver rejecting the signature, which is the expected answer for
an unsigned probe and proves the request is no longer stopped before it arrives.

  • Payload builder run against the real skill-v1.1.7 release JSON: 5730 bytes in, 353 bytes out, containing only the three expected fields.
  • Redirect matching checked against captured headers for lowercase and uppercase Location, a stale tag, a response with no Location, and a similar-prefix tag (skill-v11.1.7 must not satisfy skill-v1.1.7).
  • Both new shell blocks extracted from the parsed YAML and checked with bash -n; the workflow parses as YAML with 7 steps.
  • npm run lint clean, npm test 140/140, npm pack --dry-run unchanged at 71 files.
  • The three new assertions were confirmed to fail when the minimal payload is reverted to forwarding the whole release object.

Not covered here

The receiver's cache still has no expiry, so it cannot converge on its own if
every announcement fails; this gate makes that loud rather than silent. The
repository also has a native GitHub webhook for release events whose payload
is generated by GitHub and therefore still carries release notes.

…e result

The Skill release job forwarded the whole GitHub release object to the
package receiver, so the announcement depended on how the release notes were
worded. A body containing a shell pipeline was rejected by the receiver's
edge protection with HTTP 403, and because the package cache has no expiry
of its own, the previous Skill stayed published with nothing failing to show
it. The step also retried that 403 four times and then reported an opaque
failure.

Announce only the fields the receiver reads (action, release.tag_name, and
each asset's name and browser_download_url), report a 4xx immediately
instead of retrying it, and add a gate that polls the public endpoint until
it actually serves the released tag before the job is allowed to succeed.
@yunze7373
yunze7373 merged commit 37dc01e into main Aug 12, 2026
1 check 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.

1 participant