Repository navigation
build(release): publish per-package workspace tarballs from the flake - #196
Merged
Merged
Conversation
systemfsoftware-maker
force-pushed
the
nix/workspace-tarballs
branch
from
October 6, 2026 19:07
43717bc to
ba619bd
Compare
The flake now calls pnpm-release-management's mkPnpmWorkspacePackages, which runs pnpm pack once per publishable workspace package against the pnpm store the lockfile already pins. It exposes workspace-tarballs plus one derivation per package, and throws if a package name collides with a flake output. packageManager moves to pnpm@11.27.0 to match the pnpm_11 the Nix build runs, so the packed tarballs come from the same pnpm the repo pins. A no-network `pnpm install --frozen-lockfile --offline` leaves pnpm-lock.yaml byte-identical: sha256 4a158f16200ef06494a2b21b3af0c96a672d988cc15094a098a7877ed1c7790a before and after, header included. The pnpm store that lockfile resolves to hashes to sha256-kRv6HtXsqj4Tbf1ZdMETrb8fjsVvEchyqPmcix44vtw=, the flake's fetchPnpmDeps hash, measured by blanking it and reading the mismatch. The Nix workflow rebuilds workspace-tarballs twice and requires both to be bit-for-bit identical on x86_64-linux, aarch64-linux and aarch64-darwin.
…r a registry pnpm 11's pack composed the changelog with versioning.changelog.storage left at its default, registry: for a package with a pending .changeset/changelogs/<name>@<version>.md it downloaded the previous release's tarball CHANGELOG.md from the registry. Packing a package with pending intent therefore failed without network (ERR_PNPM_META_FETCH_FAIL) and made npm the source of truth for published history. versioning.changelog.storage: repository makes pnpm's release step write the new section into packages/<dir>/CHANGELOG.md and pack that file as-is. Every publishable package now carries its CHANGELOG.md, seeded verbatim from its latest published tarball (dist.integrity verified against the download), so the repo holds the full history up to the latest release. Pack still ships only what a package's files field names, so a package that does not list CHANGELOG.md ships without one. The version-packages release of a74531e ran under registry storage and parked one section per bumped package under .changeset/changelogs, which nothing reads under repository storage. Each of the eight publishable sections moves byte-for-byte into its CHANGELOG.md under its version heading, the private stryker-e2e-core section is dropped, and no parked file remains. scripts/guards/check-changelog-sections.ts, run by guard:projects with a selftest, fails when a publishable package's CHANGELOG.md lacks exactly one section for its current version, or when a parked section exists under repository storage. Removing the 0.3.1 section from stryker-js-cli-contract, or adding a parked file, makes it exit 1 An offline `pnpm pack` in packages/stryker-js now exits 0; with storage set back to registry the same no-network command fails with ERR_PNPM_META_FETCH_FAIL
With changelog storage in the repository, pnpm packs a package's CHANGELOG.md only when its files list names it, so 16.0.1 would have shipped without the changelog 16.0.0 carried. Every publishable package now lists CHANGELOG.md; nothing else in those manifests changes
…guard check-changelog-sections lists the publishable packages through pnpm ls -r and reads versioning.changelog.storage from pnpm-workspace.yaml. A missing or misspelt storage now fails the guard with ChangelogStorageInvalid instead of switching the parked-section check off; the selftest covers both. scripts/deno.json maps @std/yaml and @std/fs/expand-glob again, which the guard has always imported and #209 trimmed from the map
… README Under storage: repository pnpm writes each release's section into the package's CHANGELOG.md and parks nothing under .changeset/changelogs/. The .changeset README and the ledger note now describe that cycle, and the note about synthesising parked changelogs is deleted with the fallback it described
…inst the source Eleven api-extractor configs rolled their declarations up over the package's own published types file, so what shipped depended on whether api:check had run, and stryker-js, which inlines its siblings' types, came out differently from one clean build to the next. The rollups now go to temp/, dist holds only tsdown output, and three clean pnpm builds give byte-identical stryker-js chunks. stryker-js's API report drops the Node_2 alias that the old rollup introduced. A new Nix CI job builds the workspace the way the flake does and checks that every flake tarball holds exactly the files pnpm pack takes from the source tree, with the same CHANGELOG.md bytes. Its sabotage step edits one tarball's CHANGELOG.md and requires the check to fail
systemfsoftware-maker
force-pushed
the
nix/workspace-tarballs
branch
from
October 7, 2026 00:16
ba619bd to
a75e156
Compare
Under storage: repository nothing is parked in .changeset/changelogs/, so the release tools must take each GitHub Release body from the package's own CHANGELOG.md. pnpm-release-management's prm/repository-changelogs does that, so release.yml and changeset-check.yml both call it, and release.jsonc drops changelogDir, which only named the parked directory
Takes main's pnpm-release-management@main callers and its Linux-only flake systems; the workspace builder now comes from pnpm-release-management main, which needs the pnpm deps hash
…macOS tarball leg pnpm-release-management main replaced versioning.strategy "pnpm" with "changesets", so the changeset check refused this config. The flake builds Linux only since #218, so the aarch64-darwin rebuild leg had no output to build
pnpm-release-management main (#14) builds the store from one fixed-output fetch per lockfile entry, keyed by its integrity, so the flake drops its single store hash and a lockfile change needs no hash edit. The input is locked at 603ecb4
# Conflicts: # release.jsonc
Contributor
There was a problem hiding this comment.
Verified: 11/11 green on ea8ad7f (CI 37672016928, Nix 37672017124), up to date with main, 0 threads, hunt clean; review predicate met after the per-entry store fix.
kiro-systemf Bot
pushed a commit
that referenced
this pull request
Oct 8, 2026
… now requires (#230) * build(release): call the reusable release workflow with the inputs and permissions it now requires Every Release run since 65155c7 is startup_failure: the caller passed tools-ref, which the reusable no longer declares, omitted the required ci-workflow input, and granted no actions: write. The reusable runs version-management and github-release-management from this repo's dev shell, which did not provide them, and bump reads the root package.json version, which was absent (VersionIntentMalformed: path=package.json). The root takes 0.0.0: it is private, outside pnpm-workspace.yaml packages, never packed into workspace-tarballs, and the changesets strategy only reads it Verdict-Semantics: unchanged * build(release): keep the changelog directory version-management writes into version-management bump writes each moved member's section to release.jsonc changelogDir (.changeset/changelogs) without creating it, and #196 left that directory empty, so git dropped it and bump failed with ChangelogUnwritable ... NotFound. The guard only reads *.md there Verdict-Semantics: unchanged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Per-package
pnpm packtarballs as flake outputs, so systemfsoftware's starter (U11b) can consume them from a pinned revision.This repo is shared with the
strykersession. Main is merged in (merge commit, no rebase). Since #209, release runs through pnpm-release-management's reusable workflows, so this PR changes no release script of its own.Approved by Kiro (outer loop):
.github/workflows/nix.ymlis the Nix build of the per-package tarballs, which is Ryan's distribution rule. The changelog guard is approved too: it checks one mechanical property of the changelogs, not their quality.Commits
build(release): publish per-package workspace tarballs from the flakeflake.nixbuilds every workspace package withpnpm-release-management'slib.mkPnpmWorkspacePackages. The flake input follows pnpm-release-managementmain, locked at603ecb4. That builder fetches the pnpm store as one fixed-output derivation per lockfile entry, keyed by the entry'sintegrity, so the flake carries no store hash and a lockfile change needs no hash edit. Outputs:packages.<system>.<package>(one.tgzeach) andworkspace-tarballs(all of them plusindex.json).packageManagermoves frompnpm@11.21.0topnpm@11.27.0, the pnpm_11 Nix provides..github/workflows/nix.ymlbuildsworkspace-tarballsand rebuilds it bit-for-bit on x86_64-linux and aarch64-linux. The flake has no darwin systems since chore(repo): drop darwin from the flake #218, so there is no macOS leg.build(release): keep changelogs in the repo and stop pack reaching for a registryversioning.changelog.storage: registry,pnpm packdownloads the previous release's tarball to prepend its CHANGELOG.md, so an offline pack failed withERR_PNPM_META_FETCH_FAIL.pnpm-workspace.yamlnow setsstorage: repository.packages/<dir>/CHANGELOG.md, copied byte-for-byte from the latest published tarball after checking it againstdist.integrity; chore(release): version packages #200's parked sections are folded in.scripts/guards/check-changelog-sections.ts(run byguard:projects, with a selftest) fails when a publishable package's CHANGELOG.md lacks exactly one## <version>section for its current version, or when a parked section exists under repository storage.build(release): ship each package's changelog in its tarball(fileslistsCHANGELOG.mdin all 17 packages).chore(release): record the changelog now shipped by stryker-js-cli-contract(the one intent the Changeset Check asked for).build(release): refuse an unknown changelog storage in the changelog guardpnpm ls -r. A missing or misspeltversioning.changelog.storagefails withChangelogStorageInvalidinstead of switching the parked-section check off.scripts/deno.jsonmaps@std/yamland@std/fs/expand-globagain; the guard always imported them, and build(release): consume the shared pnpm-release-management toolchain #209 trimmed them from the map.docs(release): describe repository changelog storage in the changeset README(the.changesetREADME and the ledger note; the note on synthesising parked changelogs is deleted).build(release): keep api-extractor out of dist and check tarballs against the sourceapi:checkhad run, and on timing in a turbo build: three clean builds gave three different stryker-js type chunks. Rollups now go totemp/<package>.d.ts, anddistholds only tsdown output. stryker-js's API report drops theNode_2alias the old rollup introduced.nix.ymljob builds the workspace the way the flake does and runsscripts/guards/check-tarball-contents.sh. The script requires every flake tarball to hold exactly the filespnpm packtakes from the source tree, with byte-identicalCHANGELOG.md. Its sabotage step edits one tarball's CHANGELOG.md and requires the check to fail.chore(release): fold the 17.0.1 and 17.0.2 sections into stryker-js's changelog(chore(release): version packages #204 and chore(release): version packages #208 parked them under registry storage).ci(release): pin the release toolchain that reads package changelogs, now superseded by the merge of main.release.ymlandchangeset-check.ymlcall pnpm-release-management's reusable workflows at@mainwithtools-ref: main. Main's release step (pnpm-release-management fix(repo): generate release notes in the publish job before asserting them #22) asks pnpm for the changelog storage mode and, underrepository, takes the## <version>section of the package's own CHANGELOG.md.release.jsoncdropschangelogDir.chore(repo): merge main into nix/workspace-tarballs: takes main's Linux-only flake systems and its@mainworkflow callers.build(release): version through the changesets strategy and drop the macOS tarball legversioning.strategy: "pnpm"with"changesets", so the changeset check refusedrelease.jsonc. It now sets"changesets": the changesets libraries version each package from the pending intents.nix.ymlloses its aarch64-darwin leg.build(release): take the pnpm store from one fetch per lockfile entry: re-locks pnpm-release-management to603ecb4(its build(deps): bump @effect/vitest from 4.0.0-rc.112 to 4.0.0-rc.115 #14) and removes the single store hash.Proof (local, on
a75e156unless noted)pnpm build --forceruns give byte-identical stryker-js.d.mtschunks, andpnpm buildexits 0.2e8ef58:check-tarball-contents.shpasses on all 17 flake tarballs. Both of the job's steps, run from the workflow text, pass: the real check, and the sabotage, which is refused withtarball CHANGELOG.md differs.workspace-tarballsrebuilds bit-for-bit (nix build --rebuild).2e8ef58, in a scratch worktree that was never pushed:pnpm add -w -D is-number@7.0.0 --lockfile-onlychangespnpm-lock.yaml, andworkspace-tarballsstill builds with no flake edit. The same change ond260683, which still had the single store hash, fails with a fixed-output hash mismatch.storage: repostioryexits 1 naming the bad value.pnpm guard:projects,pnpm test:scripts, the changeset check, actionlint and shellcheck exit 0.d260683:pnpm check:ciexits 0. The changeset check from pnpm-release-management main exits 0 and lists all 17 changed packages, each with an intent.check-tarball-contents.shpasses on all 17 flake tarballs.check-changelog-sectionspasses on all 17 packages, each with one section for its version. All 11 CI checks are green.Open: a throwaway
version bumpfrom pnpm-release-management main fails withVersionIntentMalformed: path=package.json, because the rootpackage.jsonhas noversion. Open pnpm-release-management #28 covers that. Main already fails earlier, because itsrelease.jsoncstill sets"pnpm". Until #28 lands, the next release here stops at the bump step.