railstest 0.3.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 71951ab80587ff5f52b0e1b7c2c21750968a08483bc86eafd6f9bd21897677e5
4
+ data.tar.gz: 9d07fd0026e0b492c1eab604f180db8a6619f0c107f05847b7023de37976b57f
5
+ SHA512:
6
+ metadata.gz: 9630820ae8c355a630329fe9ecbc8da31ba16ed1194b09f8d67edb8a316dbd0d10b1c16a6f51f95d997955c6657881f3c3878a182964ab6d6fe30aabaeaf83a9
7
+ data.tar.gz: 3957c00bfca988f2b3230eb6a38554da5c7ac0d5c09e90e27d55fb190f8491c39d85ced399398dadcdcd697314cf045f472d8987cef12db49369a9344643f2eb
data/CHANGELOG.md ADDED
@@ -0,0 +1,60 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.3.1] - 2026-06-16
10
+
11
+ ### Fixed
12
+ - Docker build no longer duplicates database adapter gems declared in the gem's own Gemfile
13
+ - `--db` omitted now leaves the gem's Gemfile adapter declarations untouched
14
+ - Removed `gem update --system` from Docker build (verbose changelog output leaked into failure dumps)
15
+ - In-place TTY progress updates: ⏳ overwrites to ✅/❌ as results arrive
16
+ - Aptfile support for system packages (e.g. `libvips-dev` for ruby-vips)
17
+
18
+ ## [0.3.0] - 2026-06-16
19
+
20
+ ### Added
21
+ - **All-combinations mode is now the default** — `railstest --gem-path .` runs every compatible Ruby/Rails combination without any flags
22
+ - **`-j N` / `--workers N`** — parallel workers for multi-combination runs (default: 1, sequential)
23
+ - **`--gemspec`** — static analysis mode: reads gemspec constraints and shows which matrix combinations fall in scope, no Docker required
24
+ - **Aptfile support** — if a gem has an `Aptfile` in its root, those system packages are installed in the Docker image (same convention as Heroku)
25
+ - **In-place progress updates** on TTY: all combinations show `⏳` immediately; each updates to `✅`/`❌` in place as results arrive
26
+
27
+ ### Changed
28
+ - Single-combination mode now requires both `--ruby` AND `--rails` together; either alone filters the matrix instead of pinning
29
+ - Docker image name now includes ruby+rails version to prevent cache collisions during parallel builds
30
+ - `--db` now installs only the requested adapter gem instead of all three; omitting `--db` leaves the gem's own Gemfile adapter declarations untouched
31
+ - `bundle install` is now run with `--quiet` to suppress gem installation noise from Docker build output
32
+ - Removed `gem update --system` from Docker build (verbose changelog output leaked into failure dumps, and the base image ships with a sufficient rubygems version)
33
+
34
+ ### Fixed
35
+ - Docker image tag sanitised to lowercase to satisfy Docker naming requirements
36
+ - Ruby versions below 3.2 clamped to 3.2 minimum (zeitwerk requires Ruby >= 3.2)
37
+ - Engine-mode Dockerfile no longer duplicates database adapter gems that are already declared in the gem's own Gemfile
38
+
39
+ ## [0.2.0] - 2026-06-16
40
+
41
+ ### Added
42
+ - Validates that a `test/` or `spec/` directory with test files exists before attempting a Docker build
43
+ - Rails engine detection: automatically identifies engines with `test/dummy/config/environment.rb` and tests them without volume mounting
44
+ - Self-test script (`run_self_test.sh`) with interactive mode and continue-on-error flag
45
+
46
+ ### Changed
47
+ - Gemfile detection in `gemfiles/` is more flexible — matches any file containing the version pattern, not just exact names
48
+
49
+ ## [0.1.0] - 2026-01-29
50
+
51
+ Docker-based CLI tool for testing Rails gems with any Ruby/Rails/database combination.
52
+
53
+ ### Features
54
+ - Two testing modes: local (for gems with `gemfiles/`) and target-gem (mount into fresh Rails app)
55
+ - Auto-detection of Ruby, Rails, and test framework from gem configuration
56
+ - Flexible gemfile naming - detects version patterns in any format (`rails_7.0.gemfile`, `Gemfile.rails-5.2-rc1`, etc.)
57
+ - Validates local mode usage - prevents `--gem-path` on gems with `gemfiles/` directory
58
+ - Target-gem mode handles gems that are already Rails dependencies (e.g., solid_queue)
59
+ - SQLite, MySQL, and PostgreSQL support
60
+ - Compatibility warnings with recommended version combinations
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Runar Ingbrigtsen
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,330 @@
1
+ # Railstest v0.3.1
2
+
3
+ A Docker-based CLI tool for testing Ruby gems. Runs tests on various Ruby, Rails, and database combinations with automatic caching.
4
+
5
+ ## Features
6
+
7
+ - **Tests all compatible combinations by default** — runs every Ruby/Rails combination from the built-in matrix; use `-j N` to parallelise
8
+ - **Single-combination mode** — specify both `--ruby` and `--rails` for fast one-off runs during active development
9
+ - **`--gemspec`** — instantly shows which combinations your gemspec claims to support, no Docker required
10
+ - **Two testing modes**: Local (for gems with `gemfiles/`) and Target-Gem (bakes gem into Docker image)
11
+ - **Rails engine support**: Automatically detects Rails engines with dummy apps and tests them correctly
12
+ - **Gem caching**: All dependencies cached in Docker layers for fast subsequent runs (~1.5s vs 2+ min)
13
+ - **Multiple databases**: SQLite, MySQL, and PostgreSQL support (automatically configured)
14
+ - **Test framework detection**: Automatically detects RSpec or Rails test
15
+ - **Docker isolation**: Reproducible tests in clean environments
16
+ - **Zero runtime dependencies**: Just Docker required
17
+
18
+ ### CLI Options
19
+ - `--ruby VERSION` - Filter to one Ruby version (or pin when combined with `--rails`)
20
+ - `--rails VERSION` - Filter to one Rails version (or pin when combined with `--ruby`), accepts 7.1 or 7_1 format
21
+ - `--db DATABASE` - Database: sqlite, mysql, postgres (default: sqlite)
22
+ - `--path PATH` - Run specific test file or directory
23
+ - `--gem-path PATH` - Path to the gem to test
24
+ - `--gemspec` - Show which combinations the gemspec claims to support (no Docker required)
25
+ - `-j N` / `--workers N` - Parallel workers when testing multiple combinations (default: 1, sequential)
26
+ - `--version` - Show version
27
+ - `--help` - Show help
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ gem install railstest
33
+ ```
34
+
35
+ Or add to your Gemfile:
36
+
37
+ ```ruby
38
+ gem "railstest"
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ### How `--ruby` and `--rails` work
44
+
45
+ These flags have different meanings depending on how many you supply:
46
+
47
+ | Command | Behaviour |
48
+ |---------|-----------|
49
+ | `railstest --gem-path .` | Tests all 18 compatible combinations sequentially |
50
+ | `railstest --gem-path . -j 4` | Same, 4 combinations at a time |
51
+ | `railstest --gem-path . --ruby 4.0` | All compatible Rails versions for Ruby 4.0 |
52
+ | `railstest --gem-path . --rails 8.1` | All compatible Ruby versions for Rails 8.1 |
53
+ | `railstest --gem-path . --ruby 4.0 --rails 8.1` | That one combination only |
54
+
55
+ Both together is single-combination mode — useful for fast iteration while fixing a specific failure. Either alone (or neither) runs the full matrix or a filtered slice of it.
56
+
57
+ ### Testing all combinations
58
+
59
+ ```bash
60
+ # Sequential — safe default, clear output
61
+ railstest --gem-path .
62
+
63
+ # 4 parallel workers — faster on a capable machine
64
+ railstest --gem-path . -j 4
65
+
66
+ # All Rails versions for one Ruby
67
+ railstest --gem-path . --ruby 4.0
68
+
69
+ # All Ruby versions for one Rails
70
+ railstest --gem-path . --rails 8.1
71
+ ```
72
+
73
+ Output shows each result as it finishes, with failure output collected at the end:
74
+
75
+ ```
76
+ Railstest testing spina against 18 combinations sequentially...
77
+
78
+ ✅ Ruby 3.2 + Rails 7.0 (124s)
79
+ ✅ Ruby 3.2 + Rails 7.1 (38s)
80
+ ❌ Ruby 4.0 + Rails 8.1 (52s)
81
+ ...
82
+
83
+ Failed combinations:
84
+
85
+ ❌ Ruby 4.0 + Rails 8.1
86
+ [output from that run]
87
+
88
+ ══════════════════════════════════════════════════
89
+ 17/18 combinations passed
90
+ ```
91
+
92
+ ### Single-combination mode
93
+
94
+ Specify both `--ruby` and `--rails` to test exactly one combination. Output streams in real-time, useful when actively fixing a failure:
95
+
96
+ ```bash
97
+ railstest --gem-path . --ruby 3.2 --rails 8.1
98
+ railstest --gem-path . --ruby 3.2 --rails 8.1 --db postgres
99
+ railstest --gem-path . --ruby 3.2 --rails 8.1 --path test/models/user_test.rb
100
+ ```
101
+
102
+ ### Inspecting gemspec support claims
103
+
104
+ `--gemspec` reads your gem's declared version constraints and shows which combinations from the railstest matrix fall in scope — no Docker required:
105
+
106
+ ```bash
107
+ railstest --gem-path . --gemspec
108
+ ```
109
+
110
+ ```
111
+ spina — declared support (gemspec)
112
+ ══════════════════════════════════════════════════
113
+
114
+ ruby >= 2.7.0 → railstest tests >= 3.2 (zeitwerk requires Ruby >= 3.2)
115
+ rails >= 7.0, < 9.0
116
+
117
+ 7.0 7.1 7.2 8.0 8.1
118
+ ──────────────────────────────────
119
+ 4.0 ✓ ✓ ✓ ✓
120
+ 3.4 ✓ ✓ ✓ ✓
121
+ 3.3 ✓ ✓ ✓ ✓ ✓
122
+ 3.2 ✓ ✓ ✓ ✓ ✓
123
+
124
+ 18 combinations in scope.
125
+ Run 'railstest --gem-path .' to test them.
126
+ ```
127
+
128
+ `✓` = in scope. `·` = in the railstest matrix but excluded by the gemspec's own constraints (e.g. if the gemspec declares `rails ~> 8.1`, all 7.x columns show `·`).
129
+
130
+ ### Rails Engine Support
131
+
132
+ Railstest automatically detects Rails engines (gems with `test/dummy/config/environment.rb`) and tests them correctly without volume mounting. Just point it at the engine:
133
+
134
+ ```bash
135
+ railstest --gem-path . # all combinations
136
+ railstest --gem-path . --ruby 3.2 --rails 8.1 # single combination
137
+ ```
138
+
139
+ ### Local Mode
140
+
141
+ For gems with a `gemfiles/` directory (like railstest itself):
142
+
143
+ ```bash
144
+ cd your-gem
145
+ railstest --ruby 3.2 --rails 7.0 # single combination
146
+ railstest --ruby 3.2 --rails 7.0 --db postgres
147
+ railstest --ruby 3.2 --rails 7.0 --path test/specific_test.rb
148
+ ```
149
+
150
+ ### Version resolution (single-combination mode only)
151
+
152
+ When both `--ruby` and `--rails` are given, railstest uses them directly. When only one is given, the other is resolved in this order:
153
+
154
+ **Ruby** (when `--ruby` is omitted):
155
+ 1. `.ruby-version` file
156
+ 2. `required_ruby_version` in gemspec
157
+ 3. Clamped to 3.2 if below (zeitwerk requires Ruby >= 3.2)
158
+
159
+ **Rails** (when `--rails` is omitted):
160
+ 1. Newest version in `gemfiles/` directory
161
+ 2. Rails dependency in `Gemfile`
162
+ 3. Rails dependency in gemspec
163
+
164
+ In multi-combination mode (`--ruby` and `--rails` not both given), versions come from the built-in compatibility matrix — auto-detection is not used.
165
+
166
+ ## Requirements
167
+
168
+ - Docker installed and running
169
+ - docker-compose or docker compose CLI
170
+
171
+ ## Supported Versions
172
+
173
+ ### What Versions Can Railstest Test?
174
+
175
+ **Railstest will test your gem with any Ruby and Rails versions you specify.** It uses Docker to provide the test environment, so you can test with any Ruby that still builds. Any Rails, or any combination your gem supports.
176
+
177
+ If railstest cannot auto-detect versions from your gem's `.ruby-version`, `Gemfile`, or gemspec, it will prompt you to specify them with `--ruby` and `--rails` flags.
178
+
179
+ ### Self-Test Compatibility Matrix
180
+
181
+ Railstest tests itself using these combinations (see `gemfiles/`):
182
+
183
+ | Ruby | Rails Versions |
184
+ |------|---------------|
185
+ | 4.0 | 7.1, 7.2, 8.0, 8.1 |
186
+ | 3.4 | 7.1, 7.2, 8.0, 8.1 |
187
+ | 3.3 | 7.0, 7.1, 7.2, 8.0, 8.1 |
188
+ | 3.2 | 7.0, 7.1, 7.2, 8.0, 8.1 |
189
+
190
+ **Self-test version policy:**
191
+ - Target each Rails minor with a pessimistic constraint (`gem 'rails', '~> X.Y.0'`) and run on the `ruby:X.Y` Docker image. Both float to the latest stable patch on their own, so there are no exact patch versions to keep up to date.
192
+ - Pin other dependencies only when a specific version is needed to resolve a conflict (the exception, not the rule).
193
+ - See `gemfiles/` for the per-version constraints.
194
+
195
+ ### Supported Ruby and Rails Versions
196
+
197
+ Railstest can test with **any** Ruby version that builds in Docker. Ruby 3.2+ is required for modern Rails (zeitwerk dependency). For Rails, any version from 7.0+ is supported; older versions may work but are not guaranteed.
198
+
199
+ ## How It Works
200
+
201
+ ### Local Mode
202
+ 1. Copies your gem directory into a Docker container
203
+ 2. Uses the gemfile from `gemfiles/rails_X_X.gemfile`
204
+ 3. Runs your gem's own `bin/rails test` or `bundle exec rspec`
205
+ 4. Perfect for gems with complete test infrastructure
206
+
207
+ ### Target-Gem Mode (Simple Gems)
208
+ 1. Creates a fresh Rails application in Docker during build
209
+ 2. Copies your gem files into the image (cached in layers)
210
+ 3. Installs all dependencies including database adapters (sqlite3, mysql2, pg)
211
+ 4. No volume mounting needed - everything baked into image
212
+ 5. Runs tests from your gem within the Rails app context
213
+
214
+ ### Rails Engine Mode (Automatic Detection)
215
+ 1. Detects engines by checking for `test/dummy/config/environment.rb`
216
+ 2. Copies engine files directly into test_app directory during build
217
+ 3. Installs dependencies with proper database adapters
218
+ 4. Tests run directly in the container without volume mounts
219
+ 5. Fast caching - all gems and code cached between runs
220
+
221
+ **Caching:** All layers are cached after first build. Subsequent runs complete in ~1.5 seconds vs 2+ minutes for full rebuilds.
222
+
223
+ ## Troubleshooting
224
+
225
+ ### "Missing required configuration" error
226
+ ```
227
+ Error: Ruby version not specified and could not be detected
228
+
229
+ Rails 8.0 requires Ruby 3.1+
230
+ Use --ruby 3.2 or later
231
+ ```
232
+ **Solution:** Add a `.ruby-version` file or use `--ruby VERSION` flag. Rails 7.0+ requires Ruby 3.2+ (zeitwerk dependency).
233
+
234
+ ### "Local mode requires a 'gemfiles/' directory" error
235
+ **Solution:** This gem should use target-gem mode:
236
+ ```bash
237
+ railstest --gem-path . --ruby 3.3 --rails 7.1
238
+ ```
239
+
240
+ ### Compatibility warnings
241
+ ```
242
+ ⚠️ Warning: Ruby 3.3 and Rails 5.2 may be incompatible
243
+ Recommended Rails versions for Ruby 3.3: 7.0, 7.1, 7.2, 8.0, 8.1
244
+ ```
245
+ **This is informational** - the tool will still attempt to run, but the build may fail. Use the recommended Rails versions for your Ruby version.
246
+
247
+ ### Docker build fails installing Rails on older Ruby
248
+ Modern Rails pulls in zeitwerk, which requires Ruby >= 3.2. If you see a zeitwerk version error during `gem install rails`, railstest has auto-detected a Ruby version that is too old. Override with `--ruby 3.2` or add a `.ruby-version` file.
249
+
250
+ ### Tests can't find gems after first run
251
+ If you see `GemNotFound` errors, ensure all required gems are in your Gemfile and that the Docker build completed successfully. The tool caches all dependencies, so if a gem is missing from your Gemfile it won't be available at runtime.
252
+
253
+ ## Development
254
+
255
+ ```bash
256
+ # Build the gem
257
+ gem build railstest.gemspec
258
+
259
+ # Install locally
260
+ gem install railstest-0.3.1.gem
261
+
262
+ # Test against a gem — all combinations, or pin both for a quick smoke test
263
+ cd /path/to/test-gem
264
+ railstest --gem-path .
265
+ railstest --gem-path . --ruby 3.2 --rails 8.1
266
+ ```
267
+
268
+ ### Testing Changes to Railstest
269
+
270
+ ```bash
271
+ # Build and install from current directory
272
+ cd railstest
273
+ gem build railstest.gemspec
274
+ gem uninstall railstest -a && gem install railstest-0.3.1.gem
275
+
276
+ # Test against a gem — run all combinations or narrow down while iterating
277
+ cd ../your-gem
278
+ railstest --gem-path . # full matrix
279
+ railstest --gem-path . --ruby 3.2 --rails 8.1 # fast single run
280
+
281
+ # First build: ~2 minutes. Subsequent runs use cached Docker layers (~1.5s).
282
+ ```
283
+
284
+ ### Caching Behavior
285
+
286
+ - **First build:** Copies gem files, installs RubyGems, updates Bundler, runs `bundle install` (~2 min)
287
+ - **Subsequent builds:** Uses cached Docker layers if Gemfile hasn't changed (< 3s)
288
+ - **Gem file changes:** Invalidate cache for steps after COPY . . (still fast)
289
+
290
+ ## Self-Testing
291
+
292
+ Railstest tests itself using the `gemfiles/` directory:
293
+
294
+ ```bash
295
+ ./run_self_test.sh # All combinations in parallel (all CPU cores)
296
+ ./run_self_test.sh -j4 # 4 parallel workers
297
+ ./run_self_test.sh -j1 # Sequential
298
+ ./run_self_test.sh -i # Interactive mode (sequential, prompt between tests)
299
+ ```
300
+
301
+ The test discovers gemfiles automatically and tests each Ruby/Rails combination from `gemfiles/ruby-versions`, skipping any excluded by the compatibility matrix.
302
+
303
+ ### Performance Note
304
+
305
+ With caching enabled, self-tests run significantly faster:
306
+ - **Without cache:** ~2 minutes per combination (full rebuild)
307
+ - **With cache:** ~1.5 seconds per combination after first build
308
+
309
+ ## Contributing
310
+
311
+ When adding new Ruby or Rails versions:
312
+ 1. Add the Ruby version to `gemfiles/ruby-versions` and/or create a new `gemfiles/rails_X.Y.gemfile`
313
+ 2. Update the compatibility matrix in `lib/railstest/supported_versions.rb`
314
+ 3. Test with `./run_self_test.sh`
315
+ 4. Update the self-test matrix table in this README
316
+
317
+ ## Expected Behavior
318
+
319
+ - Docker image builds successfully with correct Rails version
320
+ - Bundle install completes without errors in target-gem mode (with caching)
321
+ - Tests run with proper framework (RSpec or Rails test)
322
+ - Database containers start and tests can connect
323
+ - Test output streams in real-time
324
+ - Proper exit codes returned (0 for success, non-zero for failure)
325
+ - Cleanup happens reliably (database containers stopped)
326
+ - **Caching works:** Subsequent runs use cached Docker layers (~1.5s vs 2+ min)
327
+
328
+ ## License
329
+
330
+ MIT
data/bin/railstest ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'railstest'
5
+
6
+ Railstest::CLI.start
@@ -0,0 +1,18 @@
1
+ volumes:
2
+ db: {}
3
+
4
+ services:
5
+ mysql:
6
+ image: mysql:8.0.31
7
+ environment:
8
+ MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
9
+ volumes:
10
+ - db:/var/lib/mysql
11
+ ports: [ "127.0.0.1:33066:3306" ]
12
+ postgres:
13
+ image: postgres:15.1
14
+ environment:
15
+ POSTGRES_HOST_AUTH_METHOD: "trust"
16
+ volumes:
17
+ - db:/var/lib/postgres
18
+ ports: [ "127.0.0.1:55432:5432" ]