Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Hosted gem `rollback` / `remove` strips the `DEPENDENCIES` `!` of a gem the user declared inside a `source "https://rubygems.org" do` block, so every frozen install fails after the unwind

Đang mở Phù hợp với người mới
#1,056 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
80/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
ruby, rust
Lĩnh vực
cli

Hướng nghiên cứu

Bắt đầu tại crates/socket-patch-core/src/patch/redirect/upstream/gem.rs, khoảng dòng 354. Lệnh gọi strip_suffix('!') cần có điều kiện bảo vệ: chỉ xóa ! khi Gemfile đã khôi phục không còn khai báo gem bên trong khối source (hoặc với tùy chọn source:/git:/path:). Kiểm tra cách ngữ cảnh của Gemfile gốc được theo dõi trong quá trình unwind. Chạy bộ kiểm thử của dự án và xác minh bằng các bước tái hiện trong issue rằng một frozen install thành công sau rollback.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

agent:triaged bug bughunt pm:bundler priority:p1

[agent] Found by the scheduled Bundler (RubyGems) bug-hunt routine (ledger #316).

Summary

Bundler marks a dependency declared inside a source … do block with ! in the lock's DEPENDENCIES (colorize (= 0.8.1)!), even when that block's source is rubygems.org. The hosted scan of such a gem works: it nests the patch-registry block inside the user's block, and the fresh frozen install gets the patched bytes. The unwind (rollback, or remove <purl>) then restores the Gemfile byte for byte, so the declaration is back inside the user's source "https://rubygems.org" do block. But the unwind always drops the ! from the lock's DEPENDENCIES line. The restored pair no longer matches what Bundler writes, so BUNDLE_FROZEN=true bundle install fails with exit 16 ("Your lockfile needs to be updated, but it can't be because frozen mode is set"). rollback still reports success with hosted.reverted: [pkg:gem/[email protected]].

Impact

After undoing a patch, every CI or deployment (frozen) install of the project breaks until someone runs an unfrozen bundle install and commits the lock. The unwind is supposed to give back the original, installable pair.

Repro (Linux, Ruby 3.3.6, Bundler 4.0.22 or 2.6.9 with bundle lock --add-checksums)

Patch API and patch registry mocked on loopback (the run-13 mock from ledger #316); rubygems.org is the real upstream.

mkdir app && cd app
printf 'source "https://rubygems.org"\n\ngem "rake"\nsource "https://rubygems.org" do\n  gem "colorize", "0.8.1"\nend\n' > Gemfile
bundle lock && cp Gemfile.lock /tmp/orig.lock    # DEPENDENCIES: colorize (= 0.8.1)!
socket-patch scan --mode hosted --yes --api-url $MOCK --org org --api-token fake
BUNDLE_FROZEN=true BUNDLE_PATH=vb bundle install  # exit 0, patched bytes (OK)
socket-patch rollback --api-url $MOCK --org org --api-token fake --patch-server-url $MOCK
diff /tmp/orig.lock Gemfile.lock
#   <   colorize (= 0.8.1)!
#   ---
#   >   colorize (= 0.8.1)
git diff Gemfile                                  # empty: the Gemfile came back exactly
BUNDLE_FROZEN=true BUNDLE_PATH=vb2 bundle install # exit 16

socket-patch remove pkg:gem/[email protected] leaves the same diff, and a frozen install then fails with exit 16 too.

Expected vs actual

  • Expected: CLI_CONTRACT.md's "Hosted unwind coverage" gem row says the unwind undoes the source "<patch registry>" do … end block and "the pair comes back". The ! should only be dropped when the restored declaration no longer sits in a user source block (the case where hosted mode added it). Here the declaration's own block still pins the source, so the original ! must stay, and the lock should come back byte-identical to the pre-scan one.
  • Actual: the ! is always removed (the row says "the DEPENDENCIES pin loses its !" without exception), which leaves a pair that Bundler's frozen mode rejects.

Matrix

OS Ruby Bundler Shape Result
Linux 3.3.6 4.0.22 top-level source + source "https://rubygems.org" do gem … end reproduces (×2)
Linux 3.3.6 4.0.22 every gem inside one source "https://rubygems.org" do block reproduces
Linux 3.3.6 4.0.22 source … do + nested group :default do reproduces
Linux 3.3.6 2.6.9 (CHECKSUMS added) every gem inside one source block reproduces
Linux 3.3.6 4.0.22 remove <purl> instead of rollback reproduces
Linux 3.3.6 4.0.22 plain top-level declaration (control) pass (lock byte-restored)

macOS and Windows weren't probed. The lock surgery is OS-independent.

First bad version

Not bisected. This is current main d47eab3; the v5 upstream restore introduced the hosted unwind.

Suspect code

crates/socket-patch-core/src/patch/redirect/upstream/gem.rs:354: for a non-transitive gem, entry.strip_suffix('!') unconditionally rewrites the DEPENDENCIES line to the unpinned form. It doesn't check whether the restored Gemfile still declares the gem inside a source … do block (or with a source: / git: / path: option), and in that case Bundler keeps the !.

Ngôn ngữ chính
Rust
Star
8
Fork
0
Merge trung bình
1 ngày 1 giờ
Pull request đã merge (30 ngày)
257

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của SocketDev/socket-patch

Tất cả issue của SocketDev/socket-patch

Issue tương tự

Thêm issue về Rust

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.