rails_preflight 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +18 -0
- data/LICENSE.txt +21 -0
- data/README.md +253 -0
- data/bin/rails-preflight +48 -0
- data/database/compatibility.yml +59 -0
- data/database/deprecations.yml +1119 -0
- data/database/gems.yml +109 -0
- data/lib/rails_preflight/config_analyzer.rb +46 -0
- data/lib/rails_preflight/database_analyzer.rb +64 -0
- data/lib/rails_preflight/deprecation_analyzer.rb +214 -0
- data/lib/rails_preflight/docker_analyzer.rb +124 -0
- data/lib/rails_preflight/gem_analyzer.rb +178 -0
- data/lib/rails_preflight/json_report.rb +45 -0
- data/lib/rails_preflight/markdown_report.rb +72 -0
- data/lib/rails_preflight/report_generator.rb +496 -0
- data/lib/rails_preflight/summary_calculator.rb +144 -0
- data/lib/rails_preflight/upgrade_analyzer.rb +409 -0
- data/lib/rails_preflight/version.rb +3 -0
- data/lib/rails_preflight.rb +14 -0
- metadata +70 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 02fcbcfa3f7d98bbc550334fcf9bd65919fbb2eb5266088823b87c0fd7465ae3
|
|
4
|
+
data.tar.gz: 42c66fa2d33b67e47fed5a36a7127eba476c34b57705d0f3c2591dea9fa1f5eb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ab95dfb109b6fee6cd50d1014792f85d4e941ba7871734766b834844bea2a2bfb15e526e426f7a19a97be7abd58339141bfea037365d9e0b34a3e6f5063b8226
|
|
7
|
+
data.tar.gz: 1606dfaa001672ed19d45469592f212979228c2efb6500b9e7f8b8017d9977817e1814b25045f79b3ada23a9d3d9fe32b09fbe71e74c3b606e5e69e761ea7731
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-10-09)
|
|
4
|
+
|
|
5
|
+
First release. Point it at a Rails 5.0 – 8.1 app and a target version: it writes a report into the app as HTML, Markdown or JSON, plus a short terminal summary. Read-only and static.
|
|
6
|
+
|
|
7
|
+
- Upgrade path with one step per Rails minor, the Ruby each step needs, and which step to upgrade Ruby on
|
|
8
|
+
- 118 deprecation rules from the release notes, 5.0 to 8.1, each cited, scanning `.rb`, `.erb`, `.haml`, `.slim` and `.rake` files, config YAML, and rake tasks in scripts and CI; APIs already removed from the current Rails are listed first as already broken
|
|
9
|
+
- Gem checks: private gems from `Gemfile.lock` and the Gemfile's sources; locked gems whose declared Rails requirement caps the upgrade; limits no gemspec declares, which Rails or the gem checks when it loads (database adapters, listen, capybara, selenium-webdriver, redis, google-cloud-storage, bullet); gems the rails gem stops pulling in; a curated list of retired gems; and, online, gems with no release since the target Rails shipped
|
|
10
|
+
- Ruby and Node end-of-life, Docker runtime risks, `config.load_defaults`, and schema charset and integer IDs from `db/schema.rb` (an app on `db/structure.sql` gets a note that these were skipped)
|
|
11
|
+
- HTML report: verdict, counts, route, plan table, one card per step with files and lines, and what the report can't see; dark mode, print styles, no network requests
|
|
12
|
+
- `--format markdown`: a checklist per step for issues, PRs and coding agents
|
|
13
|
+
- `--format json`: every finding with its parts (`"schema": 1`, may change before 1.0)
|
|
14
|
+
- `--stdout` prints the report instead of writing it, for pipes and coding agents
|
|
15
|
+
- `--fail-on blockers|broken` sets the exit code, so CI can gate on it
|
|
16
|
+
- `--offline` for a fully static run; private gem names are never sent
|
|
17
|
+
- Report snippets hide quoted values on lines that name a secret, token or password
|
|
18
|
+
- Checked against real Rails upgrades in Mastodon, Discourse, Forem, Redmine, Coursemology and Fat Free CRM
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Syed Aslam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# RailsPreFlight 🛡️
|
|
2
|
+
|
|
3
|
+
**Assess Rails upgrade risk before you touch a single line of code.**
|
|
4
|
+
|
|
5
|
+
`rails-preflight` is a static analysis tool that scans legacy Rails applications and produces a **human-readable upgrade risk report**.
|
|
6
|
+
|
|
7
|
+
It helps teams understand:
|
|
8
|
+
|
|
9
|
+
- what will block a Rails upgrade
|
|
10
|
+
- what is easy vs painful to fix
|
|
11
|
+
- where hidden dependency and infrastructure risks exist
|
|
12
|
+
|
|
13
|
+
This tool is designed for **planning and scoping**, not automated migration.
|
|
14
|
+
|
|
15
|
+
<picture>
|
|
16
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/images/report-overview-dark.png">
|
|
17
|
+
<img alt="The report for Mastodon v3.3.0, Rails 5.2.4.4 to 7.0: verdict, counts, the route through 6.0, 6.1 and 7.0 with blockers at each, and the plan table" src="docs/images/report-overview-light.png">
|
|
18
|
+
</picture>
|
|
19
|
+
|
|
20
|
+
<sub>Mastodon v3.3.0, an open-source app, checked for Rails 7.0. <a href="https://aslam.github.io/rails-preflight/sample-report.html">See the full report</a>.</sub>
|
|
21
|
+
|
|
22
|
+
## Why this exists
|
|
23
|
+
|
|
24
|
+
Rails upgrades fail not because teams can’t write code, but because they underestimate risk:
|
|
25
|
+
|
|
26
|
+
- private gems with unknown compatibility
|
|
27
|
+
- subtle framework deprecations
|
|
28
|
+
- Ruby and OS lifecycle mismatches
|
|
29
|
+
- Docker runtime issues that surface late
|
|
30
|
+
|
|
31
|
+
`rails-preflight` makes these risks visible before you start upgrading.
|
|
32
|
+
|
|
33
|
+
Think of it as **upgrade reconnaissance**, not a fixer. Run it before the upgrade starts, whoever does it: your team, a consultant or a coding agent.
|
|
34
|
+
|
|
35
|
+
## What this tool does
|
|
36
|
+
|
|
37
|
+
The audit analyzes your project for common Rails upgrade risk factors:
|
|
38
|
+
|
|
39
|
+
- Ruby & Rails compatibility, and which upgrade step to move Ruby on
|
|
40
|
+
- End-of-life Ruby and Node versions
|
|
41
|
+
- Private / internal gem dependencies
|
|
42
|
+
- Locked gems whose declared Rails requirement caps the upgrade, plus a curated list of gems with known limits
|
|
43
|
+
- Removed and deprecated Rails APIs in code, config YAML, rake tasks in scripts and CI, including ones already removed from your current Rails
|
|
44
|
+
- Docker runtime risks (EOL base image, locale, tzdata, OpenSSL mismatch)
|
|
45
|
+
- Database schema risks (charset, integer IDs)
|
|
46
|
+
- Missing or outdated `config.load_defaults`
|
|
47
|
+
|
|
48
|
+
The output is a **single HTML report** designed to be:
|
|
49
|
+
|
|
50
|
+
- readable by engineers
|
|
51
|
+
- understandable by EMs and tech leads
|
|
52
|
+
- usable in upgrade planning discussions
|
|
53
|
+
|
|
54
|
+
The same findings also come as **Markdown**, a checklist for issues, PRs and coding agents, and as **JSON** for CI and other tools. See [Output formats](#output-formats).
|
|
55
|
+
|
|
56
|
+
## What this tool intentionally does NOT do
|
|
57
|
+
|
|
58
|
+
- ❌ It does not modify your code
|
|
59
|
+
- ❌ It does not auto-fix deprecations
|
|
60
|
+
- ❌ It does not guarantee upgrade success
|
|
61
|
+
- ❌ It is not a replacement for running tests or CI
|
|
62
|
+
|
|
63
|
+
If you’re looking for a “one-click upgrade,” this is not that tool.
|
|
64
|
+
|
|
65
|
+
## Related tools
|
|
66
|
+
|
|
67
|
+
These cover what `rails-preflight` leaves out, and pair well with it:
|
|
68
|
+
|
|
69
|
+
- [next_rails](https://github.com/fastruby/next_rails) or [RailsBump](https://railsbump.org): which gem versions work with your target Rails
|
|
70
|
+
- [Brakeman](https://brakemanscanner.org): security issues
|
|
71
|
+
- [rubocop-rails](https://github.com/rubocop/rubocop-rails): autofixes for many deprecations
|
|
72
|
+
|
|
73
|
+
## Who this is for
|
|
74
|
+
|
|
75
|
+
This tool is especially useful if you are:
|
|
76
|
+
|
|
77
|
+
- Upgrading a Rails 5.0 or newer application (Rails 3 and 4 aren't covered)
|
|
78
|
+
- Planning a security-driven upgrade
|
|
79
|
+
- Scoping an upgrade before committing resources
|
|
80
|
+
- Auditing multiple legacy Rails apps
|
|
81
|
+
- A consultant or staff engineer responsible for upgrade strategy
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
Install it globally and point it at your app. It only reads files, so the app can be on any Ruby version, including the old one your servers run. The machine running it needs Ruby 2.7 or newer.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
gem install rails_preflight
|
|
89
|
+
rails-preflight /path/to/your/app
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
With no target, it reports on the next Rails minor after the app's (5.2 → 6.0, 7.1 → 7.2), the step Rails recommends taking next. Pass a target to plan a bigger jump: `rails-preflight 8.1 /path/to/your/app`. Leave out the path to audit the current directory.
|
|
93
|
+
|
|
94
|
+
Private gems come from `Gemfile.lock` and the Gemfile's `source` blocks, which are read, never run. Only when neither says where a gem comes from does the tool ask rubygems.org. It also asks rubygems.org when each public gem that depends on Rails last had a release, and lists the ones with nothing newer than the target Rails: nothing says they break, but nobody may have tried. Private gem names are never sent. Pass `--offline` for a fully static run; unplaced gems are then reported as unchecked, and release dates are skipped.
|
|
95
|
+
|
|
96
|
+
It knows Rails 5.0 to 8.1 (`database/compatibility.yml`); the default target is only as current as that list.
|
|
97
|
+
|
|
98
|
+
The tool will analyze:
|
|
99
|
+
|
|
100
|
+
- `Gemfile` and `Gemfile.lock`
|
|
101
|
+
- `.ruby-version`
|
|
102
|
+
- `Dockerfile` (if present)
|
|
103
|
+
- `db/schema.rb` (if present; an app on `db/structure.sql` gets a note that the schema checks were skipped)
|
|
104
|
+
- `config/application.rb` and `config/**/*.yml`
|
|
105
|
+
- `.rb`, `.erb`, `.haml`, `.slim` and `.rake` files under `app/`, `config/`, `db/`, `lib/`, `test/` and `spec/`
|
|
106
|
+
- Scripts and CI config (`bin/`, `script/`, Procfiles, Makefiles, CI workflows) for removed rake tasks
|
|
107
|
+
|
|
108
|
+
And generate:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
rails_preflight_report.html
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Or `rails_preflight_report.md` or `.json` with `--format markdown` or `--format json`: see [Output formats](#output-formats).
|
|
115
|
+
|
|
116
|
+
## Output formats
|
|
117
|
+
|
|
118
|
+
Every format renders the same findings. Each finding carries its parts, not only a sentence: the gem, its locked version and the requirement it fails, or the rule with every file, line and matched line, plus the release notes, README or Rails source it rests on.
|
|
119
|
+
|
|
120
|
+
| Format | Flag | Written to, in the app | For |
|
|
121
|
+
|---|---|---|---|
|
|
122
|
+
| HTML | (default) | `rails_preflight_report.html` | reading, planning, sharing |
|
|
123
|
+
| Markdown | `--format markdown` | `rails_preflight_report.md` | issues, PRs, coding agents |
|
|
124
|
+
| JSON | `--format json` | `rails_preflight_report.json` | CI and other tools |
|
|
125
|
+
|
|
126
|
+
The report is the only file the tool writes. Add `--stdout` to print it instead, for pipes and coding agents: no file is written, and progress goes to stderr so stdout holds only the report. Every run also prints a short summary (counts, then each blocker) for SSH sessions and CI logs.
|
|
127
|
+
|
|
128
|
+
### HTML
|
|
129
|
+
|
|
130
|
+
One self-contained file. It makes no network requests when opened, follows the OS dark mode, and prints on A4. [Sample: Mastodon v3.3.0 to Rails 7.0](https://aslam.github.io/rails-preflight/sample-report.html).
|
|
131
|
+
|
|
132
|
+
1. **Title and verdict**: `app: Rails current to target`, then one sentence: how many steps, when to upgrade Ruby, how many blockers.
|
|
133
|
+
|
|
134
|
+
2. **Counts**, each linked to where the findings are:
|
|
135
|
+
* **Already broken**: APIs removed before your current Rails, or gems past their last supported Rails. That code fails when it runs, or never runs.
|
|
136
|
+
* **Blockers**: must be fixed before the upgrade can work (e.g. Ruby too old, removed APIs still in use).
|
|
137
|
+
* **To fix**: will warn or break along the way (deprecations, lagging config), split into now and later versions.
|
|
138
|
+
* **Couldn't check**: what the tool could not verify (private gems, missing files), to review by hand.
|
|
139
|
+
|
|
140
|
+
3. **Route and plan**: one stop per Rails minor, since Rails recommends upgrading one at a time, with the blockers at each. Later versions past the target are faded and count the code they remove, found in the same scan. A table gives each step's work, the Ruby it needs and a relative effort: the hardest single fix in it (low, medium or high, set per check), not the amount of work. The occurrence counts on each finding show that.
|
|
141
|
+
|
|
142
|
+
4. **Steps**: "Before you start" for findings that don't belong to a step, then one card per step with its Ruby range and the removed APIs and gems to fix for it. Each finding links to the Rails release notes or the gem's source; its occurrence line expands to file, line and snippet, with app and test occurrences counted apart.
|
|
143
|
+
|
|
144
|
+
5. **Ahead of the target**: code that later Rails versions remove, by version. Not needed now.
|
|
145
|
+
|
|
146
|
+
6. **What this report can't see**: private gems and quiet gems by name, behavior changes, multi-line code and test coverage, with what to do instead.
|
|
147
|
+
|
|
148
|
+
7. **Footer**: the confidence of each section (read from project files, pattern matches, or a key input missing) and where the findings come from.
|
|
149
|
+
|
|
150
|
+
<picture>
|
|
151
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/images/report-step-dark.png">
|
|
152
|
+
<img alt="The 6.1 to 7.0 step card: four gem blockers, then removed APIs with their files, line numbers and matched lines expanded" src="docs/images/report-step-light.png">
|
|
153
|
+
</picture>
|
|
154
|
+
|
|
155
|
+
### Markdown
|
|
156
|
+
|
|
157
|
+
`--format markdown` writes `rails_preflight_report.md` into the app. A coding agent can read it from stdout instead:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
rails-preflight --format markdown --stdout 7.2 /path/to/your/app
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
It's a checklist per step, with `file:line` and the matched line under each finding. It pastes into an issue or PR as is, and opens with a note telling a coding agent to take one step at a time, run the tests after each, and leave "Ahead" and "Couldn't check" alone. From the same Mastodon run ([full sample](docs/sample-report.md)):
|
|
164
|
+
|
|
165
|
+
```markdown
|
|
166
|
+
## Step 3: 6.1 to 7.0
|
|
167
|
+
|
|
168
|
+
Needs Ruby 2.7.0–3.2: 2.7.2 works.
|
|
169
|
+
|
|
170
|
+
- [ ] **Blocker:** annotate 3.1.1 requires activerecord >= 3.2, < 7.0, so it doesn't install on Rails 7.0. Upgrade it to a release that allows 7.0, or replace it.
|
|
171
|
+
- [ ] **Blocker:** `ActionMailer::DeliveryJob` and `ActionMailer::Parameterized::DeliveryJob` were removed in Rails 7.0. Mail is delivered by `ActionMailer::MailDeliveryJob`. ([source](https://guides.rubyonrails.org/7_0_release_notes.html#action-mailer-removals))
|
|
172
|
+
- `config/initializers/delivery_job.rb:1` `ActionMailer::DeliveryJob.class_eval do`
|
|
173
|
+
- `spec/models/user_spec.rb:178` `expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::DeliveryJob)`
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### JSON
|
|
177
|
+
|
|
178
|
+
`--format json` writes `rails_preflight_report.json` into the app, for CI and other tools. With `--stdout` it can be piped:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
rails-preflight --format json --stdout 7.2 /path/to/your/app | jq '.counts'
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The top level holds `schema`, `tool`, `app`, `current_rails`, `target_rails`, `ruby`, `offline`, `verdict` and `counts`, then the findings in `before` (before the first step), `steps` (each with `from`, `version`, its Ruby note and `findings`), `ahead` (keyed by the Rails version that removes them) and `cant_see`. There's no timestamp, so the same app gives the same output. Schema 1 may still change before 1.0; the number goes up when it does. A step from the same run, shortened ([full sample](docs/sample-report.json)):
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"from": "6.1",
|
|
189
|
+
"version": "7.0",
|
|
190
|
+
"findings": [
|
|
191
|
+
{
|
|
192
|
+
"section": "Gem Compatibility",
|
|
193
|
+
"kind": "blocker",
|
|
194
|
+
"message": "annotate 3.1.1 requires activerecord >= 3.2, < 7.0, so it doesn't install on Rails 7.0. ...",
|
|
195
|
+
"removed_in": "7.0",
|
|
196
|
+
"fix_effort": "medium",
|
|
197
|
+
"gem": "annotate",
|
|
198
|
+
"version": "3.1.1",
|
|
199
|
+
"requires": "activerecord >= 3.2, < 7.0"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"section": "Deprecation Warnings",
|
|
203
|
+
"kind": "blocker",
|
|
204
|
+
"message": "'ActiveModel::Errors#keys', '#values', '#to_h', '#slice!' and '#to_xml' were removed in Rails 7.0. ...",
|
|
205
|
+
"rule": "errors_hash_methods",
|
|
206
|
+
"removed_in": "7.0",
|
|
207
|
+
"fix_effort": "low",
|
|
208
|
+
"confidence": "medium",
|
|
209
|
+
"source": "https://guides.rubyonrails.org/7_0_release_notes.html#active-model-removals",
|
|
210
|
+
"files": [
|
|
211
|
+
{ "file": "lib/mastodon/accounts_cli.rb", "line": 106, "snippet": "user.errors.to_h.each do |key, error|", "test": false }
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
`kind` is `broken`, `blocker`, `to_fix`, `tip` or `unknown`. A finding has only the parts that apply to it: gem findings have `gem`, `version` and `requires`; code findings have `rule`, `confidence` and `files`; what the report couldn't check has `names`.
|
|
219
|
+
|
|
220
|
+
### Gating CI
|
|
221
|
+
|
|
222
|
+
`--fail-on blockers` exits 1 when anything blocks the upgrade or is already broken; `--fail-on broken` only when something is already broken. It works with any format. In CI, `--offline` keeps the run fully static:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
rails-preflight --offline --format json --fail-on blockers 7.2
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Roadmap
|
|
229
|
+
|
|
230
|
+
For a detailed list of current features and future plans, please see [ROADMAP.md](ROADMAP.md).
|
|
231
|
+
|
|
232
|
+
## Philosophy
|
|
233
|
+
|
|
234
|
+
This tool favors:
|
|
235
|
+
|
|
236
|
+
- clarity over completeness
|
|
237
|
+
- honesty over false confidence
|
|
238
|
+
- planning support over automation
|
|
239
|
+
|
|
240
|
+
If it helps you avoid one failed upgrade attempt, it has done its job.
|
|
241
|
+
|
|
242
|
+
## Development
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
bundle install
|
|
246
|
+
bundle exec rake
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
CI runs the suite on every Ruby from 2.7 to 4.0.
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
MIT
|
data/bin/rails-preflight
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# No bundler/setup on purpose: it would load the Gemfile in the current directory,
|
|
5
|
+
# which is usually the app being audited, often pinned to an old Ruby.
|
|
6
|
+
lib = File.expand_path("../lib", __dir__)
|
|
7
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
8
|
+
|
|
9
|
+
require 'rails_preflight'
|
|
10
|
+
|
|
11
|
+
if %w[-h --help].include?(ARGV[0])
|
|
12
|
+
puts "Usage: rails-preflight [--offline] [--format html|markdown|json] [--stdout] [--fail-on blockers|broken] [TARGET_RAILS_VERSION] [APP_PATH]"
|
|
13
|
+
puts "Example: rails-preflight 7.2 ~/code/my_app"
|
|
14
|
+
puts "TARGET defaults to the next Rails minor after the app's; APP_PATH to the current directory."
|
|
15
|
+
puts "--offline: don't call rubygems.org; gems the lockfile can't place are reported as unchecked, and gem release dates are skipped."
|
|
16
|
+
puts "--format markdown|json: write rails_preflight_report.md or .json into the app instead of the HTML report."
|
|
17
|
+
puts "--stdout: print the report instead of writing it (progress goes to stderr), for pipes and coding agents."
|
|
18
|
+
puts "--fail-on blockers: exit 1 when anything blocks the upgrade or is already broken. --fail-on broken: only when something is already broken."
|
|
19
|
+
exit
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
offline = !ARGV.delete("--offline").nil?
|
|
23
|
+
stdout = !ARGV.delete("--stdout").nil?
|
|
24
|
+
format = :html
|
|
25
|
+
if (i = ARGV.index("--format"))
|
|
26
|
+
format = ARGV.slice!(i, 2)[1].to_s.to_sym
|
|
27
|
+
abort "--format must be html, markdown or json (got #{format})." unless %i[html markdown json].include?(format)
|
|
28
|
+
end
|
|
29
|
+
fail_on = nil
|
|
30
|
+
if (i = ARGV.index("--fail-on"))
|
|
31
|
+
fail_on = ARGV.slice!(i, 2)[1].to_s.to_sym
|
|
32
|
+
abort "--fail-on must be blockers or broken (got #{fail_on})." unless %i[blockers broken].include?(fail_on)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# The target is optional, so a lone argument that isn't a version is the app path.
|
|
36
|
+
target = ARGV.shift if ARGV[0] && (Gem::Version.correct?(ARGV[0]) || !File.directory?(ARGV[0]))
|
|
37
|
+
abort "Target must be a Rails version such as 7.2 (got #{target.inspect})." if target && !Gem::Version.correct?(target)
|
|
38
|
+
project_path = ARGV[0] || Dir.pwd
|
|
39
|
+
|
|
40
|
+
begin
|
|
41
|
+
summary = RailsPreflight::UpgradeAnalyzer.new(target, project_path, offline: offline, format: format, stdout: stdout).run
|
|
42
|
+
rescue RailsPreflight::Error => e
|
|
43
|
+
abort e.message
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Already broken is worse than blocked, so --fail-on blockers counts it too.
|
|
47
|
+
failing = { blockers: %i[broken blockers], broken: %i[broken] }.fetch(fail_on, []).sum { |key| summary&.fetch(key)&.size.to_i }
|
|
48
|
+
exit 1 if failing.positive?
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# database/compatibility.yml
|
|
2
|
+
# released: the X.Y.0 release date on rubygems.org.
|
|
3
|
+
rails_versions:
|
|
4
|
+
"5.0":
|
|
5
|
+
released: "2016-06-30"
|
|
6
|
+
required_ruby: ">= 2.2.2"
|
|
7
|
+
max_ruby: "2.4.99"
|
|
8
|
+
"5.1":
|
|
9
|
+
released: "2017-04-27"
|
|
10
|
+
required_ruby: ">= 2.2.2"
|
|
11
|
+
max_ruby: "2.5.99"
|
|
12
|
+
"5.2":
|
|
13
|
+
released: "2018-04-09"
|
|
14
|
+
required_ruby: ">= 2.2.2"
|
|
15
|
+
max_ruby: "2.6.99"
|
|
16
|
+
# Note: Rails 5.2.8.1 supports up to 2.7, but 3.0 is a hard break.
|
|
17
|
+
"6.0":
|
|
18
|
+
released: "2019-08-16"
|
|
19
|
+
required_ruby: ">= 2.5.0"
|
|
20
|
+
max_ruby: "2.7.99"
|
|
21
|
+
"6.1":
|
|
22
|
+
released: "2020-12-09"
|
|
23
|
+
required_ruby: ">= 2.5.0"
|
|
24
|
+
max_ruby: "3.0.99"
|
|
25
|
+
"7.0":
|
|
26
|
+
released: "2021-12-15"
|
|
27
|
+
required_ruby: ">= 2.7.0"
|
|
28
|
+
max_ruby: "3.2.99"
|
|
29
|
+
"7.1":
|
|
30
|
+
released: "2023-10-05"
|
|
31
|
+
required_ruby: ">= 2.7.0"
|
|
32
|
+
max_ruby: "3.4.99"
|
|
33
|
+
"7.2":
|
|
34
|
+
released: "2024-08-09"
|
|
35
|
+
required_ruby: ">= 3.1.0"
|
|
36
|
+
max_ruby: "3.4.99"
|
|
37
|
+
# Rails CI treats Ruby 3.4+ as allowed-to-fail on 7.x; 3.4 per FastRuby's compatibility table.
|
|
38
|
+
"8.0":
|
|
39
|
+
released: "2024-11-07"
|
|
40
|
+
required_ruby: ">= 3.2.0"
|
|
41
|
+
max_ruby: "4.0.99"
|
|
42
|
+
"8.1":
|
|
43
|
+
released: "2025-10-22"
|
|
44
|
+
required_ruby: ">= 3.2.0"
|
|
45
|
+
max_ruby: "4.0.99"
|
|
46
|
+
# Rails CI gates 8.x on Ruby 4.0 (rails/buildkite-config).
|
|
47
|
+
|
|
48
|
+
# Schema checks, applied when the target Rails is at or past `since`.
|
|
49
|
+
database_rules:
|
|
50
|
+
- name: "utf8_charset"
|
|
51
|
+
message: "Legacy utf8mb3 charset detected. Upgrade to utf8mb4 for Rails 6+."
|
|
52
|
+
pattern: "utf8mb3"
|
|
53
|
+
type: "warning"
|
|
54
|
+
since: "6.0"
|
|
55
|
+
- name: "integer_ids"
|
|
56
|
+
message: "Integer IDs detected. Rails 5.1+ defaults to bigint."
|
|
57
|
+
pattern: "id: :integer"
|
|
58
|
+
type: "warning"
|
|
59
|
+
since: "5.1"
|