rails-upgrade
Analyze Rails application upgrade path. Checks current version, finds latest release, fetches upgrade notes and diffs, then performs selective upgrade preserving local customizations.
git clone https://github.com/robzolkos/skill-rails-upgrade
git clone --depth=1 https://github.com/robzolkos/skill-rails-upgrade ~/.claude/skills/robzolkos-skill-rails-upgrade-rails-upgrade
SKILL.mdRails Upgrade Analyzer
Analyze the current Rails application and provide a comprehensive upgrade assessment with selective file merging.
Step 1: Verify Rails Application
Check that we're in a Rails application by looking for these files:
(must exist and contain 'rails')Gemfile
(Rails application config)config/application.rb
(Rails environment)config/environment.rb
If any of these are missing or don't indicate a Rails app, stop and inform the user this doesn't appear to be a Rails application.
Step 2: Get Current Rails Version
Extract the current Rails version from:
- First, check
for the exact installed version (look forGemfile.lock
)rails (x.y.z) - If not found, check
for the version constraintGemfile
Report the exact current version (e.g.,
7.1.3).
Step 3: Find Latest Rails Version
Use the GitHub CLI to fetch the latest Rails release:
gh api repos/rails/rails/releases/latest --jq '.tag_name'
This returns the latest stable version tag (e.g.,
v8.0.1). Strip the 'v' prefix for comparison.
Also check recent tags to understand the release landscape:
gh api repos/rails/rails/tags --jq '.[0:10] | .[].name'
Step 4: Determine Upgrade Type
Compare current and latest versions to classify the upgrade:
- Patch upgrade: Same major.minor, different patch (e.g., 7.1.3 → 7.1.5)
- Minor upgrade: Same major, different minor (e.g., 7.1.3 → 7.2.0)
- Major upgrade: Different major version (e.g., 7.1.3 → 8.0.0)
Step 5: Fetch Upgrade Guide
Use WebFetch to get the official Rails upgrade guide:
URL:
https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
Look for sections relevant to the version jump. The guide is organized by target version with sections like:
- "Upgrading from Rails X.Y to Rails X.Z"
- Breaking changes
- Deprecation warnings
- Configuration changes
- Required migrations
Extract and summarize the relevant sections for the user's specific upgrade path.
Step 6: Fetch Rails Diff
Use WebFetch to get the diff between versions from railsdiff.org:
URL:
https://railsdiff.org/{current_version}/{target_version}
For example:
https://railsdiff.org/7.1.3/8.0.0
This shows:
- Changes to default configuration files
- New files that need to be added
- Modified initializers
- Updated dependencies
- Changes to bin/ scripts
Summarize the key file changes.
Step 7: Check JavaScript Dependencies
Rails applications often include JavaScript packages that should be updated alongside Rails. Check for and report on these dependencies.
7.1: Identify JS Package Manager
Check which package manager the app uses:
# Check for package.json (npm/yarn) ls package.json 2>/dev/null # Check for importmap (Rails 7+) ls config/importmap.rb 2>/dev/null
7.2: Check Rails-Related JS Packages
If
package.json exists, check for these Rails-related packages:
# Extract current versions of Rails-related packages cat package.json | grep -E '"@hotwired/|"@rails/|"stimulus"|"turbo-rails"' || echo "No Rails JS packages found"
Key packages to check:
| Package | Purpose | Version Alignment |
|---|---|---|
| Turbo Drive/Frames/Streams | Should match Rails version era |
| Stimulus JS framework | Generally stable across Rails versions |
| WebSocket support | Should match Rails version |
| Direct uploads | Should match Rails version |
| Rich text editing | Should match Rails version |
| Rails UJS replacement | Should match Rails version era |
7.3: Check for Updates
For npm/yarn projects, check for available updates:
# Using npm npm outdated @hotwired/turbo-rails @hotwired/stimulus @rails/actioncable @rails/activestorage 2>/dev/null # Or check latest versions directly npm view @hotwired/turbo-rails version 2>/dev/null npm view @rails/actioncable version 2>/dev/null
7.4: Check Importmap Pins (if applicable)
If the app uses importmap-rails, check
config/importmap.rb for pinned versions:
cat config/importmap.rb | grep -E 'pin.*turbo|pin.*stimulus|pin.*@rails' || echo "No importmap pins found"
To update importmap pins:
bin/importmap pin @hotwired/turbo-rails bin/importmap pin @hotwired/stimulus
7.5: JS Dependency Summary
Include in the upgrade summary:
### JavaScript Dependencies **Package Manager**: [npm/yarn/importmap/none] | Package | Current | Latest | Action | |---------|---------|--------|--------| | @hotwired/turbo-rails | 8.0.4 | 8.0.12 | Update recommended | | @rails/actioncable | 7.1.0 | 8.0.0 | Update with Rails | | ... | ... | ... | ... | **Recommended JS Updates:** - Run `npm update @hotwired/turbo-rails` (or yarn equivalent) - Run `npm update @rails/actioncable @rails/activestorage` to match Rails version
Step 8: Generate Upgrade Summary
Provide a comprehensive summary including all findings from Steps 1-7:
Version Information
- Current version: X.Y.Z
- Latest version: A.B.C
- Upgrade type: [Patch/Minor/Major]
Upgrade Complexity Assessment
Rate the upgrade as Small, Medium, or Large based on:
| Factor | Small | Medium | Large |
|---|---|---|---|
| Version jump | Patch only | Minor version | Major version |
| Breaking changes | None | Few, well-documented | Many, significant |
| Config changes | Minimal | Moderate | Extensive |
| Deprecations | None active | Some to address | Many requiring refactoring |
| Dependencies | Compatible | Some updates needed | Major dependency updates |
Key Changes to Address
List the most important changes the user needs to handle:
- Configuration file updates
- Deprecated methods/features to update
- New required dependencies
- Database migrations needed
- Breaking API changes
Recommended Upgrade Steps
- Update test suite and ensure passing
- Review deprecation warnings in current version
- Update Gemfile with new Rails version
- Run
bundle update rails - Update JavaScript dependencies (see JS Dependencies section)
- DO NOT run
directly - use the selective merge process belowrails app:update - Run database migrations
- Run test suite
- Review and update deprecated code
Resources
- Rails Upgrade Guide: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
- Rails Diff: https://railsdiff.org/{current}/{target}
- Release Notes: https://github.com/rails/rails/releases/tag/v{target}
Step 9: Selective File Update (replaces rails app:update
)
rails app:updateIMPORTANT: Do NOT run
rails app:update as it overwrites files without considering local customizations. Instead, follow this selective merge process:
9.1: Detect Local Customizations
Before any upgrade, identify files with local customizations:
# Check for uncommitted changes git status # List config files that differ from a fresh Rails app # These are the files we need to be careful with git diff HEAD --name-only -- config/ bin/ public/
Create a mental list of files in these categories:
- Custom config files: Files with project-specific settings (i18n, mailer, etc.)
- Modified bin scripts: Scripts with custom behavior (bin/dev with foreman, etc.)
- Standard files: Files that haven't been customized
9.2: Analyze Required Changes from Railsdiff
Based on the railsdiff output from Step 6, categorize each changed file:
| Category | Action | Example |
|---|---|---|
| New files | Create directly | |
| Unchanged locally | Safe to overwrite | (if not customized) |
| Customized locally | Manual merge needed | , |
| Comment-only changes | Usually skip | Minor comment updates in config files |
9.3: Create Upgrade Plan
Present the user with a clear upgrade plan:
## Upgrade Plan: Rails X.Y.Z → A.B.C ### New Files (will be created): - config/initializers/new_framework_defaults_A_B.rb - bin/ci (new CI script) ### Safe to Update (no local customizations): - public/400.html - public/404.html - public/500.html ### Needs Manual Merge (local customizations detected): - config/application.rb └─ Local: i18n configuration └─ Rails: [describe new Rails changes if any] - config/environments/development.rb └─ Local: letter_opener mailer config └─ Rails: [describe new Rails changes] - bin/dev └─ Local: foreman + Procfile.dev setup └─ Rails: changed to simple ruby script ### Skip (comment-only or irrelevant changes): - config/puma.rb (only comment changes)
9.4: Execute Upgrade Plan
After user confirms the plan:
For New Files:
Create them directly using the content from railsdiff or by extracting from a fresh Rails app:
# Generate a temporary fresh Rails app to extract new files cd /tmp && rails new rails_template --skip-git --skip-bundle # Then copy needed files
Or use the Rails generator for specific files:
bin/rails app:update:configs # Only updates config files, still interactive
For Safe Updates:
Overwrite these files as they have no local customizations.
For Manual Merges:
For each file needing merge, show the user:
- Current local version (their customizations)
- New Rails default (from railsdiff)
- Suggested merged version that:
- Keeps all local customizations
- Adds only essential new Rails functionality
- Removes deprecated settings
Example merge for
config/application.rb:
# KEEP local customizations: config.i18n.available_locales = [:de, :en] config.i18n.default_locale = :de config.i18n.fallbacks = [:en] # ADD new Rails 8.1 settings if needed: # (usually none required - new defaults come via new_framework_defaults file)
9.5: Handle Active Storage Migrations
After file updates, run any new migrations:
bin/rails db:migrate
Check for new migrations that were added:
ls -la db/migrate/ | tail -10
9.6: Verify Upgrade
After completing the merge:
-
Start the Rails server and check for errors:
bin/dev # or bin/rails server -
Check the Rails console:
bin/rails console -
Run the test suite:
bin/rails test -
Review deprecation warnings in logs
Step 10: Finalize Framework Defaults
After verifying the app works:
- Review
config/initializers/new_framework_defaults_X_Y.rb - Enable each new default one by one, testing after each
- Once all defaults are enabled and tested, update
:config/application.rbconfig.load_defaults X.Y # Update to new version - Delete the
filenew_framework_defaults_X_Y.rb
Error Handling
- If
CLI is not authenticated, instruct the user to runghgh auth login - If railsdiff.org doesn't have the exact versions, try with major.minor.0 versions
- If the app is already on the latest version, congratulate the user and note any upcoming releases
- If local customizations would be lost, ALWAYS stop and show the user what would be overwritten before proceeding
Key Principles
- Never overwrite without checking - Always check for local customizations first
- Preserve user intent - Local customizations exist for a reason
- Minimal changes - Only add what's necessary for the new Rails version
- Transparency - Show the user exactly what will change before doing it
- Reversibility - User should be able to
to restore if neededgit checkout