Skip to content

Forward-port release/17.0.0 close-out to main (runbook step 5)#4734

Draft
justin808 wants to merge 29 commits into
mainfrom
forward-port/release-17.0.0-close-out
Draft

Forward-port release/17.0.0 close-out to main (runbook step 5)#4734
justin808 wants to merge 29 commits into
mainfrom
forward-port/release-17.0.0-close-out

Conversation

@justin808

@justin808 justin808 commented Jul 18, 2026

Copy link
Copy Markdown
Member

Why

v17.0.0 final shipped 2026-07-17, but main never received the release branch's stabilizers or the changelog collapse — main's CHANGELOG had no [17.0.0] section (which trips the next release dry-run) and main had regressed shipped Pro functionality: the multi-URL rolling-deploy adapter (#4544, rolling_deploy_previous_urls) existed only on release/17.0.0. This is the runbook's step-5 close-out (see internal/contributor-info/release-train-runbook.md), and the remaining item on #4569's punch list before release/17.0.0 can be deleted.

What

Ran script/release-forward-port --source origin/release/17.0.0 --target <branch> to completion (final state: 0 commits to cherry-pick, 35 skipped, 1 acknowledged-manual skipped):

Test plan

  • script/release-forward-port ... --dry-run0 commits to cherry-pick (plan exhausted)
  • Changelog PR-number audit vs v17.0.0 tag → 0 lost, 0 misplaced; structure [Unreleased] → [17.0.0] → [16.6.0]
  • Pro RuboCop on changed files → no offenses
  • rspec spec/react_on_rails_pro/rolling_deploy_adapters/http_spec.rb spec/react_on_rails_pro/configuration_spec.rb → 111 examples, 0 failures
  • OSS + Pro rake rbs:validate → pass
  • node .github/workflows/hosted-ci-safety.test.cjs → pass
  • node script/generate-llms-full.mjs → regenerated, validated (74 URLs, 8 sections)
  • Prettier clean on changed markdown + CHANGELOG

Merge notes

Squash-merge collapses the per-pick -x footers; that's acceptable because release/17.0.0 is deleted after this lands (tags remain the durable record). After merge: delete release/17.0.0 and close #4569 (fleet bumps are delegated to #3898/#4713).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Rolling deploys can now retrieve bundles from multiple previous deployment endpoints, improving resilience during promotions.
    • Previous deployment sources support comma-separated values and ordered fallback behavior.
  • Bug Fixes

    • Improved bundle discovery when an endpoint is unavailable or returns invalid data.
    • Added boot-time cache seeding guidance to reduce renderer and Rails version drift.
  • Breaking Changes

    • Replace rolling_deploy_previous_url with rolling_deploy_previous_urls.
    • Remove config.server_render_method before upgrading to v17.
  • Documentation

    • Expanded migration, deployment, security, and troubleshooting guidance.

justin808 and others added 29 commits July 17, 2026 14:14
Stamps the `17.0.0.rc.7` changelog header and adds the user-visible
entries merged into `release/17.0.0` since `v17.0.0.rc.6` that were not
yet reflected in `CHANGELOG.md`:

- **Fixed**: OSS renders no longer compute/emit Pro-only
generated-stylesheet metadata (#4395)
- **Fixed**: `create_render_options` no longer mutates the caller's
options hash (#4396)
- **Fixed**: locale-file regeneration check no longer reads the whole
file and correctly detects a legacy import after custom content (#4398)
- **Changed**: `[Pro]` removed unused `addressable`/`rainbow` runtime
gem dependencies (#4422)
- **Fixed**: `[Pro]` static RSC payload script stripping is robust to
generated body-shape changes (#4477)
- Updated the existing `create-react-on-rails-app` chalk→picocolors
entry to also credit the color-fallback-parity follow-up (#4473)
- Updated the existing Pro-by-default `create-react-on-rails-app` entry
to also credit the matching `prompts.yml` AI-agent prompt update (#4232)

Ran the classification-sweep helper over
`v17.0.0.rc.6..origin/release/17.0.0` (175 merged PRs, no `UNKNOWN`
rows) and cross-checked every PR number against the current changelog to
find the gaps above; everything else in range was either already
documented or is internal/docs/CI/release-process and intentionally
excluded per the changelog policy.

- [x] `bundle exec rake "update_changelog[rc]"` computed and stamped
`17.0.0.rc.7` from git tags, updated compare links
- [x] Verified `[unreleased]` and `[17.0.0.rc.7]` compare links anchor
correctly
- [x] Verified `CHANGELOG.md` ends with a trailing newline
- [x] Pre-commit/pre-push hooks (prettier, trailing-newlines,
markdown-links) passed

(cherry picked from commit 41ac54e)
Forward-port record: the readiness-probe changes from release/17.0.0 are
already present on main; this empty commit records the -x evidence so
script/release-forward-port treats the commit as ported.

(cherry picked from commit 737f0eb)
Forward-port record: this release/17.0.0 fix reached main inside the
squashed forward-port PR #4538 (b6674a5), which script/release-forward-port
cannot attribute per-commit. Empty commit records the -x evidence.

(cherry picked from commit 729759c)
Forward-port record: this release/17.0.0 fix reached main inside the
squashed forward-port PR #4538 (b6674a5), which script/release-forward-port
cannot attribute per-commit. Empty commit records the -x evidence.

(cherry picked from commit 1743394)
Forward-port record: this release/17.0.0 fix reached main inside the
squashed forward-port PR #4538 (b6674a5), which script/release-forward-port
cannot attribute per-commit. Empty commit records the -x evidence.

(cherry picked from commit 1c850fd)
…e command (#4539)

Two documentation/process fixes surfaced while running the RC testing
plan against **17.0.0.rc.7** (release-gate tracker #3823).

guide
The removal is a breaking change (PR #4423) and is in the CHANGELOG, but
it was **missing from the "Upgrading to v17" migration guide**. An app
that still has `config.server_render_method = ...` in its initializer
now hits `NoMethodError` at boot, and the guide never told the user to
delete it. Adds the migration bullet (delete the line; `doctor` flags
it; use Pro's Node renderer for a standalone rendering process).

The documented command

```bash
bundle exec rspec react_on_rails/spec/react_on_rails/generators
```

run from the workspace root fails with `LoadError: cannot load such file
-- rails` — the root workspace bundle has no Rails. CI runs these specs
in the `react_on_rails/` gem bundle (whose Gemfile provides Rails).
Updated the doc to run them there:

```bash
(cd react_on_rails && bundle exec rspec spec/react_on_rails/generators)
```

Verified: run correctly, the generator specs pass **398 examples, 0
failures**.

Required by the `check-llms-full` guard because the upgrade guide
changed. `node script/generate-llms-full.mjs --check` passes.

Both are cheap, in-window fixes for the current release candidate. #1 is
Lane 4a's single promotion-blocking gap; #2 makes the plan's own gate
command actually runnable.

- `pnpm exec prettier --check` on both docs: clean
- `node script/generate-llms-full.mjs --check`: `files are current`
- lefthook pre-commit (trailing-newlines, markdown-links, prettier):
pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit afab3e5)
Forward-port record: this release/17.0.0 commit's content is already on
main (via squashed forward-port or main-origin backport plus separately
forward-ported review fixes). Empty commit records the -x evidence for
script/release-forward-port.

(cherry picked from commit 793700a)
Forward-port record: this release/17.0.0 commit's content is already on
main (via squashed forward-port or main-origin backport plus separately
forward-ported review fixes). Empty commit records the -x evidence for
script/release-forward-port.

(cherry picked from commit f510f14)
Forward-port record: this release/17.0.0 commit's content is already on
main (via squashed forward-port or main-origin backport plus separately
forward-ported review fixes). Empty commit records the -x evidence for
script/release-forward-port.

(cherry picked from commit 658a63e)
Forward-port record: this release/17.0.0 commit's content is already on
main (via squashed forward-port or main-origin backport plus separately
forward-ported review fixes). Empty commit records the -x evidence for
script/release-forward-port.

(cherry picked from commit ded1858)
Forward-port record: this release/17.0.0 commit's content is already on
main (via squashed forward-port or main-origin backport plus separately
forward-ported review fixes). Empty commit records the -x evidence for
script/release-forward-port.

(cherry picked from commit c31bc69)
Forward-port record: this release/17.0.0 commit's content is already on
main (via squashed forward-port or main-origin backport plus separately
forward-ported review fixes). Empty commit records the -x evidence for
script/release-forward-port.

(cherry picked from commit 8601d96)
- Stamps the next release-candidate changelog section, `17.0.0.rc.8`, on
`release/17.0.0` using the repo rake task.
- Adds missing user-visible release notes for PRs #4529 and #4530.
- Carries the existing #4541 breaking-change entry into the new RC
section, leaves prior RC sections intact, and keeps compare links
chained from `v17.0.0.rc.7` to `v17.0.0.rc.8`.

Range: `v17.0.0.rc.7..origin/release/17.0.0`.

| PR | Title | Result | Category | Reason |
| --- | --- | --- | --- | --- |
| #4519 | Fix ShakaPerf renderer readiness probe | no-entry |
release-process | Fixes the hosted ShakaPerf release-gate workflow probe
and safety test; no package runtime behavior changes. |
| #4529 | Fix Pro RSC route errors reaching ErrorBoundary | entry-needed
| Pro runtime | Changes Pro RSC runtime cache/error handling so deferred
route fetch failures reach app error boundaries reliably. |
| #4530 | Fix RSC doctor Rspack package resolution | entry-needed | Pro
runtime | Fixes user-visible RSC diagnostics/startup checks by resolving
`@rspack/core` from the configured app dependencies. |
| #4521 | Update demo-fleet metadata from RC 7 inspection | no-entry |
internal | Updates contributor demo-fleet metadata and verification
prerequisites; no shipped package behavior changes. |
| #4539 | Docs: v17 server_render_method removal + fix rc-testing
generator gate command | no-entry | internal | Corrects
upgrade/release-testing documentation and generated LLM docs; the actual
`server_render_method` removal was already covered in rc.7. |
| #4541 | Remove undocumented Pro cache class API | entry-needed | Pro
runtime | Removes an undocumented Pro cache class API before final; the
existing breaking-change entry is included in rc.8. |

- Target branch: `release/17.0.0`.
- Release phase: `rc` by release-branch target.
- Per the release-train runbook, after this PR merges the release
operator can cut the RC from `release/17.0.0`; the release task reads
the top changelog header. Forward-port the changelog result back to
`main` when required by the runbook.

- `git fetch --prune origin main
'+refs/heads/release/*:refs/remotes/origin/release/*'` -> passed.
- `.agents/bin/agent-workflow-seam-doctor` -> passed.
- `changelog-merged-prs --self-check` -> parsers OK, GitHub smoke OK.
- `changelog-merged-prs v17.0.0.rc.7..origin/release/17.0.0 --text` -> 6
mapped PR rows, 0 `UNKNOWN` rows.
- `bundle exec rake "update_changelog[rc]"` -> auto-computed and stamped
`17.0.0.rc.8`.
- `git diff --check` -> passed.
- `pnpm exec prettier --check CHANGELOG.md` -> passed.
- Ruby header/link sanity check -> `changelog rc.8 header and links OK`.
- `script/ci-changes-detector origin/release/17.0.0` ->
documentation-only changes; recommended CI jobs: none.
- Pre-commit hook -> trailing-newlines, offline markdown-links, and
Prettier passed.
- Pre-push hook -> branch RuboCop passed (`11 files inspected, no
offenses detected`) and online markdown-links passed (`0 Errors`, 17
redirect warnings).

Labels: none. Changelog-only release-target PR; no hosted CI expansion
recommended by the detector.

(cherry picked from commit b04ffd5)
Fixes slow SSR after a rolling deploy under the staging-to-production promotion model, where the promoted image was pre-seeded with staging's previous bundle instead of production's draining bundle.

Key changes:
- Gem: renamed config.rolling_deploy_previous_url to config.rolling_deploy_previous_urls. The built-in HTTP adapter now accepts a single URL, a comma-separated string, or an Array; discovery unions bundle hashes across every endpoint and fetch tries each endpoint in order (first hit wins), with graceful per-endpoint failure. Seeding from more than one endpoint (staging + production) lets a promoted image carry the promotion target's draining bundle.
- Docs: new "Promotion deploys need a boot seed" guidance (build-time vs boot seed, the two-pending-promotions case, readiness-gate-on-completion), and renderer-topology awareness (renderer-before-Rails ordering applies only to the separate-workloads topology; same-workload deploys atomically) cross-linked with container-deployment.md.
- Domain records: react_on_rails_pro/CONTEXT.md, ADR 0001, CONTEXT-MAP.

Breaking change (RC-only): the singular rolling_deploy_previous_url was introduced during the 17.0.0 RC cycle and never shipped in a stable release, so the rename is a free change within 17.0.0 rather than a break for any released version. Rename any config.rolling_deploy_previous_url and the ROLLING_DEPLOY_PREVIOUS_URL build arg to their plural forms.

Targeted at release/17.0.0 (rc phase, development mode); forward-port to main via git cherry-pick -x.

(cherry picked from commit cb79ee7)
Forward-port record: intermediate RC pin superseded by the stable
19.2.1 pin already on main (#4672 / 02dc83c). Picking it would
regress the pin; recording -x evidence so the helper skips it.

(cherry picked from commit 3acfc44)
Forward-port record: backport of main PR #4551 (176dc8a), which is
already live on main. Recording -x evidence so the helper skips it.

(cherry picked from commit c16b4bd)
Forward-port record: backport of main PR #4564 (9d470c4), already
live on main. Recording -x evidence so the helper skips it.

(cherry picked from commit b70a350)
Stamps the 17.0.0.rc.9 release notes for post-RC.8 stabilizing work on
`release/17.0.0`.

- Multi-URL Pro rolling-deploy boot seeding (#4544)
- Pro streamed RSC CSS reveal gating (#4573)
- Published `react-on-rails-rsc@19.2.1-rc.1` scaffolding pin (#4587)

- `git diff --check`
- Pre-commit Markdown link and formatting checks

(cherry picked from commit 0c01f54)
Forward-port record: backport of work already live on main (#4671<-scanner
fix on main; #4675<-#4652; #4679<-#4658; #4686<-#4680 follow-up), with
release-specific metadata that must not return to main. Recording -x
evidence so the helper skips it.

(cherry picked from commit 3212b60)
Forward-port record: backport of work already live on main (#4671<-scanner
fix on main; #4675<-#4652; #4679<-#4658; #4686<-#4680 follow-up), with
release-specific metadata that must not return to main. Recording -x
evidence so the helper skips it.

(cherry picked from commit ec81b6c)
Forward-port record: backport of work already live on main (#4671<-scanner
fix on main; #4675<-#4652; #4679<-#4658; #4686<-#4680 follow-up), with
release-specific metadata that must not return to main. Recording -x
evidence so the helper skips it.

(cherry picked from commit 4ab97d6)
Forward-port record: backport of work already live on main (#4671<-scanner
fix on main; #4675<-#4652; #4679<-#4658; #4686<-#4680 follow-up), with
release-specific metadata that must not return to main. Recording -x
evidence so the helper skips it.

(cherry picked from commit 6a59bff)
(cherry picked from commit 98ebd89)
React on Rails `17.0.0.rc.11` needs focused release notes for the
user-visible changes merged to `release/17.0.0` since `v17.0.0.rc.10`.
Stamping the changelog before publishing lets the release task read the
intended version and generate the corresponding GitHub release notes.

- stamped `17.0.0.rc.11` immediately below `Unreleased`
- moved the existing Pro license/runtime and stable RSC 19.2.1 entries
into the new RC section
- updated the compare links from `v17.0.0.rc.10` to `v17.0.0.rc.11`
- left every earlier RC section intact

| PR | Result | Category | Rationale |
| --- | --- | --- | --- |
| 4660 | entry-needed | Pro runtime | Changes published Pro license
metadata, packaged terms, attribution behavior, and diagnostics; already
represented in the changelog. |
| 4670 | entry-needed | Pro runtime | Changes the Pro/RSC package floor,
generator output, compatibility checks, and shipped artifact license;
already represented in the changelog. |
| 4671 | no-entry | perf-reliability | Corrects the still-unreleased
4660 implementation, including regex-timeout safety; the final
user-visible behavior is already covered by the 4660 entry. |

The mechanical `v17.0.0.rc.10..origin/release/17.0.0` sweep returned no
UNKNOWN commits.

- `bundle exec rspec
spec/react_on_rails/update_changelog_rake_helpers_spec.rb` from
`react_on_rails/`: 33 examples, 0 failures
- repository pre-commit checks: trailing newlines, offline Markdown
links, and Prettier passed
- `script/ci-changes-detector origin/release/17.0.0`:
documentation-only; no hosted CI jobs recommended
- `git diff --check origin/release/17.0.0...HEAD`: passed
- structural checks: trailing newline, unique version headings,
newest-first placement, and compare-link endpoints passed

- Sol/xhigh `codex review --base origin/release/17.0.0`: no actionable
regressions; independently reproduced the stamp from the repository
helpers
- Claude Opus/xhigh report-only review with tools disabled: no BLOCKING
or DISCUSS findings
- `/simplify`: skipped as not applicable to a four-line
machine-generated changelog header/link diff

- follow-up commits after first push: 0
- review-fix rounds before first push: 0
- residual risk: the release task must still bump version metadata and
create the `v17.0.0.rc.11` tag after this PR merges; that is the normal
release action, not part of this changelog-only PR

(cherry picked from commit 7f1f9ba)
Prepare the release/17.0.0 train for the 17.0.0.rc.12 release by
stamping the existing Unreleased notes into a versioned changelog
section.

- Entry needed: PR 4679, already represented by its source PR 4658 under
Unreleased.
- No entry: PRs 4675, 4676, 4677, 4684, and 4686 are CI or maintainer
release-process changes.

- git diff --check
- Confirmed CHANGELOG.md is the only changed file.
- Confirmed the rc.12 heading is unique and version headings remain
newest-first.
- Confirmed compare links advance rc.11 to rc.12 and Unreleased starts
at rc.12.
- Confirmed the file retains a trailing newline.
- Pre-commit Markdown link and trailing-newline checks passed.
- Prettier hook skipped because this worktree has no installed Prettier
binary; the generated changelog-only diff was reviewed directly.
- No code tests were run because this changes only release-note
Markdown.

Labels: none. Generated changelog-only change; hosted CI expansion is
unnecessary.

Pre-push review: manual self-review complete; extra AI review and
simplify skipped per the prerelease changelog fast path.

Babysit: off.
(cherry picked from commit 6224bf0)
Prepare the stable React on Rails 17.0.0 changelog from the accepted
`v17.0.0.rc.12` release history. This is a metadata-only change: the
runtime tree remains identical to the accepted RC.

The release tracker is still in development mode with final-promotion
hard gates outstanding, so this PR is intentionally a draft and does not
authorize a stable release.

- Collapsed the 13 `17.0.0.rc.*` changelog sections into one `17.0.0`
section dated 2026-07-16.
- Curated superseded, RC-only, reverted, and contributor-only entries
out of the stable notes.
- Kept 204 unique user-facing PR references and rewrote affected entries
to describe the final stable behavior.
- Updated comparison links to `v16.6.0...v17.0.0` and `v17.0.0...main`.

`origin/release/17.0.0` exactly matched `v17.0.0.rc.12` before this PR,
so the classification range contained no rows and no `UNKNOWN` commits.

The rake release path permits changelog/docs/comment-only commits after
the accepted RC, but `script/release-finish promote` and the
release-train runbook still enforce branch-tip equality with the RC tag.
After this PR merges, the stable release must use `bundle exec rake
"release[17.0.0]"` directly, and only after all hard gates and explicit
promotion signoff are complete.

`SECURITY.md` is not changed here because the invoked changelog workflow
is changelog-only. Its required v17 support-window update remains
outstanding before the final release.

- `git diff --check`
- `pnpm exec prettier --check CHANGELOG.md`
- Changelog structure/link verification: stable heading first, no RC
headings, unique headings, trailing newline, correct compare links
- `bundle exec rake 'update_changelog[release]'` computed `17.0.0` and
coalesced prerelease sections
- `(cd react_on_rails && bundle exec rspec
spec/react_on_rails/update_changelog_rake_helpers_spec.rb)` — 33
examples, 0 failures
- Pre-push Ruby branch lint — 33 files inspected, no offenses
- Pre-push online Markdown link check — 1,396 links, 0 errors
- `script/ci-changes-detector origin/release/17.0.0` —
documentation-only; hosted CI recommendation: none

- Local self-review complete.
- Automated Codex and Claude review attempts did not produce a usable
final verdict (the Codex review expanded into the release-branch
history; Claude stalled during MCP startup). No findings were generated
from either attempt.
- Post-push churn: one mechanical Prettier correction (removed an extra
blank line); formatting, diff, pre-commit, and pre-push validation were
rerun before the force-with-lease update.

(cherry picked from commit 44d2517)
…17.0.0-close-out

* origin/main:
  Add rsc-guardrails agent skill + payload-escaping regression test + advisory hook (#4599)
  Regenerate llms-full references (#4728)
  CI: make hosted dispatch exact-head idempotent (#4692)
  Docs: normalize version floors, release metadata, and branch links (#4709)
  Docs: fix node-renderer startup, versions, and missing config options (#4707)
  Docs: fix Shakapacker build & migration recipes (#4703) (#4708)
  Docs: document Pro ExecJS profiling prerequisites & missing cached helpers (#4706)
  docs: correct OSS helper & API-reference examples (broken/stale snippets) (#4637)
  Docs: correct immediate_hydration removal details (#4638) (#4640)
  CI: route gem generator specs by changed paths (#4691)
  Prevent oversized GitHub release failures (#4714)
  docs(pro): fix RSC & streaming setup examples (runtime errors + stale behavior) (#4636)
  Fix demo fleet verification metadata (#4689)
  Fix html_options hash mutation causing FrozenError and state leaks (#4693)
  Fix knip duplicate-export failure breaking lint on main (#4718)
  [Pro] Demote async-props closed-stream races from error to debug (fixes #4325) (#4719)

# Conflicts:
#	CHANGELOG.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@justin808

Copy link
Copy Markdown
Member Author

+ci-run-hosted

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR adds multi-source rolling-deploy bundle discovery and ordered fetching, updates Pro configuration and tests, documents boot-time seeding and deployment ordering, expands upgrade guidance, and revises changelog and context documentation.

Changes

Rolling-deploy multi-source seeding

Layer / File(s) Summary
Multi-source adapter contract and behavior
react_on_rails_pro/lib/..., react_on_rails_pro/sig/..., react_on_rails_pro/spec/...
Renames the configuration to rolling_deploy_previous_urls, supports string, CSV, and array inputs, aggregates hashes across endpoints, fetches in order, validates URLs, and adds coverage.
Rolling-deploy correctness guidance
react_on_rails_pro/CONTEXT.md, react_on_rails_pro/docs/adr/..., docs/pro/..., llms-full-pro.txt, CONTEXT-MAP.md, docs/oss/...
Documents build-time versus boot-time seeding, multi-source fallback, renderer-before-Rails ordering, readiness behavior, promotion constraints, and RSC relationships.
Upgrade and contributor guidance
docs/oss/upgrading/..., llms-full.txt, internal/contributor-info/...
Documents removal of config.server_render_method, doctor-based cleanup, and the required gem-bundle location for generator specs.
Release and changelog updates
CHANGELOG.md
Revises Unreleased and 17.0.0 entries, adds Pro runtime and rolling-deploy notes, removes the legacy license warning entry, and updates comparison links.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Renderer
  participant RollingDeployAdapter
  participant PreviousDeployments
  participant RailsRelease
  Renderer->>RollingDeployAdapter: run boot-time pre-seed
  RollingDeployAdapter->>PreviousDeployments: discover and fetch draining bundle
  PreviousDeployments-->>RollingDeployAdapter: return bundle or fallback result
  RollingDeployAdapter-->>Renderer: complete seed
  Renderer-->>RailsRelease: report readiness
  RailsRelease->>RailsRelease: release Rails after renderer readiness
Loading

Possibly related PRs

Suggested labels: ready-for-hosted-ci

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the changeset: it forward-ports the 17.0.0 close-out to main as runbook step 5.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch forward-port/release-17.0.0-close-out

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown

Greptile Summary

This PR forward-ports the v17 release close-out to main. The main changes are:

  • Multi-endpoint discovery and fallback for HTTP rolling-deploy bundles.
  • Plural rolling-deploy URL configuration with String and Array support.
  • A consolidated final 17.0.0 changelog section.
  • Updated release, deployment, and generated reference documentation.

Confidence Score: 5/5

The changed flow looks mergeable after correcting one release-note example.

  • Multi-endpoint failures are isolated and later endpoints remain available.
  • Bundle hashes are validated before URL or filesystem use.
  • Ruby and RBS configuration shapes agree.
  • One changelog instruction causes a boot error when copied.

CHANGELOG.md

Important Files Changed

Filename Overview
react_on_rails_pro/lib/react_on_rails_pro/rolling_deploy_adapters/http.rb Adds URL normalization, manifest unioning, and ordered fallback across rolling-deploy endpoints.
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb Replaces the singular rolling-deploy URL setting with the plural multi-URL setting.
react_on_rails_pro/sig/react_on_rails_pro/configuration.rbs Updates the configuration contract to accept a URL string or an array of strings.
react_on_rails_pro/spec/react_on_rails_pro/rolling_deploy_adapters/http_spec.rb Covers multi-endpoint discovery, fallback order, first-hit behavior, and comma-separated input.
CHANGELOG.md Consolidates the final release notes but retains one removed singular configuration name.

Reviews (1): Last reviewed commit: "Regenerate llms-full artifacts after for..." | Re-trigger Greptile

Comment thread CHANGELOG.md
- **[Pro]** **HTTP rolling-deploy endpoint auto-mount**: Configuring `config.rolling_deploy_adapter = ReactOnRailsPro::RollingDeployAdapters::Http` now automatically mounts `ReactOnRailsPro::RollingDeploy::BundlesController` at `config.rolling_deploy_mount_path` (default `/react_on_rails_pro/rolling_deploy`). Set the mount path to `nil` or blank to opt out and keep a manual `draw_routes` mount; apps that previously mounted the default route manually should remove that route or give secondary manual mounts a distinct `as_prefix:` to avoid duplicate named-route errors. Fixes [Issue 3476](https://github.com/shakacode/react_on_rails/issues/3476). [PR 3504](https://github.com/shakacode/react_on_rails/pull/3504) by [justin808](https://github.com/justin808).
- **[Pro]** **`unstable_cache` for React Server Component fragment caching**: New experimental `unstable_cache(fn, options)` wrapper memoizes a server component's serialized RSC payload — replaying the stored bytes on a cache hit and tee-ing output to both the response and the cache store on a miss. Ships with a `CacheHandler` interface and a default in-memory LRU handler (register custom backends via `registerCacheHandler`), plus tag-based invalidation through `unstable_revalidateTag(tag)` that broadcasts across all Node Renderer workers via a new `POST /cache/revalidate-tag` endpoint and a Ruby-side `ReactOnRailsPro::RSCCache.revalidate_tag(tag)`. Closes [Issue 3324](https://github.com/shakacode/react_on_rails/issues/3324). [PR 3325](https://github.com/shakacode/react_on_rails/pull/3325) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
- **[Pro]** **Node Renderer integration API now exposes lifecycle hooks**: `react-on-rails-pro-node-renderer/integrations/api` now exports the tracing reset, provider-state, Fastify lifecycle, and worker shutdown hooks needed by integrations such as OpenTelemetry, keeping integrations inside the supported public boundary. Fixes [Issue 3419](https://github.com/shakacode/react_on_rails/issues/3419). [PR 3456](https://github.com/shakacode/react_on_rails/pull/3456) by [justin808](https://github.com/justin808).
- **[Pro]** **Built-in HTTP rolling-deploy adapter (scaffold)**: New `ReactOnRailsPro::RollingDeployAdapters::Http` adapter pairs with a mountable `ReactOnRailsPro::RollingDeploy::BundlesController` so the currently-deployed Rails server can directly serve previously-deployed bundles to the next deploy's build CI — no S3 bucket, IAM, or extra gem required. The controller exposes authenticated `GET /manifest` and `GET /bundles/:hash` endpoints using bearer-token auth (constant-time compare, 32-byte minimum), and the adapter pulls bundle tarballs (stdlib-only gzip/tar compose-extract with path-traversal proofing, regular-files-only guards, and a 200 MB zip-bomb cap). Configure via `config.rolling_deploy_adapter = ReactOnRailsPro::RollingDeployAdapters::Http`, `config.rolling_deploy_token`, and `config.rolling_deploy_previous_url`. See `docs/pro/rolling-deploy-adapters.md` for setup. This is part 1 of a multi-PR series — a hard HTTPS gate, streaming download, and additional hardening land in follow-ups. [PR 3379](https://github.com/shakacode/react_on_rails/pull/3379) by [justin808](https://github.com/justin808).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Release Notes Use Removed Setting

This setup instruction still names rolling_deploy_previous_url, but the updated configuration exposes only rolling_deploy_previous_urls. Copying this example into an initializer raises NoMethodError during application boot.

Context Used: CLAUDE.md (source)

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef37f0747f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# (down, 404, malformed manifest) yields [] for that base and does not
# abort discovery for the others — the point of multiple endpoints is
# resilience, so one unreachable source must not blank the rest.
bases.flat_map { |base| manifest_hashes(base) }.uniq

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve partial manifest results under multi-source timeouts

When one configured source is slow during a boot/build seed, this serial union runs inside RollingDeployCacheStager.fetch_hashes_from_adapter's 10s Timeout.timeout, but each manifest_hashes request can spend up to the HTTP adapter's 5s open timeout plus 4s read timeout. With multiple sources, a healthy source can return hashes and a later hung source can still trigger the outer timeout before the method returns, causing the stager to discard all hashes and skip seeding. Keep partial hashes or deadline-limit each source so one slow endpoint cannot blank the others.

Useful? React with 👍 / 👎.

Comment on lines +121 to +123
bases.each do |base|
payload = fetch_from(base, bundle_hash)
return payload if payload

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid timing out before later bundle sources

When a hash was discovered from a later URL (for example production after staging), fetch still probes every earlier URL first. The seeding path wraps the entire adapter.fetch(hash) in a 30s timeout, and a single fetch_from can use the full 5s open plus 25s read budget before returning nil, so an unreachable staging endpoint can exhaust the fetch budget before the healthy production endpoint is attempted. This makes the new staging+production promotion path miss the target draining bundle; cache the manifest's hash-to-source mapping or impose per-source deadlines before falling through.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/oss/upgrading/upgrading-react-on-rails.md`:
- Around line 139-145: Reorder the upgrade instructions so users run `bin/rake
react_on_rails:doctor` before removing deprecated options from
`config/initializers/react_on_rails.rb`. Then instruct them to remove every
flagged option before booting the application, preserving the existing list of
options and fix guidance.

In `@llms-full.txt`:
- Line 16324: Update the source documentation link for the rolling-deploy
adapter so generated references use docs/pro/rolling-deploy-adapters.md from the
repository root instead of traversing ../../../pro. Adjust the
artifact-generation normalization as needed, then regenerate llms-full.txt and
verify the corrected link appears there.
🪄 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: d3998b6e-88d4-4a38-a020-3d6b9fb85604

📥 Commits

Reviewing files that changed from the base of the PR and between a33d163 and ef37f07.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • CONTEXT-MAP.md
  • docs/oss/building-features/node-renderer/container-deployment.md
  • docs/oss/upgrading/upgrading-react-on-rails.md
  • docs/pro/rolling-deploy-adapters.md
  • docs/pro/rolling-deploy-custom-adapters.md
  • internal/contributor-info/rc-testing-plan.md
  • llms-full-pro.txt
  • llms-full.txt
  • react_on_rails_pro/CONTEXT.md
  • react_on_rails_pro/docs/adr/0001-boot-seed-rolling-deploy-bundles.md
  • react_on_rails_pro/lib/react_on_rails_pro/configuration.rb
  • react_on_rails_pro/lib/react_on_rails_pro/rolling_deploy_adapters/http.rb
  • react_on_rails_pro/sig/react_on_rails_pro/configuration.rbs
  • react_on_rails_pro/spec/react_on_rails_pro/rolling_deploy_adapters/http_spec.rb

Comment on lines +139 to +145
4. Remove every removed configuration option from `config/initializers/react_on_rails.rb` **before booting**. Any of the options listed in the Breaking Changes above (`config.generated_assets_dirs`, `config.skip_display_none`, `config.defer_generated_component_packs`, `config.server_render_method`) now raises `NoMethodError` at boot. Run the doctor task, which flags each remaining option with the exact fix:

```bash
bin/rake react_on_rails:doctor
```

5. Run RuboCop, your app's test suite, and asset build after the Ruby and package updates. The Ruby

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Run the doctor check before removing the stale options.

This step currently instructs users to remove every option and then run doctor to find remaining options. Reorder it so doctor identifies the stale entries first, followed by removal and application boot; otherwise the documented detection path is ineffective.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/oss/upgrading/upgrading-react-on-rails.md` around lines 139 - 145,
Reorder the upgrade instructions so users run `bin/rake react_on_rails:doctor`
before removing deprecated options from `config/initializers/react_on_rails.rb`.
Then instruct them to remove every flagged option before booting the
application, preserving the existing list of options and fix guidance.

Comment thread llms-full.txt
**Disadvantages:**

- **Version drift risk** — During rolling deploys, Rails and the Node Renderer may briefly run different versions. While protocol changes are rare, this is a risk to monitor.
- **Version drift risk** — During rolling deploys, Rails and the Node Renderer roll independently and briefly run different bundle versions, so the renderer can receive SSR requests for a bundle it hasn't cached. Mitigate this with a [rolling-deploy adapter](../../../pro/rolling-deploy-adapters.md) (Pro): it pre-seeds the new renderer with the draining bundle and makes the renderer-before-Rails ordering explicit. This risk (and that mitigation) is **specific to this separate-workloads option** — Options 1–2 share one lifecycle and cannot drift.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the relative link in the generated artifact.

Because llms-full.txt is at the repository root, ../../../pro/rolling-deploy-adapters.md resolves outside the repository and will not reach the documented target. Normalize links during artifact generation to docs/pro/rolling-deploy-adapters.md (then regenerate the file).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@llms-full.txt` at line 16324, Update the source documentation link for the
rolling-deploy adapter so generated references use
docs/pro/rolling-deploy-adapters.md from the repository root instead of
traversing ../../../pro. Adjust the artifact-generation normalization as needed,
then regenerate llms-full.txt and verify the corrected link appears there.

**Status:** accepted

When the production image is produced by **promoting the staging image**
(`upstream: hichee-staging` in Control Plane), a build-time pre-seed cannot know

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This ADR names an internal deployment identifier — hichee-staging (and the "Control Plane" tool) — in a doc that's committed to the public repo (react_on_rails_pro/docs/adr/, not under internal/).

The repo's own release runbook says explicitly:

Treat shakacode/hichee and Pro details as private: public tracker comments may say install/build/smoke/CI passed or failed, but must not expose private logs, URLs, screenshots, customer data, secrets, or proprietary Pro source details.
internal/contributor-info/release-verification-runbook.md:103

hichee is ShakaCode's own private dogfooding app, referenced elsewhere only inside internal/ docs. This ADR is the one place it leaks into non-internal/ documentation. Since react_on_rails_pro/docs/ is otherwise generic, published guidance (see the sibling docs/pro/rolling-deploy-adapters.md), consider genericizing this line — e.g. "a promoted staging image" instead of the specific upstream: hichee-staging config value and "Control Plane" tool name — or moving this ADR under internal/ if it's meant to stay implementation-specific.

Comment thread CHANGELOG.md
differs from the current process context. Fixes
[Issue 4523](https://github.com/shakacode/react_on_rails/issues/4523).
[PR 4530](https://github.com/shakacode/react_on_rails/pull/4530) by
[justin808](https://github.com/justin808).
- **`hydrate_on: visible` no longer leaks a detached root or blocks re-hydrating a replacement node**: When a `hydrate_on: visible` target was detached from the DOM before it became visible, the intersection observer left a stale scheduled root entry that kept the removed node reachable and could stop a replacement node with the same DOM id from scheduling its own hydration. The observer now runs its scheduled callback after disconnecting from a detached target; the callback's existing `isConnected` guard deletes the stale entry without hydrating the removed node, so a fresh node with the same id schedules cleanly. Fixes [Issue 4328](https://github.com/shakacode/react_on_rails/issues/4328). [PR 4374](https://github.com/shakacode/react_on_rails/pull/4374) by [justin808](https://github.com/justin808).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor/pre-existing, not introduced by this PR: this bullet and the one at line 623 (`hydrate_on: visible` cleanup no longer retains detached roots) both cite Issue 4328 / PR 4374 and describe the same fix with different wording — a leftover duplicate in the [17.0.0] section from an earlier changelog pass. Since this PR's description calls out an explicit PR-number audit of the changelog collapse ("zero lost, zero misplaced"), worth squashing these two into one bullet while you're in here, even though the dupe predates this PR.

@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review

This PR forward-ports release/17.0.0's close-out work to main: it collapses the rc.1–rc.12 changelog history into a single [17.0.0] section, and forward-ports the one piece of shipped Pro functionality that never landed on main — the multi-URL rolling-deploy adapter (rolling_deploy_previous_urlrolling_deploy_previous_urls, #4544).

Code changes (http.rb / configuration.rb / configuration.rbs)

The rename and multi-endpoint logic in ReactOnRailsPro::RollingDeployAdapters::Http is solid:

  • configured_previous_urls correctly normalizes a single string, comma-separated string, or Array (including comma-separated entries inside an Array) into a deduped, scheme-validated list — Array("a,b") wraps a plain string as intended, so single-string configs still work.
  • previous_bundle_hashes unions hashes across all endpoints and isolates a single endpoint's failure (manifest_hashes rescues per-base, so one dead endpoint doesn't blank discovery for the others) — matches the stated resilience goal.
  • fetch tries endpoints in order and short-circuits on first hit; fetch_from owns temp-dir cleanup per attempt so a failed pull from endpoint A doesn't leave debris before trying endpoint B.
  • The RBS signature (String | Array[String]) matches the new normalization logic, and the spec file was updated in lockstep with solid new coverage (union/dedupe, per-endpoint failure isolation, in-order fetch fallback, comma-separated string form).
  • No leftover references to the old rolling_deploy_previous_url singular name anywhere in code, docs, or the regenerated llms-full*.txt.

The breaking rename has no back-compat shim (old rolling_deploy_previous_url= now raises NoMethodError), but that's consistent with how the other v17 config removals are documented and is called out explicitly in both the CHANGELOG and the PR's "Breaking Changes" summary.

Docs

The new docs/pro/rolling-deploy-adapters.md / rolling-deploy-custom-adapters.md sections on promotion-deploy boot-seeding, the new ADR, and react_on_rails_pro/CONTEXT.md are thorough and internally consistent (the "boot seed depends on renderer-before-Rails ordering" argument is made and cross-linked in three places consistently).

Findings posted inline

  1. react_on_rails_pro/docs/adr/0001-boot-seed-rolling-deploy-bundles.md:6 — the new ADR names an internal deployment identifier (hichee-staging) and internal tooling ("Control Plane") in a doc committed outside internal/. The repo's own release runbook says to treat shakacode/hichee details as private; this looks like an unintentional leak of an internal codename into public-facing Pro docs.
  2. CHANGELOG.md:410 — pre-existing (not introduced by this PR) duplicate bullet in the [17.0.0] section: the same fix (Issue 4328 / PR 4374, hydrate_on: visible detached-root cleanup) is described twice with different wording (also at line 623). Given this PR explicitly claims a PR-number audit of the changelog collapse, flagging since it's an easy fix while the file is already open.

Not deeply reviewed

The bulk of the diff (CHANGELOG.md, llms-full.txt, llms-full-pro.txt) is mechanical output from script/release-forward-port collapsing already-shipped, already-reviewed content. I spot-checked for duplicate/lost PR references across the [Unreleased] and [17.0.0] sections (found only the one pre-existing duplicate above) rather than diffing every historical bullet line-by-line.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Hosted CI Requested

Triggered 9 workflow(s) for ef37f0747f42.
Skipped 0 workflow(s) with equivalent exact-head coverage.
Mode: optimized hosted CI (path-selected by script/ci-changes-detector).
Added ready-for-hosted-ci, so future commits will keep running optimized hosted CI until +ci-stop-hosted is used.

View progress in the Actions tab.

@github-actions github-actions Bot added the ready-for-hosted-ci Run optimized hosted GitHub CI for this PR label Jul 18, 2026
@justin808
justin808 marked this pull request as draft July 18, 2026 10:09
@justin808

Copy link
Copy Markdown
Member Author

Splitting this close-out per maintainer direction. This PR should not merge as one unit (with or without squash). Replacement sequence: (1) one squashed final changelog reconciliation PR, (2) the still-missing #4539 docs delta as its own PR, (3) the still-missing #4544 rolling-deploy delta as its own PR, then a separate release-forward-port tooling/process PR. Empty evidence commits for changes already on main—including ccd487c—will not be carried into any replacement. I will update this comment/thread with replacement links before closing #4734.

@justin808

Copy link
Copy Markdown
Member Author

Split replacement update: #4742 now supersedes the changelog/release-note portion of this draft. It is a single squashed CHANGELOG.md reconciliation PR. The remaining missing source/docs changes will be proposed one PR at a time after #4742 lands; commits already present on main (including empty provenance-only markers such as ccd487cff469effe68f3cbad863a2b931df019e2) will be skipped.

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

Labels

ready-for-hosted-ci Run optimized hosted GitHub CI for this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

17.0.0 final assembly: cherry-pick stabilizers to release/17.0.0, changelog, tag, publish

1 participant