Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,11 @@ jobs:
EXPECTED_VERSION: ${{ needs.verify.outputs.version }}
EXPECTED_SHA256: ${{ needs.verify.outputs.sha256 }}
RELEASE_TAG: ${{ needs.verify.outputs.tag }}
# The first scoped publication may use the organization NPM_TOKEN.
# Once npm Trusted Publishing is configured for this workflow, OIDC is tokenless.
# npm provenance and npm Trusted Publishing both reject a self-hosted
# runner ("Unsupported GitHub Actions runner environment"), and this
# organization has no GitHub-hosted runners, so publication uses the
# organization NPM_TOKEN and ships no sigstore attestation. The release
# evidence is the verify job, the SHA-256 receipt, and the tag identity.
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GH_TOKEN: ${{ github.token }}
steps:
Expand Down Expand Up @@ -132,7 +135,7 @@ jobs:
|| node -e 'process.exit(Object.values(JSON.parse(process.argv[1])).includes(process.argv[2]) ? 0 : 1)' "$tags" "$version"; then
echo "$name@$version already published; skipping"
else
npm publish "$package" --access public --provenance
npm publish "$package" --access public
fi
- name: Create immutable GitHub release
run: |
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ All notable changes to Playproof are documented here.

### Continuous integration

- Releases publish from the self-hosted pool without npm provenance: the registry rejects a sigstore bundle built on a self-hosted runner. The tag-to-commit check, the full gate, and the SHA-256 receipt on the GitHub release are the integrity evidence.
- Every workflow job runs on the organization's self-hosted Linux pool with a per-job `uv` virtual environment and a per-job pnpm install directory; the real-emulator gates (Libbet on PyBoy, Airstriker on stable-retro, Breakout on ALE, CartPole and FrozenLake on Gymnasium) all run there.

## 0.2.0
Expand Down
11 changes: 6 additions & 5 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ Playproof publishes one verified archive to npm and attaches the same archive an
2. Enable GitHub Actions and branch protection for `main`.
3. Ensure the `@tangle-network` npm organization permits public package publication.
4. For the first publication, make the organization automation token available as the repository secret `NPM_TOKEN`.
5. After `@tangle-network/playproof` exists on npm, configure npm Trusted Publishing for:
- organization: `tangle-network`;
- repository: `playproof`;
- workflow: `publish.yml`.
6. Remove the token from the repository when OIDC publication is proven.
5. Keep the token in place. npm provenance and npm Trusted Publishing both require a GitHub-hosted runner; they reject a self-hosted one with `Unsupported GitHub Actions runner environment`. This organization publishes from its own pool, so the package ships without a sigstore attestation.
6. Configure npm Trusted Publishing only when GitHub-hosted runners are available to this repository again.

## Release gates

Expand Down Expand Up @@ -54,6 +51,10 @@ The equivalent free-ROM regression (`pnpm test:pyboy-libbet`) runs in CI on ever

The workflow is idempotent: retrying an already-published version verifies the artifact identity and skips the npm mutation.

## Release integrity without provenance

A release carries four pieces of evidence instead of a sigstore attestation: the tag resolves to the exact commit the verify job checked out, `package.json` version equals the tag, the complete gate passed on that tree, and the SHA-256 of the one archive that was built is recorded in `SHA256SUMS` on the GitHub release next to the archive itself. Compare the digest of the npm tarball with that receipt to confirm the registry holds the artifact this repository built.

## Prohibited release paths

- Do not publish from a developer laptop.
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
"claude-code"
],
"publishConfig": {
"access": "public",
"provenance": true
"access": "public"
},
"engines": {
"node": ">=20.19"
Expand Down