Uh oh!
There was an error while loading. Please reload this page.
fix(release): commit synced versions, add drift guard, Go /v2 module path - #66
Merged
Conversation
…ule path `version:sync` ran AFTER `changeset publish`, so it mutated manifests in a CI workspace nobody committed. Every git tag therefore shipped stale version constants — `go/file/v2.2.12` contains `Version = "1.1.5"` — and `cargo publish --allow-dirty` existed only to paper over that dirt. - Move the sync into the changesets `version` lifecycle (`version: pnpm run version` on the action), where the working tree IS committed into the release commit, and drop it from `ci:publish`. - Split the target list into `scripts/version-targets.mjs` so `sync-versions` writes it and the new `check-versions` guard asserts it. The guard runs in PR checks, in release, and in `check-all`; it exits 1 on drift. Verified by hand-breaking `version.go` and `go.mod` locally. - A pattern that matches nothing is now an error in both scripts. Previously it was indistinguishable from "already up to date" — the fail-open branch. - Stamp `rust/file/Cargo.lock`'s own entry alongside `Cargo.toml`, so `cargo publish` runs `--locked` with no `--allow-dirty`. - Go requires a `/vN` module suffix for major >= 2, so `go/file/v2.2.x` tags resolved nothing. Module path is now `github.com/SmooAI/file/go/file/v2`, derived from `package.json`, guarded by `version:check`, and re-asserted right before the release tag is pushed. READMEs updated; the "planned /v2" note is gone because it now exists. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
🦋 Changeset detectedLatest commit: 7dec49d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
…ld catch `rust/file/src/lib.rs` asserted `VERSION == "1.1.5"` and `python/tests/test_basic.py` asserted `__version__ == "1.1.5"` — hardcoded literals kept in step with the stale constants, so both suites went green while the repo shipped 2.2.12. A test that asserts the constant it guards locks the drift in instead of catching it. Both now compare against package.json, the single source of truth `sync-versions.mjs` copies from. That surfaced one more version-bearing file the sync never covered: `python/src/smooai_file/__init__.py` hardcodes `__version__`, so the published wheel reported 1.1.5 while its own pyproject metadata said 2.2.12. Added to `version-targets.mjs`, which makes it both synced and guarded. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
Uh oh!
There was an error while loading. Please reload this page.
brentrager added a commit
that referenced
this pull request
Aug 20, 2026
All three confirmed live in this repo, not theoretical. 1. `go test ./...` served a CACHED pass against a corrupted fixture. Go's build cache does not invalidate on a file read from outside the package directory — exactly the shape of the shared contract fixtures in spec/. Verified by zeroing every sha256 and setting headBytes to 999: still `ok (cached)`. So the Go quarter of the five-port lazy contract was proving nothing. `go:test` now passes `-count=1`; the same corruption fails immediately. 2. release.yml ran `pnpm format` in WRITE mode. Whatever it rewrote was either swept into the release commit unreviewed, or — in publish mode, where the changesets action commits nothing — left the tree dirty for `cargo publish --locked`, which would fail every release now that `--allow-dirty` is gone (dropped in #66). The step is now `format:check`, and the formatting the release genuinely needs moved into `pnpm run version`, before the action commits. Confirmed that changesets' generated CHANGELOG.md is NOT oxfmt-clean, so without that ordering `format:check` would redden every future release PR. 3. PyPI, crates.io, NuGet and the Go tag were gated on `steps.changesets.outputs.published == 'true'` — on npm having published in THAT run. npm succeeds, a later step fails, the retry finds nothing new for npm, all four skip: a GREEN run that published nothing, leaving four ports on the old version indefinitely. Each is now gated on whether its own registry carries package.json's version, so a retry ships exactly what is missing, and a final step fails the run if npm published a version the others did not. `scripts/check-registries.mjs` does the detection, waits out index propagation (reading "missing" during the lag would skip the publish this run just earned, then report success), and doubles as a manual "are we stranded?" command. Verified both directions: all five present on 2.2.14 exits 0; npm present with the Go tag missing exits 1 naming it. Checked and NOT stranded today: npm, PyPI, crates.io, both NuGet packages and the Go tag are all on 2.2.14, so the truncation fix reached every port. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
brentrager added a commit
that referenced
this pull request
Aug 20, 2026
* fix(release): three traps that report success while doing nothing All three confirmed live in this repo, not theoretical. 1. `go test ./...` served a CACHED pass against a corrupted fixture. Go's build cache does not invalidate on a file read from outside the package directory — exactly the shape of the shared contract fixtures in spec/. Verified by zeroing every sha256 and setting headBytes to 999: still `ok (cached)`. So the Go quarter of the five-port lazy contract was proving nothing. `go:test` now passes `-count=1`; the same corruption fails immediately. 2. release.yml ran `pnpm format` in WRITE mode. Whatever it rewrote was either swept into the release commit unreviewed, or — in publish mode, where the changesets action commits nothing — left the tree dirty for `cargo publish --locked`, which would fail every release now that `--allow-dirty` is gone (dropped in #66). The step is now `format:check`, and the formatting the release genuinely needs moved into `pnpm run version`, before the action commits. Confirmed that changesets' generated CHANGELOG.md is NOT oxfmt-clean, so without that ordering `format:check` would redden every future release PR. 3. PyPI, crates.io, NuGet and the Go tag were gated on `steps.changesets.outputs.published == 'true'` — on npm having published in THAT run. npm succeeds, a later step fails, the retry finds nothing new for npm, all four skip: a GREEN run that published nothing, leaving four ports on the old version indefinitely. Each is now gated on whether its own registry carries package.json's version, so a retry ships exactly what is missing, and a final step fails the run if npm published a version the others did not. `scripts/check-registries.mjs` does the detection, waits out index propagation (reading "missing" during the lag would skip the publish this run just earned, then report success), and doubles as a manual "are we stranded?" command. Verified both directions: all five present on 2.2.14 exits 0; npm present with the Go tag missing exits 1 naming it. Checked and NOT stranded today: npm, PyPI, crates.io, both NuGet packages and the Go tag are all on 2.2.14, so the truncation fix reached every port. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC * fix(release): close a fail-open in the registry check, and stop it crying wolf on NuGet Two corrections found while verifying the previous commit rather than assuming it. A botched edit had left the npm-probe result being overwritten by a later branch, so `--expect-npm` returned exit 0 on a version npm did not have. Every downstream gate is `!has && present.npm`, so a false npm reading would have switched all four publishes off and let the run go green having shipped nothing — the exact fail-open this script exists to remove, reintroduced one level up. Now exits 1 with a message naming the disagreement. Verified: exit 1 on an unpublished version, exit 0 once npm has it. NuGet is no longer asserted on. Its index takes minutes to tens of minutes to show a package it has already accepted — 2.2.19 logged "Your package was pushed" for both packages and the flat-container index still read 2.2.14 twenty minutes later — so the guard would have reddened every successful release, and a guard that cries wolf gets deleted. npm, PyPI, crates.io and the Go tag index in seconds and stay strict. NuGet keeps its own protection: `dotnet nuget push` exits non-zero on a real failure, and the per-registry gate skips it only when the version is genuinely already there. Its state is still reported, just not enforced, and the reason is in the code so it does not read as an oversight. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC * docs(release): correct two workflow comments my own changes made stale The stranding guard's comment still said "any of the other four" after NuGet was dropped from the strict set, and the PyPI step still called the wheels it cleans "pre-sync version" — which stopped being true when sync-versions moved into the `version` lifecycle. A comment that describes behaviour the code no longer has is worse than none, because the next reader trusts it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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 freeto 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.
Problem
ci:publishwaspnpm build && changeset publish && pnpm run version:sync— the sync ran after publish, mutating manifests in a CI workspace that is never committed. Consequences onmaintoday:python/pyproject.tomlrust/file/Cargo.tomlgo/file/version.godotnet/**/*.csprojgit show go/file/v2.2.12:go/file/version.go→1.1.5. Andcargo publish --allow-dirtyexisted only to tolerate that dirt.Separately, Go requires a
/vNmodule-path suffix for major ≥ 2. The module wasgithub.com/SmooAI/file/go/filewhile the tags werego/file/v2.2.x, so every tagged version resolved nothing —go getonly ever got a pseudo-version offmain.Fix
versionlifecycle.version: pnpm run versionon the action, wherepnpm run version=changeset version && node scripts/sync-versions.mjs. The action commits the working tree afterversion, so the synced manifests land in the release commit. Removed fromci:publish.scripts/version-targets.mjsis now the single list of version-bearing files.sync-versions.mjswrites it; the newscripts/check-versions.mjs(pnpm version:check) asserts it and exits 1 on drift. Wired into PR checks, release, andcheck-all. Verified by hand-breakingversion.goandgo.modlocally — red, then green after sync.rust/file/Cargo.lockis stamped alongsideCargo.toml(name-targeted, so a same-versioned dependency is never touched), socargo publishruns--lockedwith no--allow-dirty.github.com/SmooAI/file/go/file/v2, derived frompackage.json's major, guarded byversion:check, and re-asserted in the tag step immediately before an immutable tag is pushed.go build/go vet/go testpass. READMEs updated (root, go, python, rust, dotnet) and the "a proper/v2module path is planned" note removed.Judgment calls
@smooai/filenpm API is untouched and changesets versions all five ports off one number — amajorwould bump to 3.0.0 and immediately require renaming the module again to/v3. No Go consumer can currently be pinned to a tag (none resolve), so pseudo-version users onmainare the only ones affected.sync-versionsrewritesgo.mod's module suffix rather than only warning about it. A bad rewrite fails loudly:go build/go vetresolve the imports in CI.Follow-up (not in this PR)
After merge + release, mint the tag and verify resolution against the proxy:
GOFLAGS=-mod=mod go get github.com/SmooAI/file/go/file/v2@v2.2.13🤖 Generated with Claude Code
https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC