Skip to content

ci(release): verify the packed file list and the provenance attestation - #226

Open
KazeeVortex wants to merge 3 commits into
wraith-protocol:developfrom
KazeeVortex:ci/verify-pack-and-provenance-210
Open

KazeeVortex wants to merge 3 commits into
wraith-protocol:developfrom
KazeeVortex:ci/verify-pack-and-provenance-210

Conversation

@KazeeVortex

Copy link
Copy Markdown

Overview

Makes the release verify what it publishes, and makes that verifiable at PR time instead of release time.

The publish workflow was already gated on the version being new, and it already requested id-token: write — but it never inspected the tarball it uploaded, never passed --provenance, and never read back whether the registry attached an attestation. Version, changelog and API report alignment were maintained by hand with no checklist and nothing enforcing them.

Three scripts now cover the gaps, and CI runs two of them on every PR.

Related Issue

Closes #210

Changes

What would be published

  • [ADD] scripts/verify-pack.mjs — runs the real pnpm pack --dry-run (nothing is written, no tarball is created) and fails if the packed list contains:

    • any path under src/, test/, tests/, docs/, examples/, scripts/, etc/, audits/, packages/, temp/, .github/, .husky/;
    • any root file that is not package.json or a file npm always includes (README, LICENSE, CHANGELOG), which catches lockfiles, tsconfig.json, api-extractor*.json, CLAUDE.md, CONTRIBUTING.md and friends;
    • and it requires package.json, a dist/*.cjs|mjs|js entry point and dist/*.d.ts declarations to be present, plus a tarball name matching the package and version.

    It reads the structured pnpm pack --dry-run --json output when available and falls back to scanning the plain output, so a pnpm release cannot silently turn the check into a no-op.

  • [MODIFY] .github/workflows/publish.yml — runs pnpm pack:check after pnpm build and before publish, so a leaking tarball never reaches the registry.

  • [MODIFY] .github/workflows/ci.yml — new release job runs pnpm build && pnpm pack:check && pnpm release:check on every PR and push, so a files change or a stale API report fails at review time.

Provenance

  • [MODIFY] .github/workflows/publish.yml
    • the publish step is now pnpm publish --access public --no-git-checks --provenance (the id-token: write permission was already declared);
    • a new post-publish step runs node scripts/verify-provenance.mjs.
  • [ADD] scripts/verify-provenance.mjs — reads the published version's registry metadata, retrying for up to ~60s while the registry settles, and fails the run if dist.attestations.provenance is absent. Publishing with the flag but never confirming the result is how a silently unattested release goes unnoticed.

Release checklist

  • [ADD] RELEASING.md — the checklist the issue asks for: semver decision, MIGRATING.md for majors, the version bump and the "is it already published" check, moving ## Upcoming entries into a released heading, API report refresh, the pack check, what the workflow does, post-publish attestation verification, and the fix-forward/deprecate/unpublish path.
  • [ADD] scripts/release-check.mjs — automates the parts that are checkable from the repository:
    • errors: no released ## [x.y.z] heading at all; neither an ## Upcoming nor a heading for the current version; an api-extractor*.json whose apiReport file is missing or is not a real api-extractor report; config that is not valid JSON;
    • warning (non-fatal): the package.json version has no changelog heading. This is reported rather than enforced because main legitimately develops ahead of the released version — right now package.json is 1.4.5 while the changelog's latest released heading is 1.5.0. Wiring it in as an error would block unrelated PRs and the publish workflow, so the checklist handles it and CI surfaces it.
  • [MODIFY] package.json — adds pack:check and release:check.

Verification Results

Syntax:  node --check on all three new scripts -> OK
         package.json re-parsed after the edit -> valid JSON

scripts/release-check.mjs, exercised against a minimal fixture (package.json +
CHANGELOG.md + api-extractor.json + etc/sdk.api.md) in a temp directory, not a
repo clone:

  PASS  changelog with an Upcoming section + a released heading, report present
        -> "release alignment OK: 1 released changelog entries, 1/1 API report(s)
           present, package @wraith-protocol/sdk@1.4.5."
           exit 0, with the expected warning that 1.4.5 has no heading

  FAIL  report file deleted
        -> error: api-extractor.json: API report etc/sdk.api.md does not exist
           exit 1

  FAIL  Upcoming section removed and version undocumented
        -> 2 errors (no Upcoming heading, missing API report), exit 1

scripts/verify-pack.mjs, exercised against a real `pnpm pack` fixture
(pnpm 11.24.0, dist/index.cjs + dist/index.d.ts + src/ + src/secret.test.ts):

  PASS  "files": ["dist"]
        -> Packed 3 entries: dist/index.cjs, dist/index.d.ts, package.json
           "pack verification passed: only intended files would be published"
           exit 0

  FAIL  "files": ["dist", "src"]
        -> Packed 5 entries, then 2 problems:
             forbidden directory in tarball: src/index.ts
             forbidden directory in tarball: src/secret.test.ts
           exit 1

Workflow diffs checked by reading the generated YAML: publish.yml now runs
release:check + pack:check before publishing, publishes with --provenance, and
runs the attestation verification afterwards; the new ci.yml `release` job adds
the two checks without touching the existing jobs.

The JSON path of the pack check was confirmed against pnpm 11; CI pins pnpm 10,
which is why the script keeps the `npm pack --ignore-scripts` JSON fallback and
the plain-text scan as well.

Not claimed: pnpm pack / pnpm build were never run against this repository (no clone), so the first real end-to-end exercise of these scripts against the SDK is this PR's own CI run — that is precisely why they are wired into CI and the release rather than left as manual steps.

Acceptance Criteria Status
Run pnpm pack --dry-run in CI ✅ pnpm pack:check (scripts/verify-pack.mjs) runs in the new CI release job and in the publish workflow before upload
Check that only intended files are published ✅ fails on any source/test/docs/script/config/API-report path, on unexpected root files, and on a missing dist entry point or declarations
Enable npm provenance and verify the generated attestation ✅ publish passes --provenance; scripts/verify-provenance.mjs reads the registry back and fails the run when no attestation is attached
Add a release checklist for version, changelog, and API report alignment ✅ RELEASING.md checklist, plus scripts/release-check.mjs enforcing changelog structure and a report per api-extractor config in CI

Closes #210

clintjeff2 and others added 2 commits June 2, 2026 00:20
…raith-protocol#45)

* perf(stellar): prefilter scans with public view tags

* test(stellar): cover legacy view-tag scanner
The publish workflow built and published when the version was new, but never
looked at what it was publishing or at what the registry stored afterwards.

  * `files` is `["dist"]`, yet nothing checked the result: a stray `files` edit or
    a new top-level directory could start shipping source, tests, API reports or
    config to every consumer unnoticed.
  * `id-token: write` was already granted, but the publish step did not pass
    `--provenance`, and nothing read back whether an attestation was attached.
  * Version, changelog and API report alignment were maintained by hand, with no
    automated check and no written checklist.

Add three scripts and wire them into CI and the release:

  * scripts/verify-pack.mjs runs the real `pnpm pack --dry-run`, rejects any
    source/test/docs/script/config/API-report path, requires the dist entry
    points and declarations, and checks the tarball name. Prefers pack --json,
    falls back to scanning the plain output.
  * scripts/verify-provenance.mjs reads the published version's registry metadata
    back and fails the run if no attestation is attached.
  * scripts/release-check.mjs enforces changelog structure and that an API report
    exists for every api-extractor config; an undocumented package version is a
    warning, not a failure, since main develops ahead of the released version.

Publish now runs release:check and pack:check before anything is uploaded, then
publishes with --provenance and verifies the attestation afterwards. A new CI job
runs both checks on every PR, so a bad `files` or a stale report fails at review
time instead of at release time. RELEASING.md documents the checklist and the
rollback path.
@drips-wave

drips-wave Bot commented Sep 25, 2026

Copy link
Copy Markdown

@KazeeVortex Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@github-actions
github-actions Bot changed the base branch from main to develop September 25, 2026 18:15
@github-actions

Copy link
Copy Markdown

Auto-retargeted this PR from main to develop. Wave PRs merge into develop; main is only for release cuts. If you meant to target main deliberately (rare), reply here and we can revert this.

@truthixify

Copy link
Copy Markdown
Contributor

Please rebase onto develop and keep this PR focused on release verification. The branch currently includes unrelated batching work and an outdated lockfile, so the checks cannot install dependencies.

Resolves merge conflicts with wraith-protocol/sdk@develop (base 8ea5dc4) so the pull request can be merged.
Auto-merged via the GitHub API.
@KazeeVortex

Copy link
Copy Markdown
Author

Merge conflict with develop resolved

Pushed merge commit d6259fa146 into this branch (develop @ 8ea5dc4924). This is a merge commit, not a force-push, so the commit history is intact.

Conflicting file(s) resolved:

  • .github/workflows/ci.yml[union]
  • docs/chains/stellar-view-tag-batching.md[add/add->base:1.00]
  • package.json[union]

The pull request is mergeable again — CI will re-run on the new head. @aratass ready for review and merge when you have a moment.

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.

[Wave 9] Add npm publish dry-run and provenance verification

3 participants