Repository navigation
Fix hosted Go pins outranked by go.work members (#1753) - #1755
Conversation
Assisted-by: Claude Code:claude-opus-5-5
In a go.work workspace Go builds the highest version any member requires. The version check behind apply, apply --check, vendor and vex read only the current module's go.mod, so when another member required a newer version, apply wrote a replace the build ignored, apply --check said "in sync" and vex attested not_affected for a module the workspace still built unpatched. The check now reads every `use` member's go.mod and go.sum and treats a higher version anywhere in the workspace as the one built. apply and vendor refuse, apply --check fails and vex leaves the patch out (go_version_not_selected). Fixes #1751. Assisted-by: Claude Code:claude-opus-5-5
When every go.work member proves a version below the patched one and none is undecided, the workspace builds the highest of them, so the refusal now names that version instead of this module's own or "unknown". Reading go.work's members is shared with the conflict check, and the Go workspace docs say which commands read the other members. Assisted-by: Claude Code:claude-opus-5-5
The workspace member list now answers whether a go.work is in effect, so the separate check has no callers left. Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
In a go.work workspace the build uses the highest version any member requires. `scan --mode hosted` only read the module it ran in, so in member a it pinned v1.0.0 while member b's v1.1.0 is what gets built, and reported the module as redirected though the pin did nothing. The hosted Go rewriter now also weighs the other members' go.mod and go.sum, the same way agent apply, apply --check and vex do. It refuses such a pin with redirect_golang_version_mismatch, and a rescan removes a pin it wrote before another member moved ahead. The in-memory engine has no workspace on disk and is unchanged. Fixes #1753 Assisted-by: Claude Code:claude-opus-5-5
Review follow-ups for the workspace check: - Parse each member's go.mod and go.sum once, not once per patched module, so a large workspace does not slow the scan. - Match the scanned module against the use list the way the rest of the go.work code does (same_dir_key). - Say "no go.work member" in the not-in-graph warning when the workspace was weighed, instead of blaming this module alone. - Pin GOWORK and GOENV in the hosted Go state tests so a machine setting GOWORK=off can't hide the workspace. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
[agent] Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit d882a61. Configure here.
|
Burn-down agent: labeled Ready for review at head
Generated by Claude Code |
|
Burn-down agent: labeled Ready for review at head
Generated by Claude Code |
Final review briefWhat it does. In a Risk: low–medium. Narrow to the hosted Go rewriter; the member read is lazy (only when a golang dep is rewritten) and an empty member list keeps today's behavior exactly (in-memory/napi engine passes none). Medium only because it can now refuse pins that were written before; that is the intended fix. Look here
Verified
Changes I made: none. Open questions: none blocking. Follow-ups the PR already names (not in scope): go.work Merge order: stacked on #1752 (base Generated by Claude Code |
Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Bugbot is paused — your team has an unpaid invoiceBugbot is paused because your team has an unpaid invoice. Pay it from the billing page in the Cursor dashboard and Bugbot resumes automatically. (requestId: 37a821e2-708f-4f35-b414-cdace212661e) |
|
[agent] Bugbot can't review 920f2f1: Cursor says it is paused until the team pays an unpaid invoice (Cursor dashboard → Billing). 920f2f1 only merges Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1753
#1752 has landed; this PR now targets
main.Summary
In a
go.workworkspace, Go builds the highest version of a module that anyusemember requires.scan --mode hosted(andget --mode hosted) read only the module they ran in. So in memberathe scan pinnedexample.com/upstream v1.0.0while memberb'sv1.1.0is what gets built, and reported the module as redirected though the pin did nothing. #1752 already keepsvexfrom attesting such a pin. This PR stops the scan from writing it.Root cause
rewrite_golang(patch/redirect/mod.rs) is an in-memory rewriter over the files the hosted engine reads, which are the root module'sgo.mod/go.sumonly. Its version gate never saw the other members.Fix
go_build_list: Fix Go version gate ignoring go.work members (#1751) #1752's MVS weighing moves out ofproject_selectioninto a pureworkspace_selection, so the agent and hosted paths share one rule. NewModuleEvidenceparses a member's go.mod/go.sum once.other_workspace_membersreads everyusemember except the scanned one (matched withgo_consumer_sync::same_dir_key, like the rest of the go.work code).hosted::engine::RewriteOptionsgains a lazygo_workspaceresolver, the same pattern ascargo_outer. It is called only when a golang dep is rewritten. The CLI passesother_workspace_members(cwd). The in-memory engine has no project on disk and passes none.rewrite_golangweighs those members. A pin another member outranks is refused withredirect_golang_version_mismatch("another go.work workspace member makes the build select v1.1.0"). A hosted pin written earlier is removed on rescan, the same as when the module's own go.mod moves on. A module this go.mod omits but a member proves at the patched version now counts as in the graph.scan --mode hostedis now in the list of commands that read every member.Test evidence
e2e_golang_hosted_state::hosted_pin_another_go_work_member_outranks_is_refused(control pin, then member b moves to v1.1.0: rescan reports 0 pinned + mismatch and removes the go.mod/go.sum pin; a fresh project never gets it)left: 1 right: 0, envelope"action":"applied"patch::redirect::tests::golang_workspace_member_requiring_a_higher_version_skipspatch::redirect::tests::golang_workspace_members_that_do_not_outrank_still_redirectvendor::go_build_list::tests::other_workspace_members_reads_every_member_but_this_oneRed run: stashed the
src/changes, kept the e2e,cargo test -p socket-patch-cli --all-features --test e2e_golang_hosted_state -- go_workfailed as above; restored, passed.Local commands (go 1.24.7,
SOCKET_PATCH_GO_E2E_REQUIRED=1):cargo fmt --all -- --check: okcargo clippy --workspace --all-features -- -D warnings: okcargo test -p socket-patch-core --all-features --lib: 6806 passed, 4 failed. All 4 rely on chmod denying writes, which it doesn't here because the container runs as root (copy_treesymlinked root,vlt_healunremovable lock,pypi_poetry/pypi_requirementswire failures). Fix Go version gate ignoring go.work members (#1751) #1752 saw the same.cargo test -p socket-patch-cli --all-featuresfor--lib --binsplus e2e_golang (23), e2e_golang_build (28), e2e_golang_hosted_build (22), e2e_golang_hosted_state (30), e2e_golang_workspace_build (16), e2e_vendor_golang_build (38), hosted_memory_engine, hosted_memory_parity, in_process_get_hosted_ecosystems, in_process_rollback_hosted, vendor (151) and vex (47): all pass.cargo test --workspacelocally: linking every test binary ran this container out of disk. CI runs it.npm/,pypi/,gem/only dispatch to the binary)./code-review highfindingsFixed in d882a61:
ModuleEvidence).canonicalize. It now usessame_dir_key.GOWORK/GOENV. The hosted state tests now pinGOWORK=auto GOENV=off.Not fixed, and why:
replacedirectives / conflicting member replaces aren't checked by the hosted rewriter: this predates the PR, since the hosted path never read go.work at all. It is a different gate (go_consumer_sync::conflict_in, used by apply/vendor) from the version selection Hosted Go scan in a go.work member pins a version another member outranks #1753 is about. Worth a follow-up issue.project_selectionfrom Fix Go version gate ignoring go.work members (#1751) #1752 has the same limit. It only matters for a pre-1.17 member whose zip line for the higher version landed only in go.work.sum.cargo_outer. It runs only when a golang dep is rewritten, and it reads a handful of small files.workspace_member_dirs: 8 lines, and both shareworkspace_fileanduse_dirs, so they can't drift on the parsing rules.https://claude.ai/code/session_011f9aeQqMk6io8PkpNve53f
Generated by Claude Code