Skip to content

Build: fix nightly gem unwind test on bundler < 2.2 (#1685) - #1687

Open
Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
agent/fix-ci-gem-unwind-old-bundler
Open

Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
agent/fix-ci-gem-unwind-old-bundler

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1685

Problem

The nightly full-scope run on main (39907645034) fails both old-bundler e2e-extended gem legs (bundler 1.17.3 and 2.1.4 on Ruby 3.1) in gem_hosted_unwind_after_unconverged_supersede_undoes_the_new_block, added in #1664.

Root cause

The test needs the "unconverged window" from #1626: a superseding hosted re-scan moves the Gemfile block to the new patch while the lock still pins the old one. Bundler 1.17 to 2.1 write one merged GEM section that lists every remote. Lockfile discovery can't attribute the new pin there, so the gen-3 scan refuses it with redirect_unattributable and writes nothing. Locally on bundler 2.1.4 the scan reports:

"action": "skipped", "uuid": "9a9a9a9a-…", "errorCode": "redirect_unattributable"

The Gemfile stays on gen 2, so the test's premise assert (gemfile.contains(GEN3), e2e_redirect_gem_build.rs:2346) fails before rollback or remove even runs. The product behaves safely here: it refuses and leaves both files unchanged. The window #1626 fixed can't open on these bundler eras. PR CI and the merge queue run only the bundler 4.0.21 leg, which is why only the nightly saw this.

Change

Test only, one function. On bundler < 2.2 (fx.bundler.at_least(2, 2), the same gate the source-block unwind test already uses), the test no longer expects the unconverged window. Instead it:

  • parses the scan envelope and requires a skipped event for vuln-gem's gen-3 uuid with errorCode: redirect_unattributable;
  • requires the refused scan to leave the Gemfile and lock byte-identical to the converged gen-2 pair;
  • then still runs rollback / remove on that gen-2 pair, with the same checks as before: no patch-registry left in either file, the gem declared again, and a frozen bundle install accepting the restored lock unchanged.

Bundler 2.2+ runs the original unconverged-window path unchanged. The doc comment and #[ignore] text say which era gets which path. No product code changed.

The refusal itself is a real product limitation: on bundler < 2.2 a superseding patch is never applied, and scan exits 0. That is filed as #1688 for the product lane and referenced in the test comment.

Runner usage

No workflow change. Lean PR run: same ~28 Linux jobs and job-minutes before and after. The nightly old-bundler legs run the same tests.

Tests (local, Ruby 3.3.6)

bundler before after
2.1.4 FAILED at :2346 (Gemfile still on gen 2) ok (refusal asserted, then rollback and remove of gen 2 pass)
2.2.33 ok ok (full path)
4.0.18 ok ok (full path)
  • Full e2e_redirect_gem_build + e2e_vendor_gem_build with --ignored on bundler 2.1.4: 32 + 8 passed.
  • Bundler 1.17.3 doesn't run on Ruby 3.3, so I couldn't run it locally. It writes the same merged-section lock shape as 2.1.4 (module docs, line 89) and takes the same branch. The nightly leg will confirm it.
  • cargo fmt --all -- --check clean. cargo clippy --workspace --all-features -- -D warnings clean. The --all-targets clippy errors (duplicate common/ module loads and others) exist on main too and are unrelated.

/code-review high

Six findings, all addressed in bb18fa1: the refusal check now parses the JSON and matches purl, uuid and code; the files are compared byte for byte; old bundler still runs the unwind (which also removes the duplicate-fixture concern, because both iterations now test something); the doc and #[ignore] text are updated; and the product limitation is filed as #1688.

Not in this PR

The Windows test shards in the same nightly fail on path-form mismatches (RUNNER~1 8.3 names vs canonical \\?\C:\Users\…, mixed separators): hosted::governing_root::tests::vlt_project_root_governs_unlisted_directories, get_failure_paths::engine_nested_apply_preserves_conflicts_introduced_during_fetch, and an unidentified user_patches test. The night before, uv::tests::global_uv_settings_reads_the_user_then_first_system_file failed instead. That is a separate root cause.

https://claude.ai/code/session_014zBZGsFDqCwbUGY77ue3Dq


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
The unconverged-supersede unwind test needs a superseding hosted
re-scan that moves only the Gemfile block to the new patch. Bundler
1.17 to 2.1 write one merged GEM section, where discovery can't
attribute the new pin, so that re-scan refuses it
(redirect_unattributable) and writes nothing. The window the test
covers never opens there, and its premise assert failed on both
old-bundler nightly legs.

On those eras the test now asserts the refusal and that both files
stay on the earlier patch, then stops with a SKIP line. Bundler 2.2+
runs the full rollback and remove checks as before.

Fixes #1685

Assisted-by: Claude Code:claude-opus-5-5
Review follow-up for the bundler < 2.2 branch of the unconverged
supersede test. It now parses the scan output and requires the
skipped event for this gem's new patch, checks that the refused scan
left the Gemfile and lock byte-identical, and then still runs
rollback or remove on the converged gen 2 pair with the same
cleanup and frozen-install checks, so old bundler legs keep covering
the unwind. The refusal itself is tracked as #1688.

Refs #1685

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 23, 2026 07:16
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 bb18fa1. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 23, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Labeled Ready for review (burn-down agent).

  • Head: bb18fa1
  • CI: 86/86 settled (36 success, 50 skipped by path filters), no failures, no main-wide failures
  • Bugbot: reviewed bb18fa1, no findings; no open review threads
  • Reviewer note: only crates/socket-patch-cli/tests/e2e_redirect_gem_build.rs changes. The bundler < 2.2 legs it fixes only run in the nightly, so the next nightly is the real confirmation.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Labeled Ready for review by the burn-down agent.

  • Head: bb18fa128b0edadff2f6188b5ab662ee3523171e
  • CI: 86/86 settled (36 success, 50 skipped), no failures; mergeable, waiting only on human review.
  • Bugbot: reviewed this head, no issues found; no open review threads.
  • Reviewer note: the bundler 1.17.3 / 2.1.4 legs this fixes run only in the nightly, so the next nightly is the real confirmation.
  • Slack announcement could not be sent from this run (no Slack send tool available).

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Final review brief

What it does. Test-only fix for the nightly failure in #1685. On bundler < 2.2 (one merged GEM section), a superseding hosted scan refuses the new pin as redirect_unattributable, so the "unconverged window" this test needs never opens. On those bundler versions the test now asserts that refusal and that both files are unchanged, then runs the same rollback/remove checks on the gen 2 pair. Bundler 2.2+ runs the old path unchanged. No product code changes.

Risk: low. One #[ignore] e2e test changes, and only the bundler < 2.2 branch is new. PR CI and the merge queue run only the bundler 4.x leg, so the new branch first runs in the nightly e2e-extended 1.17.3 / 2.1.4 legs. The author ran it on 2.1.4 locally.

Look here

  • e2e_redirect_gem_build.rs:2336:`` snapshots the converged gen 2 Gemfile/lock before the gen 3 scan
  • :2348:``` the at_least(2, 2) gate, the same one the source-block unwind test uses (line 3272)
  • :2356-2380:```` the old-bundler branch. It parses the envelope, matches purl + gen 3 uuid + redirect_unattributable, and checks both files byte for byte
  • :2419:````` the unwind and frozen-install checks, which now run on both branches

Verified. Read the full diff (1 file, +41/−11). PURL/GEN3 match the mounted generation, and the error code matches hosted::engine::REDIRECT_UNATTRIBUTABLE. CHANGELOG is untouched and there's no debug code. CI on the head: 36 checks succeeded and 50 were skipped by path filters, with none failing. ci-ok and clippy are green, Cursor Bugbot passed, and there are no review threads.

Changes I made. None.

Open question (doesn't block this PR). #1690 fixes the product limitation (#1688) and rewrites this same else arm to expect the opposite (the supersede lands, lock on gen 3). Whichever PR merges second will conflict on these lines. If this one lands first, #1690's version of the arm should win when that conflict is resolved, or the nightly goes red again. I left a note on #1690.

Auto-merge is armed, so approving sends this straight to the merge queue.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nightly: gem unwind-after-unconverged-supersede e2e fails on bundler 1.17.3/2.1.4

2 participants