Upgrade Rails 7.2.3.1 → 8.0.5#2017
Open
jbirdjavi wants to merge 10 commits into
Open
Conversation
bundle update --conservative rails; lockfile churn is rails-family only. cgi remains in the lock via datadog 2.35.0's runtime dep (Rails 8 dropped its own cgi dependency). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
Conservative in-constraint bumps for all 10 gems flagged by the raw advisory DB (48 advisories): concurrent-ruby 1.3.6->1.3.8, crass 1.0.6->1.0.7, faraday 2.14.2->2.14.3, json 2.19.8->2.21.1, loofah 2.25.1->2.25.2, msgpack 1.8.1->1.8.3, net-imap 0.6.4->0.6.4.1, nokogiri 1.19.3->1.19.4 (27 advisories), rails-html-sanitizer 1.7.0->1.7.1, websocket-driver 0.8.0->0.8.2. Lockfile-only; raw `bundle audit check --update` now reports 0 with no --ignore. Supersedes renovate #2014 (nokogiri) and dependabot #2006 (net-imap). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
ruby.yml runs brakeman with --ensure-latest, which exits 5 on 8.0.4. With Rails 8.0.5 the EOLRails warning also clears: scan is now 0 warnings. Supersedes renovate #2011. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
Skeleton-mirroring convention: propshaft declined-default comment replaces the stale sprockets-rails comment (no asset pipeline in this API app), solid_cache/solid_queue/solid_cable + kamal added as commented placeholders with why-notes, thruster placeholder commented (activated by the stacked thruster PR), sqlite3 commented example updated to the 8.0 ">= 2.1" floor, stale kredis leftover deleted, redis moved to the custom section with a why-note (skeleton dropped it; still used for cache + Action Cable), custom section alphabetized (pg folded in, google-apis before googleauth). Pure restructure: Gemfile.lock is byte-identical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
Unreviewed generator output, committed verbatim; the following commit restores custom configuration on top of the new defaults. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
… 8.0
Merge-back on top of the raw app:update output:
- application.rb: restore frozen_string_literal, fileutils require, Ougai
Log::Logger, redis_conf + :redis_cache_store, AMS json_api adapter,
pages mkdir; add HEALTHCHECK_PATH/HEALTHCHECK_ACTION constants above
the Application class; flip load_defaults 7.2 -> 8.0 (all three 8.0
changes are class (a) for this app).
- production.rb: restore public_file_server.enabled = false (nginx
serves; skeleton far-future headers line kept inert for the thruster
PR), active_storage :amazon, secret_key_base/Action Cable forgery,
Rack::Cors, routes default_url_options; comment out skeleton
logger/log_tags (Ougai override landmine) and the mailer
default_url_options example.com host (no real mailers); point
ssl_options exclude + silence_healthcheck_path at the real
/monitors/lb health route via the new constants.
- routes.rb, lograge.rb, ddtrace.rb: consume the health-check constants
(routes via delete_prefix("/"); ddtrace span-drop filter included).
- development.rb: keep 8.0 caching-block restructure; restore
Rack::Cors, log_level :debug, routes default_url_options.
- test.rb: restore custom :memory_store (skeleton is :null_store),
active_job :test adapter, localhost default_url_options.
- filter_parameter_logging.rb: keep 8.0 additions :cvv/:cvc, do NOT
re-add :email (deliberately unfiltered here; noted in-file).
- .gitignore: apply the 8.0 env-file hunk (no tracked .env*.erb; the
image gets config via build ARGs, .dockerignore excludes /.env*).
- Delete stale new_framework_defaults_7_2.rb and the generated
new_framework_defaults_8_0.rb after the flip.
- standardrb --fix for omakase spacing; STDOUT -> $stdout in bin/setup.
Verified by production boot: redis_cache_store effective, Ougai logger
is the sole broadcast target, ssl exclude true only for /monitors/lb,
public_file_server disabled.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
Hunks the 8.0 skeleton changes but app:update does not touch: - .dockerignore: mirror the 8.0 skeleton (env-file comment, drop the !/.env*.erb exception — no such files exist; add the inert Kamal section). /.env* stays excluded with a why-note: image config arrives via build ARGs and the tracked .env must never reach the image. - bin/docker-entrypoint: mirror the 8.0 rewrite (jemalloc via find, last-two-args server detection). Inert parity per the standing fleet ruling — the custom Dockerfile does not wire it as ENTRYPOINT. - config/initializers/permissions_policy.rb: deleted; the 8.0 skeleton drops this file and the app's copy was stock all-commented (untouched since the Rails 7.1 upgrade). - lib/assets/.keep -> script/.keep: full skeleton rename (no sprockets; autoload_lib ignore list unchanged, matching the 8.0 skeleton). Skipped as inapplicable or new-app scaffolding: skeleton ci.yml (app has its own workflows), database.yml sqlite multi-db, app/assets + assets.rb + layout hunks (no asset pipeline), app/channels deletions (generator artifact; this app's Action Cable is real), bin/thrust + Dockerfile CMD/EXPOSE (stacked thruster PR), solid_*/kamal (declined, commented placeholders already in the Gemfile). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
…d by 8.0) Brakeman flagged fingerprint d84924377155… as an obsolete ignore: it suppressed the EOLRails warning for Rails 7.1.5.2, which no longer fires now that the app is on 8.0.5. Same cleanup as canary #140. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
…diff) One-time, deterministic re-dump: schema header [7.1] -> [8.0] and the 8.0 dumper's namespace-qualified pg_catalog.plpgsql extension (re-sorted alphabetically). No table/column/index changes; round-trips via db:schema:load. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
CLAUDE.md said Rails 7.1; README still claimed Ruby 2.6.6 / Bundler 1.17.3 / Rails 5.2.3. Updated to the current Ruby 3.3.10 / Bundler 2.7.2 / Rails 8.0.5. No docs/DECISION_LOG.md in this repo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX
|
I see you added the "On Staging" label, I'll get this merged to the staging branch! |
|
Merge conflict attempting to merge this into staging. Please fix manually. |
knutsenm
approved these changes
Jul 22, 2026
knutsenm
left a comment
Contributor
There was a problem hiding this comment.
Reviewed as part of the fleet-wide Rails 8.0 stack audit. Verified against the diff:
- This is the first fleet repo with real Action Cable (three custom channels +
mount ActionCable.server => "/cable"), so the stray-deletion check mattered here — and passed: the upgrade leavesapp/channels/spec/channelscompletely untouched (empty diff). Only deletions are the defaults file and the fully-commented permissions_policy. - HEALTHCHECK constants wired at all four sites (ssl_options exclude, silence_healthcheck_path, routes, lograge) plus the Datadog span filter, at the real route
/monitors/lb. Ougai preserved; skeleton logger/log_tags commented with the override note. connection_pool < 3.0pin with the reason comment correctly blocks dependabot #2003/#1971 until Rails ≥ 8.1.2; jbuilder 2.15.1;rediskept with why-note (real Cable + cache). Schema re-dump mechanical; no Rails-8 route gotchas; the README staleness fix (Ruby 2.6.6/Rails 5.2.3 claims) is a nice touch.- Security: loofah 2.25.2 + rails-html-sanitizer 1.7.1 land here (master still carries the old ones until this merges). datadog is at 2.35.0 — that's above the CVE-2026-50276 floor (≥ 2.32.0), so no security action needed; just noting it trails the 2.38+ the rest of the fleet converged on, if you want to align while you're in the lockfile.
- All 10 branch commits map one-to-one to the body's list — no narrative drift.
Post-deploy note: once the nginx sidecar is removed, /cable WebSockets flow through thruster — worth a staging smoke test of live-share before the terraform change merges. Branch protection here is strict: true, so #2018 will need the rebase+push after this merges (the body already says so).
🤖 Review drafted with Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Rails 7.2.3.1 → 8.0.5 with
config.load_defaultsflipped to 8.0. The 8.0 defaults change exactly three settings, all class (a) for this app:to_time_preserves_timezone = :zonestrict_freshness = true(freshness checked via ETag before Last-Modified)Regexp.timeout ||= 1(process-global;||=respects any explicit app setting)No app-code deprecations existed before or after the flip; no code changes were required beyond config merge-back.
Commit-by-commit
bundle update --conservative rails; lockfile churn is rails-family only.cgistays in the lock via datadog 2.35.0's runtime dep (Rails 8 dropped its own cgi dependency — expected, don't revert).--ensure-latest, which exits 5 on 8.0.4; with Rails 8.0.5 the EOLRails warning also clears (scan: 0 warnings).Gemfile.lockbyte-identical (details under Adoptions).bin/rails app:update --force— unreviewed generator output committed verbatim so the merge-back is reviewable as its own diff.config.load_defaults 8.0— restores the Ougai logger,:redis_cache_store, AMS json_api adapter, Rack::Cors, custom test-env stores; comments out the skeleton's production logger/log_tags(Ougai override landmine) and the mailerexample.comdefault_url_options; keeps the 8.0 additions tofilter_parameters(:cvv/:cvc) without re-adding:email; introduces the health-path constants (below)..dockerignoremirrored (keeps/.env*excluded with a why-note),bin/docker-entrypointmirrored (inert parity per the standing fleet ruling), stockpermissions_policy.rbdeleted (8.0 skeleton drops it),lib/assets/.keep→script/.keep.docs/DECISION_LOG.mdin this repo.)Security commit (lockfile-only, conservative in-constraint)
All 10 gems flagged by the raw advisory DB (48 advisories):
concurrent-ruby 1.3.6→1.3.8, crass 1.0.6→1.0.7, faraday 2.14.2→2.14.3, json 2.19.8→2.21.1, loofah 2.25.1→2.25.2, msgpack 1.8.1→1.8.3, net-imap 0.6.4→0.6.4.1, nokogiri 1.19.3→1.19.4 (27 advisories), rails-html-sanitizer 1.7.0→1.7.1, websocket-driver 0.8.0→0.8.2.
Raw
bundle exec bundle audit check --updatenow reports 0 vulnerabilities with no--ignore(the org-levelCVE_IGNORESentries become no-ops for this repo). Expected churn notes: the brakeman 8.0.5 bump exists solely for the--ensure-latestCI gate; advisory-DB churn is a treadmill — new advisories published after this PR are new work, not regressions of this commit.Health-path constant extraction
MobileContentApi::HEALTHCHECK_PATH/HEALTHCHECK_ACTIONdefined inconfig/application.rbabove the Application class (fleet merge-back convention), consumed at all 4 sites:config/environments/production.rb—ssl_optionsredirect exclude +silence_healthcheck_pathconfig/routes.rb— viaHEALTHCHECK_PATH.delete_prefix("/")config/initializers/lograge.rb—ignore_actionsconfig/initializers/ddtrace.rb— the Datadog span-drop filter (a rename without this site would silently flood Datadog with healthcheck spans)Adoptions (new-app 8.0 tech)
bin/thrust+ Dockerfile CMD/EXPOSE, then nginx sidecar removal in cru-terraform after deploy).Bot-PR accounting
connection_pool < 3.0— the redis_cache_store conflict is fixed upstream only at Rails >= 8.1.2. These stay blocked until this app reaches 8.1.2+.Out of scope (noted, not changed here)
.env— this repo commits a real.env(fleet-wide pattern; okta/mpd_tool/autonag likewise)..dockerignore /.env*keeps it out of the image. Rotation + untracking is a dedicated fleet remediation sweep, not this PR.# check=error=truedirective, gem-cache layer cleanup (rm -rf ~/.bundle "$BUNDLE_PATH"/ruby/*/cache), build-timebootsnap precompile.[7.1]→[8.0]plus the 8.0 dumper'spg_catalog.plpgsqlextension qualification. Round-trip proven (schema:load on a scratch DB re-dumps byte-identical). No table/column/index changes.Verification (local, CI-verbatim)
CI=true RAILS_ENV=test): 670 examples, 0 failures, 3 pending (same as master)-A -q --ensure-latest: exit 0, 0 warnings, no obsolete ignores; standardrb: 369 files, no offenseszeitwerk:checkclean; test + production eager-load boots clean (production boot with dummy env exercised the real:redis_cache_storeagainst Redis — write/read round-trip OK)/monitors/lb→ 200,/systems→ 200 (real JSON:API payload); zero deprecation warnings in any outputPost-deploy verification (staging, by real request)
ssl_options:assume_ssl+force_sslare enabled with the/monitors/lbexclude — verify redirect/HSTS behavior and that the health check stays exempt by real request in staging after deploy.redis_cache_storeon real Redis: verified locally at boot, but confirm cache reads/writes against the real ElastiCache endpoint by real request in staging after deploy.🤖 Generated with Claude Code
https://claude.ai/code/session_01C9vz7gguLNupgNEFGtjLfX