Fix release script: require changelog, fix RC version computation#2848
Fix release script: require changelog, fix RC version computation#2848
Conversation
…tion Two bugs caused the 16.5.0 release to go out without a changelog entry: 1. compute_target_gem_version did not account for pre-release versions. When the current version was 16.5.0.rc.0 and a "patch" bump was requested, it computed 16.5.1 as the target — but gem bump actually strips the RC suffix to produce 16.5.0. All pre-release validation (changelog check, version policy) ran against the wrong version. 2. Missing changelog was only a warning (warn_changelog_missing), not a hard stop. The release proceeded without a CHANGELOG section, skipping the GitHub release entirely. Fixes: - compute_target_gem_version now strips the pre-release suffix on patch bump (16.5.0.rc.0 + patch → 16.5.0), matching gem-release behavior - Replaced warn_changelog_missing with require_changelog_section! that aborts unless RELEASE_VERSION_POLICY_OVERRIDE is set - Added CHANGELOG.md section for 16.5.0 (references 16.5.0.rc.0) - Updated [unreleased] comparison link to v16.5.0 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughRelease tooling updated to promote prerelease patch bumps to stable by stripping prerelease suffix, added tag-detection and an interactive release confirmation, updated changelog links and added a 16.5.0 entry, and extended tests to cover the new behaviors and edge cases. (34 words) Changes
Sequence Diagram(s)sequenceDiagram
participant Rake as Rake(:release)
participant Resolver as VersionResolver
participant Changelog as CHANGELOG.md
participant Git as Git
participant User as User (stdin)
Rake->>Resolver: resolve_version_input(current_gem_version, version_input)
Resolver->>Git: version_tagged?(monorepo_root, candidate)
Git-->>Resolver: tagged / not tagged
Resolver-->>Rake: compute_target_gem_version(...)
Rake->>Changelog: extract_changelog_section(final_version)
Changelog-->>Rake: section content / nil
Rake->>User: confirm_release!(version) (prompt)
User-->>Rake: y / n
alt confirmed
Rake->>Git: create tag / push / perform release steps
else aborted
Rake-->>User: abort release
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review: Fix release script — require changelog, fix RC version computationThis is a solid, focused fix for two real bugs that caused the 16.5.0 release to ship without a changelog or GitHub release. The changes are clean, well-scoped, and follow the existing codebase patterns. What works well
One gap worth consideringThe Minor nitThe error message in Overall this is good to merge once the minor/major pre-release question is resolved (or documented as intentional). |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
rakelib/release.rake (1)
211-217: Logic is correct; consider adding test coverage for prerelease transitions.The fix correctly handles the prerelease → stable case (e.g.,
16.5.0.rc.0+patch→16.5.0), matchinggem-releasebehavior. However, the existing spec (seerelease_rake_helpers_spec.rb:46-57) only tests stable versions.Consider adding a test case like:
expect(compute_target_gem_version(current_gem_version: "16.5.0.rc.0", version_input: "patch")).to eq("16.5.0")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rakelib/release.rake` around lines 211 - 217, Add a spec to cover prerelease→stable transitions for compute_target_gem_version: update or add a test in release_rake_helpers_spec.rb that calls compute_target_gem_version(current_gem_version: "16.5.0.rc.0", version_input: "patch") and asserts it returns "16.5.0"; this verifies the branch that strips the prerelease suffix when version[:prerelease_type] is present and ensures future regressions are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@rakelib/release.rake`:
- Around line 211-217: Add a spec to cover prerelease→stable transitions for
compute_target_gem_version: update or add a test in release_rake_helpers_spec.rb
that calls compute_target_gem_version(current_gem_version: "16.5.0.rc.0",
version_input: "patch") and asserts it returns "16.5.0"; this verifies the
branch that strips the prerelease suffix when version[:prerelease_type] is
present and ensures future regressions are caught.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ea6618f4-751b-4753-ad74-04a0397c6df7
📒 Files selected for processing (2)
CHANGELOG.mdrakelib/release.rake
Greptile SummaryThis PR fixes two bugs in the release automation that caused the 16.5.0 stable release to go out without a CHANGELOG entry or GitHub release. The changes are surgical and correct.
Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["rake release[version, dry_run, override]"] --> B[resolve_version_input]
B --> C[validate_requested_version_input!]
C --> D[compute_target_gem_version]
D --> E{Is pre-release\nversion?}
E -- "yes + patch bump\n(NEW: e.g. 16.5.0.rc.0)" --> F["Strip suffix → 16.5.0\n✅ was: 16.5.1"]
E -- "no + patch bump" --> G["Increment patch\n16.5.0 → 16.5.1"]
E -- minor/major --> H["Bump minor/major\n(unchanged)"]
F --> I
G --> I
H --> I
I["require_changelog_section!"] --> J{Section\nexists?}
J -- "yes" --> K[validate_release_version_policy!]
J -- "no + allow_override" --> L["⚠️ Warn and continue\n(RELEASE_VERSION_POLICY_OVERRIDE=true)"]
J -- "no + no override" --> M["❌ abort release\n✅ was: just a warning"]
L --> K
K --> N[Run gem bump / npm publish / GitHub release]
|
…rmation Refine the release script to prevent the kind of issue that happened with the 16.5.0 release (released without changelog or GitHub release): 1. resolve_version_input now checks if the latest CHANGELOG version is untagged (not yet released) and uses it, even when it matches the current gem version. This handles the common workflow of updating the changelog, committing, then running rake release. 2. Added a confirmation prompt before releasing that shows the target version and whether a CHANGELOG section exists. The user must type "y" to proceed (skipped for dry runs). 3. Replaced the hard-abort require_changelog_section! with the simpler confirmation approach — the user sees the changelog status clearly and decides whether to proceed. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
| if changelog_version && !version_tagged?(monorepo_root, changelog_version) | ||
| puts "Found untagged CHANGELOG.md version: #{changelog_version} (current: #{current_version})" | ||
| return changelog_version | ||
| end |
There was a problem hiding this comment.
Edge case: changelog_version < current_version and untagged
This branch fires whenever changelog_version is truthy and not tagged—including the case where changelog_version < current_version. That can happen if, for example, a patch release was cut without updating the changelog, leaving an older version entry as the "latest" changelog entry. In that scenario the function returns changelog_version (a lower version), which will then fail validate_release_version_policy!, but the error message will be confusing ("requested version X must be greater than latest tagged version Y" when X < Y).
Consider narrowing the guard to the == case that is the stated intent:
| end | |
| if changelog_version && Gem::Version.new(changelog_version) == Gem::Version.new(current_version) && | |
| !version_tagged?(monorepo_root, changelog_version) |
| print "Proceed with release? [y/N] " | ||
| $stdout.flush | ||
| answer = $stdin.gets&.strip&.downcase | ||
| abort "Release aborted." unless answer == "y" |
There was a problem hiding this comment.
Missing changelog doesn't block the release
The confirmation prompt informs the user that the changelog section is absent but still lets them type y and proceed. sync_github_release (called later) will then hard-abort because the section is required. The practical result is the gem gets published but no GitHub release is created—exactly the 16.5.0 situation this PR was meant to prevent.
Consider requiring an explicit second confirmation, or outright aborting, when has_changelog is falsy:
unless has_changelog
puts " Changelog: ✗ MISSING — no GitHub release will be created"
puts " Run /update-changelog to add entries before releasing."
puts "################################################################################"
print "Proceed WITHOUT a changelog entry? This will skip the GitHub release. [y/N] "
$stdout.flush
abort "Release aborted." unless $stdin.gets&.strip&.downcase == "y"
end
ReviewThe two root-cause fixes are correct and well-targeted:
I've left four inline comments covering:
The most actionable of these is #2 (narrowing the |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rakelib/release.rake`:
- Around line 390-410: In confirm_release! ensure a missing changelog blocks the
release: check the has_changelog boolean and if false call abort with a clear
message (instead of only printing a warning) before prompting the user; update
the confirm_release! flow so that when has_changelog is false it aborts the task
(use the existing abort "Release aborted." pattern) so publishing cannot proceed
without a changelog.
- Around line 546-552: The fast-path branch uses an untagged changelog version
without ensuring it matches the runtime current version, so change the guard in
the release logic to only accept the changelog_version when it equals
current_version; specifically update the if that references changelog_version
and version_tagged?(monorepo_root, changelog_version) to also require
changelog_version == current_version so the code only returns the changelog
value when it truly represents the current version.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c6ebfc22-f219-49b8-8b8c-3812104d3b67
📒 Files selected for processing (1)
rakelib/release.rake
| def confirm_release!(version:, monorepo_root:) | ||
| changelog_path = File.join(monorepo_root, "CHANGELOG.md") | ||
| section = extract_changelog_section(changelog_path: changelog_path, version: version) | ||
| return if section | ||
| has_changelog = extract_changelog_section(changelog_path: changelog_path, version: version) | ||
|
|
||
| puts "" | ||
| puts "################################################################################" | ||
| puts "RELEASE CONFIRMATION" | ||
| puts "################################################################################" | ||
| puts "WARNING: No CHANGELOG.md section found for #{version}." | ||
| puts "Consider running /update-changelog to add entries before releasing." | ||
| puts "sync_github_release will fail without a matching changelog section." | ||
| puts " Version: #{version}" | ||
| if has_changelog | ||
| puts " Changelog: ✓ section found" | ||
| else | ||
| puts " Changelog: ✗ MISSING — no GitHub release will be created" | ||
| puts " Run /update-changelog to add entries before releasing." | ||
| end | ||
| puts "################################################################################" | ||
| print "Proceed with release? [y/N] " | ||
| $stdout.flush | ||
| answer = $stdin.gets&.strip&.downcase | ||
| abort "Release aborted." unless answer == "y" | ||
| end |
There was a problem hiding this comment.
Missing changelog still only warns, so the release can proceed.
Line 402 detects the exact condition that previously produced a release without notes, but Line 409 still lets the task continue after a "y". That means the script can still publish gems/packages and only skip the GitHub release afterward.
🛠️ Proposed fix
-def confirm_release!(version:, monorepo_root:)
+def confirm_release!(version:, monorepo_root:, allow_override:)
changelog_path = File.join(monorepo_root, "CHANGELOG.md")
has_changelog = extract_changelog_section(changelog_path: changelog_path, version: version)
+
+ unless has_changelog
+ handle_version_policy_violation!(
+ message: "❌ Could not find `### [#{version}]` in CHANGELOG.md. Run /update-changelog before releasing.",
+ allow_override: allow_override
+ )
+ end
puts ""
puts "################################################################################"
puts "RELEASE CONFIRMATION"
@@
if has_changelog
puts " Changelog: ✓ section found"
else
- puts " Changelog: ✗ MISSING — no GitHub release will be created"
+ puts " Changelog: ✗ MISSING — proceeding only because override is enabled"
puts " Run /update-changelog to add entries before releasing."
end
@@
- confirm_release!(version: resolved_target_gem_version, monorepo_root: release_root) unless is_dry_run
+ confirm_release!(
+ version: resolved_target_gem_version,
+ monorepo_root: release_root,
+ allow_override: allow_version_policy_override
+ ) unless is_dry_runAlso applies to: 750-750
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rakelib/release.rake` around lines 390 - 410, In confirm_release! ensure a
missing changelog blocks the release: check the has_changelog boolean and if
false call abort with a clear message (instead of only printing a warning)
before prompting the user; update the confirm_release! flow so that when
has_changelog is false it aborts the task (use the existing abort "Release
aborted." pattern) so publishing cannot proceed without a changelog.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Missing equality check allows returning older untagged version
- I confirmed the conditional was overly broad and updated it to require changelog and current versions to be equal before returning an untagged changelog version.
Or push these changes by commenting:
@cursor push 1bf19df349
Preview (1bf19df349)
diff --git a/rakelib/release.rake b/rakelib/release.rake
--- a/rakelib/release.rake
+++ b/rakelib/release.rake
@@ -546,7 +546,9 @@
# If the latest changelog version matches the current version but hasn't been
# tagged yet, use it. This handles the case where the changelog was updated
# and the version bumped in a prior step (e.g., RC → stable promotion).
- if changelog_version && !version_tagged?(monorepo_root, changelog_version)
+ if changelog_version &&
+ Gem::Version.new(changelog_version) == Gem::Version.new(current_version) &&
+ !version_tagged?(monorepo_root, changelog_version)
puts "Found untagged CHANGELOG.md version: #{changelog_version} (current: #{current_version})"
return changelog_version
endAdd comments and tests clarifying that "minor" and "major" bumps from a pre-release version increment from the base (e.g., 16.5.0.rc.0 + "minor" = 16.6.0), matching gem-release behavior. To promote an RC to its stable version, use "patch" instead. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
Review: Fix release script — RC version computation and changelog gate Overall this is a solid, well-scoped fix. The root causes are correctly identified, the changes are minimal, and the new specs cover the key cases. A few things worth addressing: 1. version_tagged? relies on stale local tags version_tagged? passes fetch_tags: false to tagged_release_gem_versions. It is called from resolve_version_input, which runs before validate_release_version_policy! fetches tags. If the local tag cache is stale, version_tagged? could return false for a version that has already been released, causing the release task to proceed for an already-published version. Consider either fetching tags inside version_tagged?, or adding a comment explaining why the downstream validate_release_version_policy! (which does fetch) is a sufficient safety net. 2. confirm_release! has no specs The new confirm_release! reads from stdin but is not exercised by any spec. Worth adding cases for: abort on non-'y' input, abort on nil (EOF), and the two changelog-present vs missing display paths. 3. No runtime warning for minor/major from pre-release The comments in compute_target_gem_version explain the footgun (16.5.0.rc.0 + minor produces 16.6.0, not 16.5.0), but there is no runtime signal. A puts warning in those branches would surface the surprise without blocking anything. 4. Removing warn_changelog_missing silences the dry-run changelog warning The old warn_changelog_missing ran unconditionally, including during dry runs. The new confirm_release! is skipped on dry runs (unless is_dry_run). This means rake release[patch,true] no longer warns about a missing changelog section. Consider printing changelog status even on dry runs (without the prompt) to preserve pre-flight visibility. 5. Minor: has_changelog is a string, not a boolean extract_changelog_section returns a String or nil. Naming the variable has_changelog and using it as a boolean works in Ruby but is slightly misleading. Using !!extract_changelog_section(...) would make the intent explicit. CHANGELOG note The 16.5.0 compare link (v16.5.0.rc.0...v16.5.0) will 404 until v16.5.0 is tagged. Expected once the release lands, just noting it for anyone reviewing before that. Verdict The core logic fixes are correct. Issues 1 and 4 are the most impactful: a stale-tag false-negative in version_tagged? could trigger an accidental re-release, and silently dropping the dry-run changelog warning reduces pre-flight visibility. |
| else | ||
| "#{version[:major]}.#{version[:minor]}.#{version[:patch] + 1}" | ||
| end | ||
| when "minor" |
There was a problem hiding this comment.
No runtime warning when minor/major is requested from a pre-release version. A developer running rake release[minor] from 16.5.0.rc.0 will silently publish 16.6.0 instead of 16.5.0. A one-line puts here (and in the major branch) would surface this:
| when "minor" | |
| # NOTE: From a pre-release (e.g., 16.5.0.rc.0), this produces 16.6.0, not 16.5.0. | |
| # To promote a pre-release to its stable version, use "patch" instead. | |
| # This matches `gem bump --version minor` behavior from the gem-release gem. | |
| warn "⚠️ Bumping minor from a pre-release version (#{current_gem_version}) produces #{version[:major]}.#{version[:minor] + 1}.0, not the stable version. Use 'patch' to promote to stable." | |
| "#{version[:major]}.#{version[:minor] + 1}.0" |
There was a problem hiding this comment.
Declining — the comments added in 36d96e9 already document this behavior. A runtime warning would add noise for an intentional operation. If someone runs rake release[minor] from an RC, the existing comments make the behavior clear.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Existing test breaks due to unstubbed
version_tagged?call- I updated the failing resolve_version_input spec to stub version_tagged? for the equal-version path so it no longer shells out to git in a non-repo temp path.
Or push these changes by commenting:
@cursor push fa160c26e3
Preview (fa160c26e3)
diff --git a/react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb b/react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb
--- a/react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb
+++ b/react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb
@@ -205,6 +205,7 @@
it "falls back to a patch bump when the changelog does not introduce a newer version" do
allow(self).to receive(:extract_latest_changelog_version).with(monorepo_root: "/tmp/repo").and_return("16.3.0")
allow(self).to receive(:current_gem_version).with("/tmp/repo").and_return("16.3.0")
+ allow(self).to receive(:version_tagged?).with("/tmp/repo", "16.3.0").and_return(true)
expect(resolve_version_input("", "/tmp/repo")).to eq("patch")
endThere was a problem hiding this comment.
♻️ Duplicate comments (2)
rakelib/release.rake (2)
398-417:⚠️ Potential issue | 🟠 MajorMissing changelog still doesn't block publishing.
This is still open:
confirm_release!only reports the missing/empty section and then proceeds after"y", so the task can still publish gems/packages and skip the GitHub release afterward. Threadallow_version_policy_overridethrough this helper and fail before prompting when the changelog section is missing or empty.🛠️ Suggested fix
-def confirm_release!(version:, monorepo_root:) +def confirm_release!(version:, monorepo_root:, allow_override:) changelog_path = File.join(monorepo_root, "CHANGELOG.md") has_changelog = extract_changelog_section(changelog_path: changelog_path, version: version) + + unless has_changelog + handle_version_policy_violation!( + message: "❌ Could not find non-empty `### [#{version}]` in CHANGELOG.md. " \ + "Run /update-changelog before releasing.", + allow_override: allow_override + ) + end puts "" puts "################################################################################" @@ if has_changelog puts " Changelog: ✓ section found" else - puts " Changelog: ✗ MISSING — no GitHub release will be created" - puts " Run /update-changelog to add entries before releasing." + puts " Changelog: ✗ MISSING/EMPTY — proceeding only because override is enabled" end @@ - confirm_release!(version: resolved_target_gem_version, monorepo_root: release_root) unless is_dry_run + confirm_release!( + version: resolved_target_gem_version, + monorepo_root: release_root, + allow_override: allow_version_policy_override + ) unless is_dry_runAlso applies to: 758-758
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rakelib/release.rake` around lines 398 - 417, confirm_release! currently only warns about a missing changelog section and still prompts to continue; thread the allow_version_policy_override flag into confirm_release! and, inside confirm_release!, call extract_changelog_section (already used) and if the changelog section is missing/empty AND allow_version_policy_override is false, abort immediately with a helpful message (do not prompt); if allow_version_policy_override is true preserve the existing prompt behavior. Update the confirm_release! signature to accept allow_version_policy_override:, propagate that parameter from callers, and ensure the abort path occurs before the interactive print/gets block.
554-560:⚠️ Potential issue | 🟠 MajorRestrict the untagged-CHANGELOG fast path to the current version.
This is still open: the new branch returns any untagged latest changelog version, not just the version currently in
version.rb. If the newest changelog entry is older but untagged, auto mode resolves backwards and can downgrade the release target.🛠️ Suggested fix
- if changelog_version && !version_tagged?(monorepo_root, changelog_version) + if changelog_version && + Gem::Version.new(changelog_version) == Gem::Version.new(current_version) && + !version_tagged?(monorepo_root, changelog_version) puts "Found untagged CHANGELOG.md version: #{changelog_version} (current: #{current_version})" return changelog_version end🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rakelib/release.rake` around lines 554 - 560, The current fast-path returns any untagged changelog_version which can downgrade the target; modify the conditional so it only triggers when changelog_version is present, untagged, AND equals the repo's current_version (i.e., change the if to: if changelog_version && changelog_version == current_version && !version_tagged?(monorepo_root, changelog_version) ), ensuring you compare the same types/format used by current_version and changelog_version.
🧹 Nitpick comments (1)
react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb (1)
53-67: Please add specs for the two other new release branches.Since you're already expanding helper coverage here, add one example for
resolve_version_inputwhen the changelog version equals the current version but the tag is missing, and one for the missing/empty changelog path inconfirm_release!. Those are the two new control-flow branches inrakelib/release.rake, and neither is pinned down yet.Also applies to: 158-178
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb` around lines 53 - 67, Add two specs covering the new branches: one that calls resolve_version_input with a changelog version equal to the current gem version but with the git tag absent (simulate tag missing) and assert the expected return/behavior for that branch; and one that calls confirm_release! with a missing or empty changelog_path (simulate nil/"" path) and assert the expected error/return for that branch. Place these examples alongside the existing compute_target_gem_version specs in react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb and reference the resolve_version_input and confirm_release! methods so the new control-flow branches in rakelib/release.rake are exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@rakelib/release.rake`:
- Around line 398-417: confirm_release! currently only warns about a missing
changelog section and still prompts to continue; thread the
allow_version_policy_override flag into confirm_release! and, inside
confirm_release!, call extract_changelog_section (already used) and if the
changelog section is missing/empty AND allow_version_policy_override is false,
abort immediately with a helpful message (do not prompt); if
allow_version_policy_override is true preserve the existing prompt behavior.
Update the confirm_release! signature to accept allow_version_policy_override:,
propagate that parameter from callers, and ensure the abort path occurs before
the interactive print/gets block.
- Around line 554-560: The current fast-path returns any untagged
changelog_version which can downgrade the target; modify the conditional so it
only triggers when changelog_version is present, untagged, AND equals the repo's
current_version (i.e., change the if to: if changelog_version &&
changelog_version == current_version && !version_tagged?(monorepo_root,
changelog_version) ), ensuring you compare the same types/format used by
current_version and changelog_version.
---
Nitpick comments:
In `@react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb`:
- Around line 53-67: Add two specs covering the new branches: one that calls
resolve_version_input with a changelog version equal to the current gem version
but with the git tag absent (simulate tag missing) and assert the expected
return/behavior for that branch; and one that calls confirm_release! with a
missing or empty changelog_path (simulate nil/"" path) and assert the expected
error/return for that branch. Place these examples alongside the existing
compute_target_gem_version specs in
react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb and reference
the resolve_version_input and confirm_release! methods so the new control-flow
branches in rakelib/release.rake are exercised.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d9343e22-b076-4e09-b195-899d0eb3d137
📒 Files selected for processing (2)
rakelib/release.rakereact_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb
Review: Fix release script — RC version computation and changelog enforcementThe two root-cause fixes are correct and well-reasoned. The Gem::Version comparison (== for untagged same-version) and the patch -> strip-prerelease behavior both match gem-release semantics, and the new tests cover the key cases clearly. A few things worth addressing before merging: 1. version_tagged? only checks local tags (inline comment on line 538) 2. Silent abort on non-interactive stdin (inline comment on line 416) 3. Confirmation blocks automated pre-release runs (inline comment on line 760) 4. confirm_release! has no tests (inline comment near line 202 in spec) Positive notes:
|
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
rakelib/release.rake (1)
398-417:⚠️ Potential issue | 🟠 MajorMissing changelog still isn't blocking the release path.
Line 400 detects the exact failure case, but Lines 409-417 still let a
ycontinue. Because Line 760 now invokes this before publish, the task can still push/tag/publish artifacts and only skip the GitHub release afterward, which is the same gap this PR is trying to close.🛠️ Proposed fix
def confirm_release!(version:, monorepo_root:) changelog_path = File.join(monorepo_root, "CHANGELOG.md") has_changelog = extract_changelog_section(changelog_path: changelog_path, version: version) + abort "❌ Could not find `### [#{version}]` in CHANGELOG.md. Run /update-changelog before releasing." unless has_changelog puts "" puts "################################################################################" puts "RELEASE CONFIRMATION" puts "################################################################################" puts " Version: #{version}" - if has_changelog - puts " Changelog: ✓ section found" - else - puts " Changelog: ✗ MISSING — no GitHub release will be created" - puts " Run /update-changelog to add entries before releasing." - end + puts " Changelog: ✓ section found" puts "################################################################################" print "Proceed with release? [y/N] " $stdout.flush answer = $stdin.gets&.strip&.downcase abort "Release aborted." unless answer == "y" endAlso applies to: 760-760
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rakelib/release.rake` around lines 398 - 417, The confirm_release! method currently allows proceeding even when has_changelog is false; change confirm_release! so that if extract_changelog_section (has_changelog) is false it immediately aborts with a clear message (e.g., "Release aborted: missing CHANGELOG section for #{version}") before prompting for confirmation, ensuring missing changelog blocks any subsequent publish/tag/push steps invoked later (affecting callers that run confirm_release! before publish).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rakelib/release.rake`:
- Around line 537-540: The version_tagged? helper uses
tagged_release_gem_versions(monorepo_root, fetch_tags: false) which only checks
the local tag view while later policy validation fetches tags, causing a
mismatch; change version_tagged? to call
tagged_release_gem_versions(monorepo_root, fetch_tags: true) (or accept and
forward a fetch_tags parameter) so both auto-resolution and policy validation
use the same tag view, and make the same change for the similar block covering
lines 554-562 that also calls tagged_release_gem_versions with fetch_tags:
false.
---
Duplicate comments:
In `@rakelib/release.rake`:
- Around line 398-417: The confirm_release! method currently allows proceeding
even when has_changelog is false; change confirm_release! so that if
extract_changelog_section (has_changelog) is false it immediately aborts with a
clear message (e.g., "Release aborted: missing CHANGELOG section for
#{version}") before prompting for confirmation, ensuring missing changelog
blocks any subsequent publish/tag/push steps invoked later (affecting callers
that run confirm_release! before publish).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 84ba956b-792e-49f9-86fb-212b4e9d0df0
📒 Files selected for processing (5)
docs/oss/building-features/node-renderer/basics.mddocs/oss/migrating/rsc-troubleshooting.mddocs/pro/js-memory-leaks.mdrakelib/release.rakereact_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb
✅ Files skipped from review due to trivial changes (4)
- docs/oss/building-features/node-renderer/basics.md
- docs/pro/js-memory-leaks.md
- docs/oss/migrating/rsc-troubleshooting.md
- react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
Code review findings for this PR (3 issues + minor notes): (1) BEHAVIORAL REGRESSION - dry runs no longer show changelog warning. warn_changelog_missing was unconditional but confirm_release! is skipped for dry runs, so users doing rake release[patch,true] preflight checks get zero changelog feedback now. Suggest splitting display from interactive prompt. (2) DOUBLE TAG FETCH - version_tagged? calls tagged_release_gem_versions with fetch_tags:true, then validate_release_version_policy! does the same, causing two git fetch --tags round-trips. Consider accepting fetch_tags: keyword in version_tagged? and passing false there. (3) STYLE INCONSISTENCY - version_tagged? uses positional args while every other helper in release.rake uses keyword args, making argument-order mistakes easy. Suggest: version_tagged?(monorepo_root:, version:). Minor/non-blocking: (a) dry-run skip for confirm_release! is in the caller with no comment explaining why - add a comment; (b) test name 'falls back to patch bump when changelog version is older than current and untagged' is misleading since version_tagged? is never called in that path. Overall the fix is correct and test coverage is solid. |
| fetch_tags: true | ||
| ) | ||
|
|
||
| confirm_release!(version: resolved_target_gem_version, monorepo_root: release_root) unless is_dry_run |
There was a problem hiding this comment.
Dry runs skip this call entirely, so a user running rake release[patch,true] to pre-check their release gets zero feedback about a missing changelog section — the old warn_changelog_missing was unconditional. Suggest splitting display from the interactive gate:
| confirm_release!(version: resolved_target_gem_version, monorepo_root: release_root) unless is_dry_run | |
| # Always show changelog status; only prompt interactively for real releases. | |
| if is_dry_run | |
| changelog_path = File.join(release_root, "CHANGELOG.md") | |
| unless extract_changelog_section(changelog_path: changelog_path, version: resolved_target_gem_version) | |
| puts "DRY RUN WARNING: No CHANGELOG.md section for #{resolved_target_gem_version} — GitHub release will be skipped." | |
| end | |
| else | |
| confirm_release!(version: resolved_target_gem_version, monorepo_root: release_root) | |
| end |
|
|
||
| def version_tagged?(monorepo_root, version) | ||
| tagged_versions = tagged_release_gem_versions(monorepo_root, fetch_tags: true) | ||
| tagged_versions.include?(version) |
There was a problem hiding this comment.
This always calls tagged_release_gem_versions with fetch_tags: true, which runs git fetch --tags. The validate_release_version_policy! call that follows shortly after also fetches tags with fetch_tags: true, resulting in two remote round-trips per release.
Consider accepting a fetch_tags: keyword so the caller in resolve_version_input can pass false (tags will be refreshed by the policy check):
| tagged_versions.include?(version) | |
| def version_tagged?(monorepo_root:, version:, fetch_tags: true) | |
| tagged_versions = tagged_release_gem_versions(monorepo_root, fetch_tags: fetch_tags) | |
| tagged_versions.include?(version) | |
| end |
| # and the version bumped in a prior step (e.g., RC → stable promotion). | ||
| if changelog_version && | ||
| Gem::Version.new(changelog_version) == Gem::Version.new(current_version) && | ||
| !version_tagged?(monorepo_root, changelog_version) |
There was a problem hiding this comment.
Every other helper in this file uses keyword arguments; version_tagged? is the only exception. Positional args make argument-order errors easy to introduce silently. When you convert version_tagged? to keyword args (see the suggestion on that method), update this call site to match:
| !version_tagged?(monorepo_root, changelog_version) | |
| !version_tagged?(monorepo_root: monorepo_root, version: changelog_version, fetch_tags: false) |
| allow(self).to receive(:version_tagged?).with("/tmp/repo", "16.3.0").and_return(true) | ||
|
|
||
| expect(resolve_version_input("", "/tmp/repo")).to eq("patch") | ||
| end |
There was a problem hiding this comment.
The test name says "older than current and untagged" but version_tagged? is never called in this path (correctly, since the == guard short-circuits before reaching the untagged check). The "untagged" part of the name is misleading.
Suggest: "falls back to patch bump when changelog version is older than current gem version"
…olve-2835 * origin/main: (21 commits) docs: fix profiling node renderer command (#2863) generators: point Pro install fallback to upgrade guide (#2868) Add RSC Flight payload optimization guide (Article 7) (#2827) Migrate from deprecated Async::Variable to Async::Promise (#2832) docs: turn pro quick start into a gateway (#2862) Fix upload-assets endpoint duplicating bundles across directories (#2768) docs: fix stale docs links and help URLs (#2850) docs: replace dead pro.reactonrails.com links (#2851) docs: refresh generator and helper URLs (#2852) Add standalone RSC upgrade guide for existing Pro apps (#2831) Raise docs version floor to 16.4.0 in install/demo guidance (#2610) Fix release script: require changelog, fix RC version computation (#2848) Bump version to 16.5.0 Bump version to 16.5.0.rc.0 Update CHANGELOG.md for 16.5.0.rc.0 (#2847) Docs: add memory leak prevention guide for Node Renderer SSR (#2845) Docs: fix RSC migration gaps found during real-world migration (#2842) Add common mistakes sections to RSC migration guides (#2826) fix: preserve runtime env vars across Bundler.with_unbundled_env (#2836) Skip Pro CI workflows for Dependabot PRs (#2825) ... # Conflicts: # CHANGELOG.md
## Summary - Stamped `### [16.5.1] - 2026-03-27` with two Pro fixes (PRs #2872, #2768) - Removed the `### [16.5.0.rc.0]` section (was already released as 16.5.0 stable) - Consolidated the 16.5.0 section with full entries (previously just said "no changes from rc.0") - Updated diff links at bottom of file ## Skipped PRs (docs/internal only) #2856, #2860, #2857, #2859, #2864, #2870, #2863, #2868, #2827, #2862, #2850, #2851, #2852, #2831, #2610, #2848 ## Test plan - [ ] Verify CHANGELOG.md formatting and diff links are correct - [ ] Run `rake release` (no args) after merge to publish 16.5.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: changes are limited to `CHANGELOG.md` release notes and version/compare links with no runtime code modifications. > > **Overview** > Documents the `16.5.1` release by adding a new section under *Unreleased* with two **[Pro]** fixes (missing packaged rake tasks and avoiding duplicated bundles during remote renderer asset uploads). > > Cleans up the `16.5.0` entry by removing the `16.5.0.rc.0` section and updating the compare-link footer so `unreleased` now starts from `v16.5.1` and `16.5.0` compares from `v16.4.0`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9a6b224. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated changelog to document version 16.5.1 release with consolidated version history and updated comparison links. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
## Summary - Stamped `### [16.5.1] - 2026-03-27` with two Pro fixes (PRs #2872, #2768) - Removed the `### [16.5.0.rc.0]` section (was already released as 16.5.0 stable) - Consolidated the 16.5.0 section with full entries (previously just said "no changes from rc.0") - Updated diff links at bottom of file ## Skipped PRs (docs/internal only) #2856, #2860, #2857, #2859, #2864, #2870, #2863, #2868, #2827, #2862, #2850, #2851, #2852, #2831, #2610, #2848 ## Test plan - [ ] Verify CHANGELOG.md formatting and diff links are correct - [ ] Run `rake release` (no args) after merge to publish 16.5.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: changes are limited to `CHANGELOG.md` release notes and version/compare links with no runtime code modifications. > > **Overview** > Documents the `16.5.1` release by adding a new section under *Unreleased* with two **[Pro]** fixes (missing packaged rake tasks and avoiding duplicated bundles during remote renderer asset uploads). > > Cleans up the `16.5.0` entry by removing the `16.5.0.rc.0` section and updating the compare-link footer so `unreleased` now starts from `v16.5.1` and `16.5.0` compares from `v16.4.0`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9a6b224. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated changelog to document version 16.5.1 release with consolidated version history and updated comparison links. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>


Summary
Two bugs caused the 16.5.0 release to go out without a changelog entry or GitHub release:
compute_target_gem_versiondidn't handle pre-release → stable transitions: When the current version was16.5.0.rc.0and a "patch" bump was requested, it computed16.5.1as the target, butgem bumpactually strips the RC suffix to produce16.5.0. All pre-release validation ran against the wrong version.resolve_version_inputdidn't detect untagged changelog versions: When the latest changelog version equaled the current gem version, it fell back to "patch" even if that changelog version hadn't been released yet. No confirmation was shown before proceeding.Changes
compute_target_gem_version: Now strips the pre-release suffix on patch bump (16.5.0.rc.0+ patch →16.5.0), matchinggem-releasegem behaviorresolve_version_input: Now checks if the latest changelog version is untagged (not yet released) and uses it, even when it matches the current gem version### [16.5.0]section (references RC notes), updated[unreleased]linkTest plan
rake release[patch,true](dry run) from a pre-release version correctly computes the stable versionrake release(no args) detects an untagged changelog version and uses itbundle exec rake "sync_github_release[16.5.0]"to create the missing GitHub release🤖 Generated with Claude Code
Note
Medium Risk
Updates release automation (version selection, changelog extraction, and interactive confirmation), which can affect published gem/npm versions and GitHub releases if misconfigured. Changes are well-covered by new specs but should be validated in a real/dry-run release flow.
Overview
Fixes release automation edge cases around RC→stable promotion and changelog handling.
compute_target_gem_versionnow strips prerelease suffixes onpatchbumps (e.g.,16.5.0.rc.0→16.5.0), andresolve_version_inputcan select a changelog version that matches the current gem version when it hasn’t been tagged yet.Adds an interactive
confirm_release!prompt (skipped for dry runs) that displays the target version and whether a non-emptyCHANGELOG.mdsection exists; empty sections are treated as missing. Also updatesCHANGELOG.mdwith a16.5.0stable entry and compare links, plus minor docs formatting tweaks.Written by Cursor Bugbot for commit 504a2e8. This will update automatically on new commits. Configure here.
Summary by CodeRabbit