Skip to content

fix(release): isolate npm publish credentials - #82

Merged
GSTJ merged 1 commit into
mainfrom
fix/publish-trust-boundary
Aug 31, 2026
Merged

fix(release): isolate npm publish credentials#82
GSTJ merged 1 commit into
mainfrom
fix/publish-trust-boundary

Conversation

@GSTJ

@GSTJ GSTJ commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Summary

Releases now validate their metadata and ancestry before publishing the verified tarball produced by the build job.

Details

  • Starts from main and rejects a release when its ref, event SHA, annotated tag, package version, changelog section, tag annotation, release body, or main ancestry disagree.
  • Switches to the release commit after validation, installs dependencies, and runs the package checks without npm credentials.
  • Builds one tarball, records its SHA-256 digest, and verifies that digest in a separate publish job.
  • Gives the legacy token only to npm publish ./release-artifact/*.tgz --ignore-scripts.
  • Runs safe-publish-latest explicitly in publish mode before building the tarball.

Testing steps

  1. Install and audit the locked dependencies.

    pnpm install --frozen-lockfile && pnpm audit --audit-level=low

    Confirm the install completes and the audit reports no known vulnerabilities.

  2. Run the repository checks.

    pnpm run lint && pnpm run format && pnpm run typecheck && pnpm run test && pnpm run build && pnpm run changelog:check && pnpm run release:check

    Confirm every command exits successfully.

  3. Validate the workflow.

    actionlint .github/workflows/npm-publish.yml

    Confirm it reports no workflow errors.

  4. Exercise the registry guard against the current package version.

    pnpm exec safe-publish-latest --force-in-publish

    Confirm it exits with code 3 because 1.3.8 is already published.

  5. Pack the project without lifecycle scripts.

    proof_root=$(mktemp -d)
    mkdir "$proof_root/release-artifact"
    npm pack --ignore-scripts --pack-destination "$proof_root/release-artifact"

    Confirm npm creates the package tarball.

  6. From the same shell, dry-run the local tarball publish.

    (cd "$proof_root" && npm publish ./release-artifact/*.tgz --access public --ignore-scripts --dry-run)

    Confirm npm reads the local package, runs no lifecycle scripts, and stops only because 1.3.8 already exists.

@github-actions

Copy link
Copy Markdown

馃帀 Congratulations on making your first pull request in '@gstj/safe-jsx'! We appreciate your contribution and will review it as soon as possible. Thank you for helping us make this project better.

@GSTJ

GSTJ commented Aug 31, 2026

Copy link
Copy Markdown
Owner Author

Local proof from 9d82c4f. The transcript covers the full suite, release rejection cases, registry guard, actionlint, package build, and local tarball dry run. The dry run executes no lifecycle scripts and reaches npm's already-published check for 1.3.8.

Local release hardening proof

@GSTJ
GSTJ merged commit b10d395 into main Aug 31, 2026
5 checks passed
@GSTJ
GSTJ deleted the fix/publish-trust-boundary branch August 31, 2026 13:46
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