fix(release): rt builds and runs on Windows (#1502) #1505
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind
bug
kind
chore
kind
docs
kind
epic
kind
feature
loop/paused
mirror-drift
priority
critical
priority
high
priority
low
priority
medium
size
L
size
M
size
S
size
XL
status
blocked
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
frankenbit/release-toolkit!1505
Loading…
Reference in a new issue
No description provided.
Delete branch "claude/1502-windows-build"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #1502
rtnow builds and runs natively on Windows. The cause was one Unix-only syscall in the cut lock. Once the build works, one Windows runtime bug (register-check) and one misleading refusal (post_bump_hooks) show up, and this PR fixes both. Linux behaviour is byte-identical.Commits
8e2cf58fix(release)tryLockExclusive/unlockFile:lock_unix.go(//go:build !windows, the identicalflock(LOCK_EX|LOCK_NB)) +lock_windows.go(LockFileEx). Cross-process and killed-holder tests. Fragment.6aef15bfix(register)scanOneFileconverts the walked path once withfilepath.ToSlashfor the self-exclusion key, the allow-list subject and the printed hit.0ac9790fix(prep)post_bump_hookis refused by name with the real cause, before any hook runs. Docs line in integration.md.ca66a11testrtbehaviour change. Details in the commit message.Measured
Windows: Go 1.27.1 windows/amd64, Git 2.55.0.windows.3, run from Git Bash. Linux:
golang:1.25container on a real clone of the branch.55a12b9ca66a11go build ./cmd/rt, Windowsundefined: syscall.Flock(5 errors)go run ./cmd/rt fragment-check changelog.druns nativelyrt register-checkon this repo, WindowsOK: 0 register-drift hits, exit 0go vet ./... && go test -count=1 ./..., Windowscmd/rtcannot compilegofmt -lclean under Go 1.25Linux unchanged. The review pass built
rtbefore and after, at the change's first base02fae6a, and compared stdout, stderr and exit code. All three were byte-identical for:--helpregister-checkon the repo, on a fixture walk, and on explicit files including a./prefixprep --dry-runwith a non-executable hook, a hook that exits 3, and a succeeding hookfragment-checkOn the rebase to
55a12b9, onlydocs/integration.mdmet upstream changes, and that was context, not conflict.Mutation evidence (AGENTS.md section 8 Axis B). Each mutant was applied, then restored:
TestAcquireLock_anotherProcessHoldsItandTestNewCutter_concurrentCut, on Windows and LinuxLOCKFILE_FAIL_IMMEDIATELY/LOCK_NBdroppedTestAcquireLock_killedHolderDoesNotStrandTheLock: stranded after 5 sreleasenot idempotentTestCutLock_releaseIsIdempotentfilescan.goreverted, tests kept (Windows)TestScanTree,TestScanTreeExplicitOSPath,TestRegisterFileScanDrift,TestRegisterFileScanExemptAndAllowlistTestPrep_dryRunFailurePathLeavesTheCheckoutUntouched. Its hook arm is now Windows-aware; the unchanged-file arms still bite.TestScanTreeExplicitOSPathcan only discriminate on Windows; on Linux the two path forms are the same string. It was confirmed red there.Decisions (AGENTS.md section 7)
How to call
LockFileEx:syscall.NewLazyDLL+SyscallN. Chosen. Right when the module graph should stay at its two direct dependencies and only two calls are needed. The arguments mirror cmd/go's lockedfile: zeroedOVERLAPPED, whole range0xFFFFFFFF:0xFFFFFFFF. kernel32 is a KnownDLL, so the search path does not matter.os.OpenFile(O_CREATE|O_RDWR)opens a synchronous handle in Go 1.24-1.27 (os/file_windows.go), soERROR_IO_PENDINGcannot occur.golang.org/x/sys/windows. Right if more Windows API is ever needed, or if generated bindings are preferred over hand-writtenSyscallN. It adds a module togo.sumand to the release supply chain.What
rt prepdoes withpost_bump_hookson Windows:chmod +xthat cannot help on Windows.CreateProcessdoes not dispatch on a shebang.sh. Right only if a Windows-localrt prepwith hooks becomes a real use case. It tiesrtto where Git Bash is installed.Skip or port a test: port wherever Windows has the feature. Skip only where it does not:
regexeccannot match a multibyte member of a multi-member bracket under a UTF-8 locale.Re-pin (AGENTS.md section 2)
This changes code behind
rt prepandrt release: the cut lock and the hook runner.check-self-bootstrapwill not flag it.gates.DefaultComposeScriptsguards only workflow YAML andscripts/workflow-parse-check.sh(internal/gates/selfboot_check.go:234).rtwould compose the same rolling PR either way.No new verb or flag (section 13 not triggered):
--helpoutput is identical.Still not supported on Windows
post_bump_hooks: refused by name, see above.%TEMP%. Since Go 1.23filepath.EvalSymlinksdoes not resolve junctions, so a repo reached through a directory junction takes a different lock than its real path.sh,bashandlocaleresolve differently.version_filesguard does not reject a..\prefix;resolveUnderRoottreats only a leading/as absolute; an atomic rename fails over a read-only destination..goreleaser.yaml, ADR-0009 section 9).Verify at source (AGENTS.md section 6)
Please verify, not read:
go build ./cmd/rtbuilds here and fails on55a12b9.rt register-checkat the repo root on Windows: exit 0 here, 71 hits with only the lock commit applied.lock_windows.go) turnsTestAcquireLock_anotherProcessHoldsItred.golang:1.25.🤖 Generated with Claude Code
Landing identity record
96d26467698f3184f8fb11dd202135e2c29dd3d8This is a post-merge identity record. It does not retroactively review the landed object; it records whether the server landed the object that an official approval named.
go test ./...still fails on an LF checkout —cmd/rtdoes not build, and POSIX-only tests run unguarded #1501go test ./...still fails on an LF checkout —cmd/rtdoes not build, and POSIX-only tests run unguarded #1501