next_rails 1.5.0 → 1.6.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 +4 -4
- data/.github/workflows/main.yml +1 -1
- data/.rspec +1 -0
- data/CHANGELOG.md +9 -1
- data/CONTRIBUTING.md +4 -0
- data/README.md +160 -105
- data/exe/deprecations +34 -15
- data/lib/deprecation_tracker/shard_merger.rb +64 -0
- data/lib/deprecation_tracker.rb +60 -32
- data/lib/next_rails/bundle_report/cli.rb +2 -1
- data/lib/next_rails/bundle_report/rails_version_compatibility.rb +13 -11
- data/lib/next_rails/bundle_report/ruby_version_compatibility.rb +9 -9
- data/lib/next_rails/bundle_report.rb +4 -4
- data/lib/next_rails/tint.rb +47 -0
- data/lib/next_rails/version.rb +1 -1
- data/next_rails.gemspec +1 -2
- metadata +8 -23
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7ef709432bba364ea112d6d8774d0c51b8bf1959b48ede86437b7ae801c7ea3b
|
|
4
|
+
data.tar.gz: f568512b09f8d16199ec4fb1800964f6a8067a3fb3d36eeaf48a335e117d56c5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2b296e5306c8ab34b7f5b38801785ecfb3a6039a6a48310533ffc02033634a9d67ca2c03f6531c0dc05725a44cffe06d9dc65071f947bc6ec5c6bdd2892a6f9
|
|
7
|
+
data.tar.gz: cba5e3a34b3127fdcb2bfa28775250b5d7b2f8e0bdb5fb453976c6304f34ca1e272c4b6abee61eb12fe01c0e0cb4c22ea838d7d94164c40f57d7e039ecd7db51
|
data/.github/workflows/main.yml
CHANGED
|
@@ -13,7 +13,7 @@ jobs:
|
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
strategy:
|
|
15
15
|
matrix:
|
|
16
|
-
ruby-version: ["3.4", "3.3", "3.2", "3.1", "3.0", "2.7", "2.6", "2.5", "2.4", "2.3"]
|
|
16
|
+
ruby-version: ["4.0", "3.4", "3.3", "3.2", "3.1", "3.0", "2.7", "2.6", "2.5", "2.4", "2.3"]
|
|
17
17
|
|
|
18
18
|
steps:
|
|
19
19
|
- uses: actions/checkout@v4
|
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
# main [(unreleased)](https://github.com/fastruby/next_rails/compare/v1.
|
|
1
|
+
# main [(unreleased)](https://github.com/fastruby/next_rails/compare/v1.6.0...main)
|
|
2
2
|
|
|
3
3
|
- [BUGFIX: example](https://github.com/fastruby/next_rails/pull/<number>)
|
|
4
4
|
|
|
5
5
|
* Your changes/patches go here.
|
|
6
6
|
|
|
7
|
+
# v1.6.0 / 2026-05-07 [(commits)](https://github.com/fastruby/next_rails/compare/v1.5.0...v1.6.0)
|
|
8
|
+
|
|
9
|
+
- [CHORE: Drop `rainbow` gem dependency in favor of a native `NextRails::Tint` ANSI wrapper](https://github.com/fastruby/next_rails/pull/183)
|
|
10
|
+
- [BUGFIX: Compare mode now checks only buckets the current process ran, fixing parallel test support](https://github.com/fastruby/next_rails/pull/179)
|
|
11
|
+
- [FEATURE: Add `deprecations merge` command to combine parallel CI shards](https://github.com/fastruby/next_rails/pull/177)
|
|
12
|
+
- [FEATURE: Add parallel CI support for DeprecationTracker](https://github.com/fastruby/next_rails/pull/176)
|
|
13
|
+
- [CHORE: Add Ruby 4.0 to the test matrix](https://github.com/fastruby/next_rails/pull/178)
|
|
14
|
+
|
|
7
15
|
# v1.5.0 / 2026-04-01 [(commits)](https://github.com/fastruby/next_rails/compare/v1.4.8...v1.5.0)
|
|
8
16
|
|
|
9
17
|
- [FEATURE: Add `NextRails.current?` as the inverse of `NextRails.next?`](https://github.com/fastruby/next_rails/pull/174)
|
data/CONTRIBUTING.md
CHANGED
|
@@ -34,6 +34,10 @@ To run all of the tests, simply run:
|
|
|
34
34
|
bundle exec rake
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
### Testing against specific Ruby versions
|
|
38
|
+
|
|
39
|
+
See the [Docker Development Environment for Old Ruby Versions](https://github.com/fastruby/next_rails/wiki/Docker-Development-Environment-for-Old-Ruby-Versions) wiki page for setup and examples.
|
|
40
|
+
|
|
37
41
|
## A word on the changelog
|
|
38
42
|
|
|
39
43
|
You may also notice that we have a changelog in the form of [CHANGELOG.md](CHANGELOG.md). We use a format based on [Keep A Changelog](https://keepachangelog.com/en/1.0.0/).
|
data/README.md
CHANGED
|
@@ -1,83 +1,117 @@
|
|
|
1
1
|
# Next Rails
|
|
2
2
|
|
|
3
3
|
[](https://github.com/fastruby/next_rails/actions/workflows/main.yml)
|
|
4
|
+
[](https://rubygems.org/gems/next_rails)
|
|
5
|
+
[](LICENSE.txt)
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
set up dual booting, track deprecation warnings, and get a report on outdated
|
|
7
|
-
dependencies for any Rails application.
|
|
7
|
+
A toolkit to upgrade your next Rails application. It helps you set up **dual booting**, **track deprecation warnings**, and get a **compatibility report** on outdated dependencies for any Rails application. [Learn more](https://www.fastruby.io/blog/next-rails-gem.html).
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Features
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- **Dual Boot** — Run your app against two sets of dependencies (e.g. Rails 7.1 and Rails 7.2) side by side
|
|
12
|
+
- **Deprecation Tracking** — Capture and compare deprecation warnings across test runs (RSpec & Minitest)
|
|
13
|
+
- **Bundle Report** — Check gem compatibility with a target Rails or Ruby version
|
|
14
|
+
- **Ruby Check** — Find the minimum Ruby version compatible with a target Rails version
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
conference talk by Jordan Raine.
|
|
16
|
+
## Installation
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
> complete Rails upgrades.
|
|
18
|
+
Add this line to your application's Gemfile:
|
|
18
19
|
|
|
19
|
-
>
|
|
20
|
+
> [!WARNING]
|
|
21
|
+
> We recommend adding `next_rails` in the root of your Gemfile, not inside a group.
|
|
22
|
+
> This ensures `NextRails.next?` and `NextRails.current?` are available everywhere in your codebase.
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
```ruby
|
|
25
|
+
gem 'next_rails'
|
|
26
|
+
```
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
Then run:
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
```bash
|
|
31
|
+
bundle install
|
|
32
|
+
```
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
## Dual Boot
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
# Show all out-of-date gems
|
|
33
|
-
bundle_report outdated
|
|
36
|
+
We recommend upgrading **one minor version at a time** (e.g. 7.1 → 7.2, not 6.1 → 7.0). This keeps changes small and manageable.
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
bundle_report outdated | head -n 5
|
|
38
|
+
### Setup
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
> [!NOTE]
|
|
41
|
+
> The `next_rails --init` command will add a `next?` helper method to the top of your Gemfile, which you can use to conditionally set gem versions.
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
```bash
|
|
44
|
+
# Initialize dual boot (creates Gemfile.next and Gemfile.next.lock)
|
|
45
|
+
next_rails --init
|
|
43
46
|
|
|
44
|
-
#
|
|
45
|
-
|
|
47
|
+
# Edit your Gemfile to conditionally set gem versions using `next?`
|
|
48
|
+
vim Gemfile
|
|
46
49
|
|
|
47
|
-
#
|
|
48
|
-
|
|
50
|
+
# Install dependencies for the next version
|
|
51
|
+
next bundle install
|
|
49
52
|
|
|
50
|
-
#
|
|
51
|
-
|
|
53
|
+
# Start your server using the next Gemfile
|
|
54
|
+
next rails s
|
|
52
55
|
```
|
|
53
56
|
|
|
54
|
-
###
|
|
57
|
+
### Conditional code
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
application:
|
|
59
|
+
When your Gemfile targets two versions, you may need to branch application code as well:
|
|
58
60
|
|
|
59
61
|
```ruby
|
|
60
62
|
if NextRails.next?
|
|
61
|
-
# Do things "the Rails 7 way"
|
|
63
|
+
# Do things "the Rails 7.2 way"
|
|
62
64
|
else
|
|
63
|
-
# Do things "the Rails
|
|
65
|
+
# Do things "the Rails 7.1 way"
|
|
64
66
|
end
|
|
65
67
|
```
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
Or use `NextRails.current?` for the inverse check:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
if NextRails.current?
|
|
73
|
+
# Do things "the Rails 7.1 way"
|
|
74
|
+
else
|
|
75
|
+
# Do things "the Rails 7.2 way"
|
|
76
|
+
end
|
|
77
|
+
```
|
|
70
78
|
|
|
71
|
-
This
|
|
72
|
-
[Ruby or Rails shims](https://www.fastruby.io/blog/rails/upgrades/rails-upgrade-shims.html).
|
|
79
|
+
Both methods check your environment (e.g. `ENV['BUNDLE_GEMFILE']`) to determine which dependency set is active. This is useful for injecting [Ruby or Rails shims](https://www.fastruby.io/blog/rails/upgrades/rails-upgrade-shims.html).
|
|
73
80
|
|
|
74
|
-
|
|
81
|
+
## Bundle Report
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
Inspect your Gemfile and check compatibility with a target Rails or Ruby version.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Show all out-of-date gems
|
|
87
|
+
bundle_report outdated
|
|
88
|
+
|
|
89
|
+
# Show all out-of-date gems in JSON format
|
|
90
|
+
bundle_report outdated --json
|
|
91
|
+
|
|
92
|
+
# Show gems incompatible with Rails 7.2
|
|
93
|
+
bundle_report compatibility --rails-version=7.2
|
|
94
|
+
|
|
95
|
+
# Show gems incompatible with Ruby 3.3
|
|
96
|
+
bundle_report compatibility --ruby-version=3.3
|
|
97
|
+
|
|
98
|
+
# Find minimum Ruby version compatible with Rails 7.2
|
|
99
|
+
bundle_report ruby_check --rails-version=7.2
|
|
100
|
+
|
|
101
|
+
# Help
|
|
102
|
+
bundle_report --help
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Deprecation Tracking
|
|
106
|
+
|
|
107
|
+
Track deprecation warnings in your test suite so you can monitor and fix them incrementally.
|
|
108
|
+
|
|
109
|
+
### RSpec
|
|
110
|
+
|
|
111
|
+
Add to `rails_helper.rb` or `spec_helper.rb`:
|
|
77
112
|
|
|
78
113
|
```ruby
|
|
79
114
|
RSpec.configure do |config|
|
|
80
|
-
# Tracker deprecation messages in each file
|
|
81
115
|
if ENV["DEPRECATION_TRACKER"]
|
|
82
116
|
DeprecationTracker.track_rspec(
|
|
83
117
|
config,
|
|
@@ -89,10 +123,11 @@ RSpec.configure do |config|
|
|
|
89
123
|
end
|
|
90
124
|
```
|
|
91
125
|
|
|
92
|
-
|
|
126
|
+
### Minitest
|
|
127
|
+
|
|
128
|
+
Add near the top of `test_helper.rb`:
|
|
93
129
|
|
|
94
130
|
```ruby
|
|
95
|
-
# Tracker deprecation messages in each file
|
|
96
131
|
if ENV["DEPRECATION_TRACKER"]
|
|
97
132
|
DeprecationTracker.track_minitest(
|
|
98
133
|
shitlist_path: "test/support/deprecation_warning.shitlist.json",
|
|
@@ -102,105 +137,125 @@ if ENV["DEPRECATION_TRACKER"]
|
|
|
102
137
|
end
|
|
103
138
|
```
|
|
104
139
|
|
|
105
|
-
>
|
|
140
|
+
> [!NOTE]
|
|
141
|
+
> This is currently not compatible with the `minitest/parallel_fork` gem.
|
|
106
142
|
|
|
107
|
-
|
|
143
|
+
### Running deprecation tracking
|
|
108
144
|
|
|
109
145
|
```bash
|
|
110
|
-
#
|
|
146
|
+
# Save current deprecations to the shitlist
|
|
111
147
|
DEPRECATION_TRACKER=save rspec
|
|
112
|
-
|
|
148
|
+
|
|
149
|
+
# Fail if deprecations have changed since the last save
|
|
113
150
|
DEPRECATION_TRACKER=compare rspec
|
|
114
151
|
```
|
|
115
152
|
|
|
116
|
-
|
|
153
|
+
### Parallel CI support
|
|
117
154
|
|
|
118
|
-
|
|
155
|
+
When running tests across parallel CI nodes, each node can write to its own shard file to avoid conflicts. The tracker auto-detects the node index from common CI environment variables (`CI_NODE_INDEX`, `CIRCLE_NODE_INDEX`, `BUILDKITE_PARALLEL_JOB`, `SEMAPHORE_JOB_INDEX`, `CI_NODE_INDEX` for GitLab), or you can set it explicitly via the `node_index` option.
|
|
119
156
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
157
|
+
#### RSpec
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
RSpec.configure do |config|
|
|
161
|
+
if ENV["DEPRECATION_TRACKER"]
|
|
162
|
+
DeprecationTracker.track_rspec(
|
|
163
|
+
config,
|
|
164
|
+
node_index: ENV["CI_NODE_INDEX"]
|
|
165
|
+
)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
125
168
|
```
|
|
126
169
|
|
|
127
|
-
|
|
170
|
+
The `node_index` option is only used in save mode. When set, the tracker writes to a shard file (e.g. `deprecation_warning.shitlist.node-0.json`) instead of the canonical file. Compare mode does not support `node_index` and will raise an error if passed—compare should only run after merging shards on the final canonical shitlist.
|
|
128
171
|
|
|
129
|
-
####
|
|
172
|
+
#### Merging shards
|
|
130
173
|
|
|
131
|
-
|
|
174
|
+
After all parallel nodes finish saving, merge shards into the canonical file:
|
|
132
175
|
|
|
133
176
|
```bash
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
```
|
|
177
|
+
# Merge all shard files and remove them afterwards
|
|
178
|
+
deprecations merge --delete-shards
|
|
137
179
|
|
|
138
|
-
|
|
180
|
+
# Or use --next to merge shards for the next Rails version
|
|
181
|
+
deprecations merge --next --delete-shards
|
|
182
|
+
```
|
|
139
183
|
|
|
140
|
-
|
|
184
|
+
You can also merge shards programmatically:
|
|
141
185
|
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
186
|
+
```ruby
|
|
187
|
+
DeprecationTracker.merge_shards(
|
|
188
|
+
"spec/support/deprecation_warning.shitlist.json",
|
|
189
|
+
delete_shards: true
|
|
190
|
+
)
|
|
147
191
|
```
|
|
148
192
|
|
|
149
|
-
|
|
193
|
+
#### Example CI workflow
|
|
150
194
|
|
|
151
|
-
|
|
195
|
+
```yaml
|
|
196
|
+
# 1. Save phase — each parallel node writes its own shard
|
|
197
|
+
# (runs on every node)
|
|
198
|
+
DEPRECATION_TRACKER=save CI_NODE_INDEX=$NODE bundle exec rspec <subset>
|
|
152
199
|
|
|
153
|
-
|
|
200
|
+
# 2. Merge phase — fan-in step, runs once after all nodes finish
|
|
201
|
+
deprecations merge --delete-shards
|
|
154
202
|
|
|
155
|
-
|
|
156
|
-
|
|
203
|
+
# 3. Compare phase — each parallel node checks only its own buckets
|
|
204
|
+
# against the merged canonical file (no CI_NODE_INDEX needed)
|
|
205
|
+
DEPRECATION_TRACKER=compare bundle exec rspec <subset>
|
|
157
206
|
```
|
|
158
207
|
|
|
159
|
-
|
|
208
|
+
### `deprecations` command
|
|
160
209
|
|
|
161
|
-
|
|
210
|
+
View, filter, and manage stored deprecation warnings:
|
|
162
211
|
|
|
163
|
-
|
|
212
|
+
```bash
|
|
213
|
+
deprecations info
|
|
214
|
+
deprecations info --pattern "ActiveRecord::Base"
|
|
215
|
+
deprecations merge --delete-shards
|
|
216
|
+
deprecations run
|
|
217
|
+
deprecations --help
|
|
218
|
+
```
|
|
164
219
|
|
|
165
|
-
|
|
220
|
+
## CLI Reference
|
|
166
221
|
|
|
167
|
-
|
|
222
|
+
```bash
|
|
223
|
+
bundle exec next_rails --init # Set up dual boot
|
|
224
|
+
bundle exec next_rails --version # Show gem version
|
|
225
|
+
bundle exec next_rails --help # Show help
|
|
226
|
+
```
|
|
168
227
|
|
|
169
|
-
|
|
228
|
+
## Contributing
|
|
170
229
|
|
|
171
|
-
|
|
230
|
+
Bug reports and pull requests are welcome! See the [Contributing guide](CONTRIBUTING.md) for setup instructions and guidelines.
|
|
172
231
|
|
|
173
|
-
|
|
174
|
-
The Gemfile.next.lock is initialized with the contents of your existing
|
|
175
|
-
Gemfile.lock lock file. We initialize the Gemfile.next.lock to prevent
|
|
176
|
-
major version jumps when running the next version of Rails.
|
|
232
|
+
## Releases
|
|
177
233
|
|
|
178
|
-
|
|
234
|
+
`next_rails` follows [Semantic Versioning](https://semver.org). Given a version number `MAJOR.MINOR.PATCH`, we increment the:
|
|
179
235
|
|
|
180
|
-
|
|
236
|
+
- **MAJOR** version for incompatible API changes
|
|
237
|
+
- **MINOR** version for backwards-compatible new functionality
|
|
238
|
+
- **PATCH** version for backwards-compatible bug fixes
|
|
181
239
|
|
|
182
|
-
|
|
240
|
+
### Steps to release a new version
|
|
183
241
|
|
|
184
|
-
|
|
242
|
+
1. Update the version number in `lib/next_rails/version.rb`
|
|
243
|
+
2. Update `CHANGELOG.md` with the appropriate headers and entries
|
|
244
|
+
3. Commit your changes to a `release/v1.x.x` branch
|
|
245
|
+
4. Push your changes and submit a pull request `Release v1.x.x`
|
|
246
|
+
5. Merge your pull request to the `main` branch
|
|
247
|
+
6. Tag the latest version on `main`: `git tag v1.x.x`
|
|
248
|
+
7. Push the tag to GitHub: `git push --tags`
|
|
249
|
+
8. Build the gem: `gem build next_rails.gemspec`
|
|
250
|
+
9. Push to RubyGems: `gem push next_rails-1.x.x.gem`
|
|
185
251
|
|
|
186
|
-
|
|
252
|
+
## Maintainers
|
|
187
253
|
|
|
188
|
-
|
|
189
|
-
2. MINOR version when you add functionality in a backwards compatible manner, and
|
|
190
|
-
3. PATCH version when you make backwards compatible bug fixes.
|
|
254
|
+
Maintained by [OmbuLabs / FastRuby.io](https://www.fastruby.io).
|
|
191
255
|
|
|
192
|
-
|
|
256
|
+
## History
|
|
193
257
|
|
|
194
|
-
|
|
195
|
-
2. Update `CHANGELOG.md` to have the right headers
|
|
196
|
-
3. Commit your changes to a `release/v-1-1-0` branch
|
|
197
|
-
4. Push your changes and submit a pull request
|
|
198
|
-
5. Merge your pull request to the `main` branch
|
|
199
|
-
6. Git tag the latest version of the `main` branch (`git tag v1.1.0`)
|
|
200
|
-
7. Push tags to GitHub (`git push --tags`)
|
|
201
|
-
8. Build the gem (`gem build next_rails.gemspec`)
|
|
202
|
-
9. Push the .gem package to Rubygems.org (`gem push next_rails-1.1.0.gem`)
|
|
203
|
-
10. You are all done!
|
|
258
|
+
This gem started as a fork of [`ten_years_rails`](https://github.com/clio/ten_years_rails), a companion to the "[Ten Years of Rails Upgrades](https://www.youtube.com/watch?v=6aCfc0DkSFo)" conference talk by Jordan Raine.
|
|
204
259
|
|
|
205
260
|
## License
|
|
206
261
|
|
data/exe/deprecations
CHANGED
|
@@ -3,6 +3,7 @@ require "json"
|
|
|
3
3
|
require "rainbow"
|
|
4
4
|
require "optparse"
|
|
5
5
|
require "set"
|
|
6
|
+
require_relative "../lib/deprecation_tracker/shard_merger"
|
|
6
7
|
|
|
7
8
|
def run_tests(deprecation_warnings, opts = {})
|
|
8
9
|
tracker_mode = opts[:tracker_mode]
|
|
@@ -49,6 +50,7 @@ option_parser = OptionParser.new do |opts|
|
|
|
49
50
|
bin/deprecations --next info # Show top ten deprecations for Rails 5
|
|
50
51
|
bin/deprecations --pattern "ActiveRecord::Base" --verbose info # Show full details on deprecations matching pattern
|
|
51
52
|
bin/deprecations --tracker-mode save --pattern "pass" run # Run tests that output deprecations matching pattern and update shitlist
|
|
53
|
+
bin/deprecations merge --delete-shards # Merge parallel CI shards and remove shard files
|
|
52
54
|
|
|
53
55
|
Modes:
|
|
54
56
|
info
|
|
@@ -57,6 +59,9 @@ option_parser = OptionParser.new do |opts|
|
|
|
57
59
|
run
|
|
58
60
|
Run tests that are known to cause deprecation warnings. Use --pattern to filter what tests are run.
|
|
59
61
|
|
|
62
|
+
merge
|
|
63
|
+
Merge parallel CI shard files into the canonical shitlist. Use with --delete-shards to remove shard files after merging.
|
|
64
|
+
|
|
60
65
|
Options:
|
|
61
66
|
MESSAGE
|
|
62
67
|
|
|
@@ -76,6 +81,10 @@ option_parser = OptionParser.new do |opts|
|
|
|
76
81
|
options[:verbose] = true
|
|
77
82
|
end
|
|
78
83
|
|
|
84
|
+
opts.on("--delete-shards", "Delete shard files after merging") do
|
|
85
|
+
options[:delete_shards] = true
|
|
86
|
+
end
|
|
87
|
+
|
|
79
88
|
opts.on_tail("-h", "--help", "Prints this help") do
|
|
80
89
|
puts opts
|
|
81
90
|
exit
|
|
@@ -87,24 +96,34 @@ option_parser.parse!
|
|
|
87
96
|
options[:mode] = ARGV.last
|
|
88
97
|
path = options[:next] ? "spec/support/deprecation_warning.next.shitlist.json" : "spec/support/deprecation_warning.shitlist.json"
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
case options[:mode]
|
|
100
|
+
when "merge"
|
|
101
|
+
output = DeprecationTracker::ShardMerger.new(path, delete_shards: !!options[:delete_shards]).merge
|
|
102
|
+
shards = output[:shards]
|
|
103
|
+
result = output[:result]
|
|
104
|
+
total_messages = result.values.map(&:size).reduce(0, :+)
|
|
105
|
+
puts "Merged #{shards} shard files into #{path} (#{result.size} buckets, #{total_messages} deprecation messages)"
|
|
106
|
+
when "run", "info"
|
|
107
|
+
pattern_string = options.fetch(:pattern, ".+")
|
|
108
|
+
pattern = /#{pattern_string}/
|
|
109
|
+
|
|
110
|
+
deprecation_warnings = JSON.parse(File.read(path)).each_with_object({}) do |(test_file, messages), hash|
|
|
111
|
+
filtered_messages = messages.select {|message| message.match(pattern) }
|
|
112
|
+
hash[test_file] = filtered_messages if !filtered_messages.empty?
|
|
113
|
+
end
|
|
97
114
|
|
|
98
|
-
if deprecation_warnings.empty?
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
end
|
|
115
|
+
if deprecation_warnings.empty?
|
|
116
|
+
abort "No test files with deprecations matching #{pattern.inspect}."
|
|
117
|
+
exit 2
|
|
118
|
+
end
|
|
102
119
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
120
|
+
if options[:mode] == "run"
|
|
121
|
+
run_tests(deprecation_warnings, next_mode: options[:next], tracker_mode: options[:tracker_mode])
|
|
122
|
+
else
|
|
123
|
+
print_info(deprecation_warnings, verbose: options[:verbose])
|
|
124
|
+
end
|
|
106
125
|
when nil
|
|
107
|
-
STDERR.puts Rainbow("Must pass a mode: run or
|
|
126
|
+
STDERR.puts Rainbow("Must pass a mode: run, info, or merge").red
|
|
108
127
|
puts option_parser
|
|
109
128
|
exit 1
|
|
110
129
|
else
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
|
|
4
|
+
class DeprecationTracker
|
|
5
|
+
class ShardMerger
|
|
6
|
+
attr_reader :base_path, :delete_shards
|
|
7
|
+
|
|
8
|
+
def initialize(base_path, delete_shards: false)
|
|
9
|
+
@base_path = base_path
|
|
10
|
+
@delete_shards = delete_shards
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def merge
|
|
14
|
+
dirname = File.dirname(base_path)
|
|
15
|
+
unless File.directory?(dirname)
|
|
16
|
+
warn "Directory does not exist: #{dirname}"
|
|
17
|
+
return { shards: 0, result: {} }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
shard_files = Dir.glob(shard_glob).sort
|
|
21
|
+
|
|
22
|
+
if shard_files.empty?
|
|
23
|
+
warn "No shards found at #{shard_glob}"
|
|
24
|
+
return { shards: 0, result: {} }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
merged = {}
|
|
28
|
+
shard_files.each do |file|
|
|
29
|
+
parse_shard(file).each do |bucket, messages|
|
|
30
|
+
merged[bucket] = (merged[bucket] || []).concat(Array(messages))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
result = {}
|
|
35
|
+
merged.sort.each do |k, v|
|
|
36
|
+
result[k] = v.sort
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
begin
|
|
40
|
+
File.write(base_path, JSON.pretty_generate(result))
|
|
41
|
+
rescue Errno::EACCES => e
|
|
42
|
+
raise "Cannot write to #{base_path}: #{e.message}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
shard_files.each { |f| File.delete(f) } if delete_shards
|
|
46
|
+
|
|
47
|
+
{ shards: shard_files.size, result: result }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def shard_glob
|
|
53
|
+
"#{base_path.chomp('.json')}.node-*.json"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def parse_shard(file)
|
|
57
|
+
JSON.parse(File.read(file))
|
|
58
|
+
rescue Errno::ENOENT
|
|
59
|
+
raise "Shard file not found: #{file}"
|
|
60
|
+
rescue JSON::ParserError => e
|
|
61
|
+
raise "Invalid JSON in shard file #{file}: #{e.message}"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/deprecation_tracker.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "next_rails/tint"
|
|
2
2
|
require "json"
|
|
3
3
|
|
|
4
4
|
# A shitlist for deprecation warnings during test runs. It has two modes: "save" and "compare"
|
|
@@ -73,11 +73,14 @@ class DeprecationTracker
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
DEFAULT_PATH = "spec/support/deprecation_warning.shitlist.json"
|
|
77
|
+
|
|
76
78
|
def self.init_tracker(opts = {})
|
|
77
|
-
shitlist_path = opts[:shitlist_path]
|
|
78
|
-
mode = opts[:mode]
|
|
79
|
+
shitlist_path = opts[:shitlist_path] || DEFAULT_PATH
|
|
80
|
+
mode = opts[:mode] || ENV["DEPRECATION_TRACKER"] || :save
|
|
79
81
|
transform_message = opts[:transform_message]
|
|
80
|
-
|
|
82
|
+
node_index = opts[:node_index]
|
|
83
|
+
deprecation_tracker = DeprecationTracker.new(shitlist_path, transform_message, mode, node_index: node_index)
|
|
81
84
|
# Since Rails 7.1 the preferred way to track deprecations is to use the deprecation trackers via
|
|
82
85
|
# `Rails.application.deprecators`.
|
|
83
86
|
# We fallback to tracking deprecations via the ActiveSupport singleton object if Rails.application.deprecators is
|
|
@@ -126,13 +129,35 @@ class DeprecationTracker
|
|
|
126
129
|
ActiveSupport::TestCase.include(MinitestExtension.new(tracker))
|
|
127
130
|
end
|
|
128
131
|
|
|
129
|
-
|
|
132
|
+
def self.merge_shards(base_path, delete_shards: false)
|
|
133
|
+
require_relative "deprecation_tracker/shard_merger"
|
|
134
|
+
ShardMerger.new(base_path, delete_shards: delete_shards).merge[:result]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
attr_reader :deprecation_messages, :shitlist_path, :transform_message, :bucket, :mode, :node_index
|
|
130
138
|
|
|
131
|
-
def initialize(shitlist_path, transform_message = nil, mode = :save)
|
|
139
|
+
def initialize(shitlist_path, transform_message = nil, mode = :save, node_index: nil)
|
|
132
140
|
@shitlist_path = shitlist_path
|
|
133
141
|
@transform_message = transform_message || -> (message) { message }
|
|
134
142
|
@deprecation_messages = {}
|
|
135
|
-
@mode = mode.to_sym
|
|
143
|
+
@mode = mode ? mode.to_sym : :save
|
|
144
|
+
if @mode == :compare && node_index
|
|
145
|
+
raise ArgumentError, "node_index cannot be used with compare mode"
|
|
146
|
+
end
|
|
147
|
+
@node_index = node_index
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def parallel?
|
|
151
|
+
!@node_index.nil?
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def shard_path
|
|
155
|
+
ext = File.extname(shitlist_path)
|
|
156
|
+
"#{shitlist_path.chomp(ext)}.node-#{node_index}#{ext}"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def target_path
|
|
160
|
+
parallel? ? shard_path : shitlist_path
|
|
136
161
|
end
|
|
137
162
|
|
|
138
163
|
def add(message)
|
|
@@ -155,16 +180,17 @@ class DeprecationTracker
|
|
|
155
180
|
end
|
|
156
181
|
|
|
157
182
|
def compare
|
|
158
|
-
|
|
183
|
+
stored = read_json(shitlist_path)
|
|
159
184
|
|
|
160
185
|
changed_buckets = []
|
|
186
|
+
|
|
161
187
|
normalized_deprecation_messages.each do |bucket, messages|
|
|
162
|
-
if
|
|
188
|
+
if stored[bucket] != messages
|
|
163
189
|
changed_buckets << bucket
|
|
164
190
|
end
|
|
165
191
|
end
|
|
166
192
|
|
|
167
|
-
if changed_buckets.
|
|
193
|
+
if changed_buckets.any?
|
|
168
194
|
message = <<-MESSAGE
|
|
169
195
|
⚠️ Deprecation warnings have changed!
|
|
170
196
|
|
|
@@ -183,33 +209,33 @@ class DeprecationTracker
|
|
|
183
209
|
See \e[4;37mdev-docs/testing/deprecation_tracker.md\e[0;31m for more information.
|
|
184
210
|
MESSAGE
|
|
185
211
|
|
|
186
|
-
raise UnexpectedDeprecations,
|
|
212
|
+
raise UnexpectedDeprecations, NextRails::Tint(message).red
|
|
187
213
|
end
|
|
188
214
|
end
|
|
189
215
|
|
|
190
216
|
def diff
|
|
191
|
-
|
|
192
|
-
`git diff --no-index #{shitlist_path} #{
|
|
217
|
+
temp_file = create_temp_file
|
|
218
|
+
`git diff --no-index #{shitlist_path} #{temp_file.path}`
|
|
193
219
|
ensure
|
|
194
|
-
|
|
220
|
+
temp_file.delete
|
|
195
221
|
end
|
|
196
222
|
|
|
197
223
|
def save
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
FileUtils.cp(
|
|
224
|
+
temp_file = create_temp_file
|
|
225
|
+
create_if_path_does_not_exist(target_path)
|
|
226
|
+
FileUtils.cp(temp_file.path, target_path)
|
|
201
227
|
ensure
|
|
202
|
-
|
|
228
|
+
temp_file.delete if temp_file
|
|
203
229
|
end
|
|
204
230
|
|
|
205
|
-
def
|
|
206
|
-
dirname = File.dirname(
|
|
231
|
+
def create_if_path_does_not_exist(path)
|
|
232
|
+
dirname = File.dirname(path)
|
|
207
233
|
unless File.directory?(dirname)
|
|
208
234
|
FileUtils.mkdir_p(dirname)
|
|
209
235
|
end
|
|
210
236
|
end
|
|
211
237
|
|
|
212
|
-
def
|
|
238
|
+
def create_temp_file
|
|
213
239
|
temp_file = Tempfile.new("temp-deprecation-tracker-shitlist")
|
|
214
240
|
temp_file.write(JSON.pretty_generate(normalized_deprecation_messages))
|
|
215
241
|
temp_file.flush
|
|
@@ -219,22 +245,24 @@ class DeprecationTracker
|
|
|
219
245
|
|
|
220
246
|
# Normalize deprecation messages to reduce noise from file output and test files to be tracked with separate test runs
|
|
221
247
|
def normalized_deprecation_messages
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
248
|
+
@normalized_deprecation_messages ||= begin
|
|
249
|
+
normalized = read_json(target_path).merge(deprecation_messages).each_with_object({}) do |(bucket, messages), hash|
|
|
250
|
+
hash[bucket] = messages.sort
|
|
251
|
+
end
|
|
225
252
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
253
|
+
# not using `to_h` here to support older ruby versions
|
|
254
|
+
{}.tap do |h|
|
|
255
|
+
normalized.reject {|_key, value| value.empty? }.sort_by {|key, _value| key }.each do |k ,v|
|
|
256
|
+
h[k] = v
|
|
257
|
+
end
|
|
230
258
|
end
|
|
231
259
|
end
|
|
232
260
|
end
|
|
233
261
|
|
|
234
|
-
def
|
|
235
|
-
return {} unless File.exist?(
|
|
236
|
-
JSON.parse(File.read(
|
|
262
|
+
def read_json(path)
|
|
263
|
+
return {} unless File.exist?(path)
|
|
264
|
+
JSON.parse(File.read(path))
|
|
237
265
|
rescue JSON::ParserError => e
|
|
238
|
-
raise "#{
|
|
266
|
+
raise "#{path} is not valid JSON: #{e.message}"
|
|
239
267
|
end
|
|
240
268
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "optparse"
|
|
4
4
|
require "next_rails"
|
|
5
5
|
require "next_rails/bundle_report"
|
|
6
|
+
require "next_rails/tint"
|
|
6
7
|
|
|
7
8
|
class NextRails::BundleReport::CLI
|
|
8
9
|
def initialize(argv)
|
|
@@ -89,7 +90,7 @@ class NextRails::BundleReport::CLI
|
|
|
89
90
|
begin
|
|
90
91
|
option_parser.parse!(@argv)
|
|
91
92
|
rescue OptionParser::ParseError => e
|
|
92
|
-
warn
|
|
93
|
+
warn NextRails::Tint(e.message).red
|
|
93
94
|
puts option_parser
|
|
94
95
|
exit 1
|
|
95
96
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require "next_rails/tint"
|
|
2
|
+
|
|
1
3
|
class NextRails::BundleReport::RailsVersionCompatibility
|
|
2
4
|
def initialize(gems: NextRails::GemInfo.all, options: {})
|
|
3
5
|
@gems = gems
|
|
@@ -20,8 +22,8 @@ class NextRails::BundleReport::RailsVersionCompatibility
|
|
|
20
22
|
def erb_output
|
|
21
23
|
template = <<-ERB
|
|
22
24
|
<% if incompatible_gems_by_state[:found_compatible] -%>
|
|
23
|
-
<%=
|
|
24
|
-
<%=
|
|
25
|
+
<%= NextRails::Tint("=> Incompatible with Rails #{rails_version} (with new versions that are compatible):").white.bold %>
|
|
26
|
+
<%= NextRails::Tint("These gems will need to be upgraded before upgrading to Rails #{rails_version}.").italic %>
|
|
25
27
|
|
|
26
28
|
<% incompatible_gems_by_state[:found_compatible].each do |gem| -%>
|
|
27
29
|
<%= gem_header(gem) %> - upgrade to <%= gem.latest_compatible_version.version %>
|
|
@@ -29,8 +31,8 @@ class NextRails::BundleReport::RailsVersionCompatibility
|
|
|
29
31
|
|
|
30
32
|
<% end -%>
|
|
31
33
|
<% if incompatible_gems_by_state[:incompatible] -%>
|
|
32
|
-
<%=
|
|
33
|
-
<%=
|
|
34
|
+
<%= NextRails::Tint("=> Incompatible with Rails #{rails_version} (with no new compatible versions):").white.bold %>
|
|
35
|
+
<%= NextRails::Tint("These gems will need to be removed or replaced before upgrading to Rails #{rails_version}.").italic %>
|
|
34
36
|
|
|
35
37
|
<% incompatible_gems_by_state[:incompatible].each do |gem| -%>
|
|
36
38
|
<%= gem_header(gem) %> - new version, <%= gem.latest_version.version %>, is not compatible with Rails #{rails_version}
|
|
@@ -38,16 +40,16 @@ class NextRails::BundleReport::RailsVersionCompatibility
|
|
|
38
40
|
|
|
39
41
|
<% end -%>
|
|
40
42
|
<% if incompatible_gems_by_state[:no_new_version] -%>
|
|
41
|
-
<%=
|
|
42
|
-
<%=
|
|
43
|
-
<%=
|
|
43
|
+
<%= NextRails::Tint("=> Incompatible with Rails #{rails_version} (with no new versions):").white.bold %>
|
|
44
|
+
<%= NextRails::Tint("These gems will need to be upgraded by us or removed before upgrading to Rails #{rails_version}.").italic %>
|
|
45
|
+
<%= NextRails::Tint("This list is likely to contain internal gems, like Cuddlefish.").italic %>
|
|
44
46
|
|
|
45
47
|
<% incompatible_gems_by_state[:no_new_version].each do |gem| -%>
|
|
46
48
|
<%= gem_header(gem) %> - new version not found
|
|
47
49
|
<% end -%>
|
|
48
50
|
|
|
49
51
|
<% end -%>
|
|
50
|
-
<%=
|
|
52
|
+
<%= NextRails::Tint(incompatible_gems.length.to_s).red %> gems incompatible with Rails <%= rails_version %>
|
|
51
53
|
ERB
|
|
52
54
|
|
|
53
55
|
erb_version = ERB.version
|
|
@@ -63,9 +65,9 @@ class NextRails::BundleReport::RailsVersionCompatibility
|
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
def gem_header(_gem)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
parts = [NextRails::Tint("#{_gem.name} #{_gem.version}").bold]
|
|
69
|
+
parts << NextRails::Tint(" (loaded from git)").magenta if _gem.sourced_from_git?
|
|
70
|
+
parts.join
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
def incompatible_gems
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "next_rails/tint"
|
|
2
2
|
|
|
3
3
|
class NextRails::BundleReport::RubyVersionCompatibility
|
|
4
4
|
MINIMAL_VERSION = 1.0
|
|
@@ -10,20 +10,20 @@ class NextRails::BundleReport::RubyVersionCompatibility
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def generate
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
message
|
|
13
|
+
(valid? ? message : invalid_message).to_s
|
|
16
14
|
end
|
|
17
15
|
|
|
18
16
|
private
|
|
19
17
|
|
|
20
18
|
def message
|
|
21
|
-
|
|
19
|
+
noun = incompatible.one? ? "gem" : "gems"
|
|
20
|
+
parts = [NextRails::Tint("=> Incompatible gems with Ruby #{ruby_version}:").white.bold]
|
|
22
21
|
incompatible.each do |gem|
|
|
23
|
-
|
|
22
|
+
parts << NextRails::Tint("#{gem.name} - required Ruby version: #{gem.gem_specification.required_ruby_version}").magenta
|
|
24
23
|
end
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
parts << ""
|
|
25
|
+
parts << NextRails::Tint("#{incompatible.length} incompatible #{noun} with Ruby #{ruby_version}").red
|
|
26
|
+
parts.join("\n")
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def incompatible
|
|
@@ -35,7 +35,7 @@ class NextRails::BundleReport::RubyVersionCompatibility
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def invalid_message
|
|
38
|
-
|
|
38
|
+
NextRails::Tint("=> Invalid Ruby version: #{options[:ruby_version]}.").red.bold
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def valid?
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "next_rails/tint"
|
|
2
2
|
require "cgi"
|
|
3
3
|
require "erb"
|
|
4
4
|
require "json"
|
|
@@ -105,14 +105,14 @@ module NextRails
|
|
|
105
105
|
header = "#{gem.name} #{gem.version}"
|
|
106
106
|
|
|
107
107
|
puts <<-MESSAGE
|
|
108
|
-
#{
|
|
108
|
+
#{NextRails::Tint(header).bold.white}: released #{gem.age} (latest version, #{gem.latest_version.version}, released #{gem.latest_version.age})
|
|
109
109
|
MESSAGE
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
percentage_out_of_date = ((out_of_date_gems.count / total_gem_count.to_f) * 100).round
|
|
113
113
|
footer = <<-MESSAGE
|
|
114
|
-
#{
|
|
115
|
-
#{
|
|
114
|
+
#{NextRails::Tint(sourced_from_git_count.to_s).yellow} gems are sourced from git
|
|
115
|
+
#{NextRails::Tint(out_of_date_gems.count.to_s).red} of the #{total_gem_count} gems are out-of-date (#{percentage_out_of_date}%)
|
|
116
116
|
MESSAGE
|
|
117
117
|
|
|
118
118
|
puts ''
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NextRails
|
|
4
|
+
# Lightweight ANSI color/style wrapper with chainable style methods.
|
|
5
|
+
# Wrap a string with `NextRails::Tint("text")` then chain styles:
|
|
6
|
+
#
|
|
7
|
+
# NextRails::Tint("hello").red.bold
|
|
8
|
+
#
|
|
9
|
+
# Instances are effectively immutable: each style method returns a new
|
|
10
|
+
# `Tint` rather than mutating the receiver, so a reference can be reused
|
|
11
|
+
# without styles accumulating across chains.
|
|
12
|
+
class Tint
|
|
13
|
+
CODES = {
|
|
14
|
+
bold: 1,
|
|
15
|
+
italic: 3,
|
|
16
|
+
red: 31,
|
|
17
|
+
green: 32,
|
|
18
|
+
yellow: 33,
|
|
19
|
+
blue: 34,
|
|
20
|
+
magenta: 35,
|
|
21
|
+
cyan: 36,
|
|
22
|
+
white: 37
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
def initialize(string, codes = [])
|
|
26
|
+
@string = string.to_s
|
|
27
|
+
@codes = codes
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
CODES.each_key do |style|
|
|
31
|
+
define_method(style) do
|
|
32
|
+
self.class.new(@string, @codes + [CODES[style]])
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def to_s
|
|
37
|
+
return @string if @codes.empty?
|
|
38
|
+
|
|
39
|
+
"\e[#{@codes.join(";")}m#{@string}\e[0m"
|
|
40
|
+
end
|
|
41
|
+
alias_method :to_str, :to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.Tint(string)
|
|
45
|
+
Tint.new(string)
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/next_rails/version.rb
CHANGED
data/next_rails.gemspec
CHANGED
|
@@ -22,8 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
23
23
|
spec.require_paths = ["lib"]
|
|
24
24
|
|
|
25
|
-
spec.
|
|
26
|
-
spec.add_development_dependency "bundler", ">= 1.16", "< 3.0"
|
|
25
|
+
spec.add_development_dependency "bundler", ">= 1.16"
|
|
27
26
|
spec.add_development_dependency "rake"
|
|
28
27
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
29
28
|
spec.add_development_dependency "simplecov", "~> 0.17.1"
|
metadata
CHANGED
|
@@ -1,29 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: next_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ernesto Tagwerker
|
|
8
8
|
- Luis Sagastume
|
|
9
|
+
autorequire:
|
|
9
10
|
bindir: exe
|
|
10
11
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
12
|
+
date: 2026-05-07 00:00:00.000000000 Z
|
|
12
13
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: rainbow
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - ">="
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '3'
|
|
20
|
-
type: :runtime
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - ">="
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '3'
|
|
27
14
|
- !ruby/object:Gem::Dependency
|
|
28
15
|
name: bundler
|
|
29
16
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -31,9 +18,6 @@ dependencies:
|
|
|
31
18
|
- - ">="
|
|
32
19
|
- !ruby/object:Gem::Version
|
|
33
20
|
version: '1.16'
|
|
34
|
-
- - "<"
|
|
35
|
-
- !ruby/object:Gem::Version
|
|
36
|
-
version: '3.0'
|
|
37
21
|
type: :development
|
|
38
22
|
prerelease: false
|
|
39
23
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -41,9 +25,6 @@ dependencies:
|
|
|
41
25
|
- - ">="
|
|
42
26
|
- !ruby/object:Gem::Version
|
|
43
27
|
version: '1.16'
|
|
44
|
-
- - "<"
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '3.0'
|
|
47
28
|
- !ruby/object:Gem::Dependency
|
|
48
29
|
name: rake
|
|
49
30
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -194,6 +175,7 @@ files:
|
|
|
194
175
|
- exe/next.sh
|
|
195
176
|
- exe/next_rails
|
|
196
177
|
- lib/deprecation_tracker.rb
|
|
178
|
+
- lib/deprecation_tracker/shard_merger.rb
|
|
197
179
|
- lib/next_rails.rb
|
|
198
180
|
- lib/next_rails/bundle_report.rb
|
|
199
181
|
- lib/next_rails/bundle_report/cli.rb
|
|
@@ -201,6 +183,7 @@ files:
|
|
|
201
183
|
- lib/next_rails/bundle_report/ruby_version_compatibility.rb
|
|
202
184
|
- lib/next_rails/gem_info.rb
|
|
203
185
|
- lib/next_rails/init.rb
|
|
186
|
+
- lib/next_rails/tint.rb
|
|
204
187
|
- lib/next_rails/version.rb
|
|
205
188
|
- next_rails.gemspec
|
|
206
189
|
- pull_request_template.md
|
|
@@ -208,6 +191,7 @@ homepage: https://github.com/fastruby/next_rails
|
|
|
208
191
|
licenses:
|
|
209
192
|
- MIT
|
|
210
193
|
metadata: {}
|
|
194
|
+
post_install_message:
|
|
211
195
|
rdoc_options: []
|
|
212
196
|
require_paths:
|
|
213
197
|
- lib
|
|
@@ -222,7 +206,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
222
206
|
- !ruby/object:Gem::Version
|
|
223
207
|
version: '0'
|
|
224
208
|
requirements: []
|
|
225
|
-
rubygems_version: 3.
|
|
209
|
+
rubygems_version: 3.4.19
|
|
210
|
+
signing_key:
|
|
226
211
|
specification_version: 4
|
|
227
212
|
summary: A toolkit to upgrade your next Rails application
|
|
228
213
|
test_files: []
|