kettle-jem-appraisals 0.1.4 → 0.1.6
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +66 -1
- data/README.md +40 -16
- data/lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb +115 -29
- data/lib/kettle/jem/appraisals/cli.rb +100 -14
- data/lib/kettle/jem/appraisals/matrix_builder.rb +16 -1
- data/lib/kettle/jem/appraisals/modular_gemfile_generator.rb +62 -14
- data/lib/kettle/jem/appraisals/version.rb +1 -1
- data/lib/kettle/jem/appraisals.rb +1 -0
- data.tar.gz.sig +0 -0
- metadata +37 -17
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55c26a21775e32a64b50f493b789920cdcb15a9f142be11204c06c6c012bb411
|
|
4
|
+
data.tar.gz: 94556e63d682de6d157ffe647a78cda96cd3fcafc362bcf4f1234a23ed8dd8b9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35de41e63c518c3b0501e00b957f553a61eccecd4367d1861a12c4a4afc9ef4f788a5bfb640610d1810e576f1ee59cafb684895a2cecd91b40af3d87268421c7
|
|
7
|
+
data.tar.gz: 958ffe7e6d18a08a5b9241ba58c90047d6610bc7fce5f8cdef64a0287c617c7f882ca8b1829e056990e73ea970d5d067edc05bf7b5b3eccb85a0f86519b5cd5f
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,67 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [0.1.6] - 2026-09-29
|
|
34
|
+
|
|
35
|
+
- TAG: [v0.1.6][0.1.6t]
|
|
36
|
+
- COVERAGE: 95.69% -- 976/1020 lines in 15 files
|
|
37
|
+
- BRANCH COVERAGE: 83.93% -- 282/336 branches in 15 files
|
|
38
|
+
- 92.13% documented
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- kettle-jem-template-20260913-001 - Templating now also surfaces a review
|
|
43
|
+
entry in `dependency_conflicts.resolve` when a direct development
|
|
44
|
+
dependency doesn't support one or more of this project's declared
|
|
45
|
+
`engines:` and has no template-managed modular home (e.g. `sqlite3` on
|
|
46
|
+
`jruby`). Review each entry and pick a resolution per the project's own
|
|
47
|
+
engine support needs.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- [kc] kettle-jem/prepare: updated 14 project files:
|
|
52
|
+
- dependencies (14)
|
|
53
|
+
|
|
54
|
+
- [kc] kettle-jem/template: updated 17 project files:
|
|
55
|
+
- code and tests (2)
|
|
56
|
+
- dependencies (2)
|
|
57
|
+
- documentation (1)
|
|
58
|
+
- other (2)
|
|
59
|
+
- workflows (10)
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- Restore the released kettle-jem dependency floor after local templating raised it to an unreleased version.
|
|
64
|
+
|
|
65
|
+
- Skip the style-only RuboCop toolchain in the Ruby 3.2 appraisal bundle.
|
|
66
|
+
|
|
67
|
+
- Launch the generated appraisal binstub through the active Ruby interpreter so matrix resolution works on Windows.
|
|
68
|
+
|
|
69
|
+
## [0.1.5] - 2026-09-19
|
|
70
|
+
|
|
71
|
+
- TAG: [v0.1.5][0.1.5t]
|
|
72
|
+
- COVERAGE: 95.68% -- 975/1019 lines in 15 files
|
|
73
|
+
- BRANCH COVERAGE: 83.93% -- 282/336 branches in 15 files
|
|
74
|
+
- 92.13% documented
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
|
|
78
|
+
- Security floors from kettle-rb `Kettle::Rb::GemFloors` in generated per-version gemfiles for tracked gems and their tracked sub-dependencies (e.g. `gem "activerecord", "~> 7.1.0", ">= 7.1.6"`)
|
|
79
|
+
- `--resolve` warns, and generated gemfiles carry a `# kettle-rb:` comment, when a series has advisories no release fixes or an exact patch version is below its security floor
|
|
80
|
+
- Runtime dependency on kettle-rb `>= 0.1.14`
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- ActiveRecord support gemfiles take their sqlite3 requirements from kettle-rb `Kettle::Rb::GemDependencies` instead of hardcoded ranges, are written per requirement under `gemfiles/modular/activerecord_support/` (e.g. `v6.0.gemfile` for ActiveRecord 6.0–7.0), and only for the ActiveRecord versions in the matrix
|
|
85
|
+
- `activerecord_support.gemfile` / `activerecord_support_modern.gemfile` generated by 0.1.4 and earlier are removed (hand-maintained ones are kept)
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- `--resolve` now exits non-zero when `bin/appraisal generate` fails, instead of reporting "Resolve complete"
|
|
90
|
+
- `-h`/`--help` prints usage instead of running scaffold mode, and unknown options are rejected before any file is written
|
|
91
|
+
- A selected version whose optimal Ruby bucket falls below the project's Ruby floor (e.g. activerecord 5.2 for a gem requiring Ruby >= 2.5) is assigned to the lowest bucket that can run it instead of being silently dropped; selected versions that still cannot be assigned are reported
|
|
92
|
+
- `semver` mode includes the lowest minor allowed by a gem's `requirements` (e.g. activerecord 7.0 for `>= 7.0`)
|
|
93
|
+
|
|
33
94
|
## [0.1.4] - 2026-09-14
|
|
34
95
|
|
|
35
96
|
- TAG: [v0.1.4][0.1.4t]
|
|
@@ -194,7 +255,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
194
255
|
- kettle-jem-template-20260802-001 - Devcontainer JSON files now merge as JSONC,
|
|
195
256
|
preserving comments and trailing commas during template updates.
|
|
196
257
|
|
|
197
|
-
[Unreleased]: https://github.com/appraisal-rb/kettle-jem-appraisals/compare/v0.1.
|
|
258
|
+
[Unreleased]: https://github.com/appraisal-rb/kettle-jem-appraisals/compare/v0.1.6...HEAD
|
|
259
|
+
[0.1.6]: https://github.com/appraisal-rb/kettle-jem-appraisals/compare/v0.1.5...v0.1.6
|
|
260
|
+
[0.1.6t]: https://github.com/appraisal-rb/kettle-jem-appraisals/releases/tag/v0.1.6
|
|
261
|
+
[0.1.5]: https://github.com/appraisal-rb/kettle-jem-appraisals/compare/v0.1.4...v0.1.5
|
|
262
|
+
[0.1.5t]: https://github.com/appraisal-rb/kettle-jem-appraisals/releases/tag/v0.1.5
|
|
198
263
|
[0.1.4]: https://github.com/appraisal-rb/kettle-jem-appraisals/compare/v0.1.3...v0.1.4
|
|
199
264
|
[0.1.4t]: https://github.com/appraisal-rb/kettle-jem-appraisals/releases/tag/v0.1.4
|
|
200
265
|
[0.1.3]: https://github.com/appraisal-rb/kettle-jem-appraisals/compare/v0.1.2...v0.1.3
|
data/README.md
CHANGED
|
@@ -65,7 +65,7 @@ targets **`appraisal`** (which does not support `eval_gemfile`, and only support
|
|
|
65
65
|
|
|
66
66
|
Compatible with MRI Ruby 4.0.0+, and JRuby.
|
|
67
67
|
CI workflows and Appraisals are generated for MRI Ruby 4.0.0+.
|
|
68
|
-
This test floor is configured by `ruby.test_minimum` in `.
|
|
68
|
+
This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
|
|
69
69
|
may be higher than the gem's runtime compatibility floor when legacy Rubies are
|
|
70
70
|
not practical for the current toolchain.
|
|
71
71
|
|
|
@@ -381,19 +381,24 @@ database driver whose gem differs per engine and per ActiveRecord version:
|
|
|
381
381
|
`sqlite3` on MRI/TruffleRuby, `activerecord-jdbcsqlite3-adapter` (plus
|
|
382
382
|
`bigdecimal`) on JRuby. When `activerecord` is a tier1 gem, `--resolve`:
|
|
383
383
|
|
|
384
|
-
- writes `gemfiles/modular/activerecord_support
|
|
385
|
-
ActiveRecord
|
|
386
|
-
|
|
387
|
-
|
|
384
|
+
- writes one support gemfile under `gemfiles/modular/activerecord_support/` for
|
|
385
|
+
each `sqlite3` requirement the matrix's ActiveRecord versions need. The
|
|
386
|
+
requirements come from [kettle-rb][kettle-rb]'s `Kettle::Rb::GemDependencies`
|
|
387
|
+
(what each ActiveRecord series' sqlite3 adapter declares), and each file is
|
|
388
|
+
named after the oldest ActiveRecord series sharing the requirement (for
|
|
389
|
+
example `v6.0.gemfile` covers 6.0–7.0 with `sqlite3 ~> 1.4`, and `v8.0.gemfile`
|
|
390
|
+
covers 8.0+ with `sqlite3 >= 2.1`). Each file has a JRuby platform block for
|
|
391
|
+
the JDBC adapter, whose release series tracks ActiveRecord so Bundler picks
|
|
388
392
|
the matching adapter;
|
|
389
393
|
- adds the matching support gemfile to each generated entry, based on that
|
|
390
|
-
entry's ActiveRecord version (unless `appraisal_gemfiles` already lists one
|
|
391
|
-
|
|
394
|
+
entry's ActiveRecord version (unless `appraisal_gemfiles` already lists one);
|
|
395
|
+
- removes `activerecord_support.gemfile` / `activerecord_support_modern.gemfile`
|
|
396
|
+
written by kettle-jem-appraisals 0.1.4 and earlier.
|
|
392
397
|
|
|
393
398
|
Existing support gemfiles that do not carry the `# Generated by
|
|
394
399
|
kettle-jem-appraisals` header are treated as hand-maintained and left untouched.
|
|
395
400
|
Set `activerecord_support: false` to opt out entirely (for example, when the
|
|
396
|
-
suite uses PostgreSQL). Point the root `Gemfile` at the
|
|
401
|
+
suite uses PostgreSQL). Point the root `Gemfile` at the newest support gemfile
|
|
397
402
|
via kettle-jem's `test_bundle.gemfiles`, and select the JDBC adapter in your spec
|
|
398
403
|
helper on JRuby:
|
|
399
404
|
|
|
@@ -408,6 +413,21 @@ adapter = (RUBY_PLATFORM == "java" && ActiveRecord.version < Gem::Version.new("7
|
|
|
408
413
|
ActiveRecord::Base.establish_connection(adapter: adapter, database: ":memory:")
|
|
409
414
|
```
|
|
410
415
|
|
|
416
|
+
### Security floors
|
|
417
|
+
|
|
418
|
+
Per-version gemfiles for gems tracked by kettle-rb's `Kettle::Rb::GemFloors`
|
|
419
|
+
(activemodel, activerecord, activesupport, sqlite3) require the minor series'
|
|
420
|
+
security floor, e.g. `gem "activerecord", "~> 7.1.0", ">= 7.1.6"`: the newest
|
|
421
|
+
patch that keeps the series' original minimum Ruby, never below a patched
|
|
422
|
+
advisory. Tracked sub-dependencies get their floor too. Exact patch versions
|
|
423
|
+
(`patch` mode) stay pinned.
|
|
424
|
+
|
|
425
|
+
When a series has advisories that no release fixes (for example activerecord
|
|
426
|
+
5.2–7.0 and CVE-2025-55193), or an exact patch version is below its floor,
|
|
427
|
+
`--resolve` warns and the generated gemfile carries a `# kettle-rb:` comment.
|
|
428
|
+
Support gemfiles likewise note sqlite3 advisories that no allowed sqlite3
|
|
429
|
+
release fixes. Update kettle-rb to pick up new advisories.
|
|
430
|
+
|
|
411
431
|
### Optimal bucket assignment
|
|
412
432
|
|
|
413
433
|
Rather than cross-producting every gem version with every Ruby series,
|
|
@@ -450,14 +470,17 @@ This generates:
|
|
|
450
470
|
|
|
451
471
|
### CLI flags
|
|
452
472
|
|
|
453
|
-
| Flag
|
|
454
|
-
|
|
455
|
-
| `--scaffold`
|
|
456
|
-
| `--resolve`
|
|
457
|
-
| `--force`
|
|
473
|
+
| Flag | Description |
|
|
474
|
+
|-------------------|---------------------------------------------|
|
|
475
|
+
| `--scaffold` | Force scaffold mode (even if config exists) |
|
|
476
|
+
| `--resolve` | Force resolve mode |
|
|
477
|
+
| `--force` | Bypass freshness TTL and re-resolve |
|
|
478
|
+
| `-v`, `--version` | Print the version and exit |
|
|
479
|
+
| `-h`, `--help` | Print usage and exit |
|
|
458
480
|
|
|
459
|
-
Without
|
|
460
|
-
resolve otherwise.
|
|
481
|
+
Without a mode flag, the CLI auto-detects: scaffold if no versions are configured,
|
|
482
|
+
resolve otherwise. Unknown options exit with an error before any file is written.
|
|
483
|
+
`--resolve` exits non-zero when `bin/appraisal generate` fails.
|
|
461
484
|
|
|
462
485
|
### Re-resolving
|
|
463
486
|
|
|
@@ -651,6 +674,7 @@ Thanks for RTFM. ☺️
|
|
|
651
674
|
[✉️ruby-forum]: https://www.rubyforum.org/tag/appraisal-rb
|
|
652
675
|
|
|
653
676
|
[✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
|
|
677
|
+
[kettle-rb]: https://github.com/kettle-dev/kettle-rb
|
|
654
678
|
[⛳️gem-namespace]: https://github.com/appraisal-rb/kettle-jem-appraisals
|
|
655
679
|
[⛳️namespace-img]: https://img.shields.io/badge/namespace-Kettle::Jem::Appraisals-3C2D2D.svg?style=square&logo=ruby&logoColor=white
|
|
656
680
|
[⛳️gem-name]: https://clickgems.clickhouse.com/dashboard/kettle-jem-appraisals
|
|
@@ -756,7 +780,7 @@ Thanks for RTFM. ☺️
|
|
|
756
780
|
[📌gitmoji]: https://gitmoji.dev
|
|
757
781
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
758
782
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
759
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-
|
|
783
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-1.020-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
760
784
|
[🔐security]: https://github.com/appraisal-rb/kettle-jem-appraisals/blob/main/SECURITY.md
|
|
761
785
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
762
786
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "fileutils"
|
|
4
|
+
require "kettle/rb"
|
|
4
5
|
|
|
5
6
|
module Kettle
|
|
6
7
|
module Jem
|
|
@@ -9,8 +10,13 @@ module Kettle
|
|
|
9
10
|
# database driver on every engine: +sqlite3+ on MRI/TruffleRuby and
|
|
10
11
|
# +activerecord-jdbcsqlite3-adapter+ (plus +bigdecimal+) on JRuby.
|
|
11
12
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
13
|
+
# The sqlite3 requirement comes from +Kettle::Rb::GemDependencies+, which
|
|
14
|
+
# records what each ActiveRecord series' sqlite3 adapter declares. One
|
|
15
|
+
# support gemfile is written per run of consecutive ActiveRecord series
|
|
16
|
+
# sharing a requirement, named after the oldest series in the run
|
|
17
|
+
# (+gemfiles/modular/activerecord_support/v6.0.gemfile+ covers 6.0–7.0).
|
|
18
|
+
# ActiveRecord newer than the recorded series uses the newest run.
|
|
19
|
+
#
|
|
14
20
|
# The JDBC adapter's release series tracks ActiveRecord (52.x, 61.x, 72.x…),
|
|
15
21
|
# so an open requirement lets Bundler pick the adapter matching the
|
|
16
22
|
# resolved ActiveRecord.
|
|
@@ -20,33 +26,32 @@ module Kettle
|
|
|
20
26
|
#
|
|
21
27
|
# @example
|
|
22
28
|
# generator = ActiveRecordSupportGemfileGenerator.new(base_dir: "/path/to/gem")
|
|
23
|
-
# generator.generate
|
|
24
|
-
# generator.eval_path_for("7.1.6") #=> "modular/activerecord_support.gemfile"
|
|
29
|
+
# generator.generate(["7.1", "8.0"])
|
|
30
|
+
# generator.eval_path_for("7.1.6") #=> "modular/activerecord_support/v7.1.gemfile"
|
|
25
31
|
class ActiveRecordSupportGemfileGenerator
|
|
26
32
|
# @return [String] header marking a support gemfile as generated (and safe to regenerate)
|
|
27
33
|
GENERATED_HEADER = "# Generated by kettle-jem-appraisals"
|
|
28
34
|
|
|
29
|
-
# @return [String]
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
# @return [String] support gemfile for ActiveRecord at or above {MODERN_ACTIVERECORD}
|
|
33
|
-
MODERN_PATH = "gemfiles/modular/activerecord_support_modern.gemfile"
|
|
35
|
+
# @return [String] directory holding the support gemfiles
|
|
36
|
+
SUPPORT_DIR = "gemfiles/modular/activerecord_support"
|
|
34
37
|
|
|
35
|
-
# @return [
|
|
36
|
-
|
|
38
|
+
# @return [String] support gemfile for ActiveRecord older than every recorded series
|
|
39
|
+
UNKNOWN_PATH = "#{SUPPORT_DIR}/unknown.gemfile"
|
|
37
40
|
|
|
38
|
-
# @return [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
# @return [Array<String>] support gemfiles written by kettle-jem-appraisals 0.1.4 and earlier
|
|
42
|
+
LEGACY_PATHS = [
|
|
43
|
+
"gemfiles/modular/activerecord_support.gemfile",
|
|
44
|
+
"gemfiles/modular/activerecord_support_modern.gemfile"
|
|
45
|
+
].freeze
|
|
43
46
|
|
|
44
47
|
class << self
|
|
45
48
|
# @param path [String] a gemfile path, with or without the leading +gemfiles/+
|
|
46
|
-
# @return [Boolean] whether +path+ names
|
|
49
|
+
# @return [Boolean] whether +path+ names an ActiveRecord support gemfile
|
|
47
50
|
def support_gemfile?(path)
|
|
48
51
|
normalized = path.to_s.strip.sub(%r{\Agemfiles/}, "")
|
|
49
|
-
|
|
52
|
+
return true if normalized.start_with?("#{SUPPORT_DIR.delete_prefix("gemfiles/")}/")
|
|
53
|
+
|
|
54
|
+
LEGACY_PATHS.any? { |legacy| legacy.delete_prefix("gemfiles/") == normalized }
|
|
50
55
|
end
|
|
51
56
|
end
|
|
52
57
|
|
|
@@ -58,40 +63,121 @@ module Kettle
|
|
|
58
63
|
@base_dir = base_dir
|
|
59
64
|
end
|
|
60
65
|
|
|
61
|
-
# Writes
|
|
66
|
+
# Writes the support gemfile needed by each ActiveRecord version, skipping
|
|
67
|
+
# hand-maintained files, and removes support gemfiles generated by
|
|
68
|
+
# kettle-jem-appraisals 0.1.4 and earlier.
|
|
62
69
|
#
|
|
63
|
-
# @
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
# @param activerecord_versions [Array<String>] ActiveRecord versions in the matrix
|
|
71
|
+
# @return [Hash{String => Symbol}] relative path => +:written+, +:kept+, or +:removed+
|
|
72
|
+
def generate(activerecord_versions)
|
|
73
|
+
results = {}
|
|
74
|
+
activerecord_versions.map { |version| group_for(version) }.uniq.each do |group|
|
|
75
|
+
relative_path = path_for(group)
|
|
66
76
|
absolute = File.join(base_dir, relative_path)
|
|
67
|
-
if
|
|
77
|
+
if hand_maintained?(absolute)
|
|
68
78
|
results[relative_path] = :kept
|
|
69
79
|
next
|
|
70
80
|
end
|
|
71
81
|
|
|
72
82
|
FileUtils.mkdir_p(File.dirname(absolute))
|
|
73
|
-
File.write(absolute, build_content(
|
|
83
|
+
File.write(absolute, build_content(group))
|
|
74
84
|
results[relative_path] = :written
|
|
75
85
|
end
|
|
86
|
+
|
|
87
|
+
LEGACY_PATHS.each do |relative_path|
|
|
88
|
+
absolute = File.join(base_dir, relative_path)
|
|
89
|
+
next unless File.exist?(absolute) && !hand_maintained?(absolute)
|
|
90
|
+
|
|
91
|
+
FileUtils.rm_f(absolute)
|
|
92
|
+
results[relative_path] = :removed
|
|
93
|
+
end
|
|
94
|
+
results
|
|
76
95
|
end
|
|
77
96
|
|
|
78
97
|
# @param activerecord_version [String, Gem::Version] the entry's ActiveRecord version
|
|
79
98
|
# @return [String] the matching support gemfile, relative to +gemfiles/+ (for +eval_gemfile+)
|
|
80
99
|
def eval_path_for(activerecord_version)
|
|
81
|
-
|
|
82
|
-
|
|
100
|
+
path_for(group_for(activerecord_version)).delete_prefix("gemfiles/")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @param activerecord_version [String, Gem::Version]
|
|
104
|
+
# @return [Array<String>] the sqlite3 requirements for that ActiveRecord version
|
|
105
|
+
def sqlite3_requirements(activerecord_version)
|
|
106
|
+
group = group_for(activerecord_version)
|
|
107
|
+
group ? group.first.requirements : []
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Advisories that affect every sqlite3 series the requirements allow.
|
|
111
|
+
#
|
|
112
|
+
# @param activerecord_version [String, Gem::Version]
|
|
113
|
+
# @return [Array<String>] advisory ids; empty when a fixed sqlite3 release is allowed
|
|
114
|
+
def unfixed_sqlite3_advisories(activerecord_version)
|
|
115
|
+
requirement = Gem::Requirement.new(*sqlite3_requirements(activerecord_version))
|
|
116
|
+
allowed = Kettle::Rb::GemFloors.entries_for("sqlite3").select { |entry|
|
|
117
|
+
requirement.satisfied_by?(Gem::Version.new(entry.floor))
|
|
118
|
+
}
|
|
119
|
+
return [] if allowed.empty? || allowed.any? { |entry| entry.unpatched_advisories.empty? }
|
|
120
|
+
|
|
121
|
+
allowed.flat_map(&:unpatched_advisories).uniq.sort
|
|
83
122
|
end
|
|
84
123
|
|
|
85
124
|
private
|
|
86
125
|
|
|
87
|
-
|
|
88
|
-
|
|
126
|
+
# Runs of consecutive ActiveRecord series with identical sqlite3 requirements.
|
|
127
|
+
def groups
|
|
128
|
+
@groups ||= Kettle::Rb::GemDependencies.entries_for("activerecord", "sqlite3")
|
|
129
|
+
.sort_by { |entry| Gem::Version.new(entry.series) }
|
|
130
|
+
.chunk_while { |older, newer| older.requirements == newer.requirements }
|
|
131
|
+
.to_a
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def group_for(activerecord_version)
|
|
135
|
+
series = Kettle::Rb::GemFloors.series_for(activerecord_version)
|
|
136
|
+
return unless series
|
|
137
|
+
|
|
138
|
+
version = Gem::Version.new(series)
|
|
139
|
+
groups.reverse.find { |group| Gem::Version.new(group.first.series) <= version }
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def path_for(group)
|
|
143
|
+
group ? "#{SUPPORT_DIR}/v#{group.first.series}.gemfile" : UNKNOWN_PATH
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def hand_maintained?(absolute)
|
|
147
|
+
File.exist?(absolute) && !File.read(absolute).include?(GENERATED_HEADER)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def label(group)
|
|
151
|
+
return "ActiveRecord without recorded sqlite3 requirements" unless group
|
|
152
|
+
|
|
153
|
+
first = group.first.series
|
|
154
|
+
last = group.last.series
|
|
155
|
+
range =
|
|
156
|
+
if group.equal?(groups.last)
|
|
157
|
+
"#{first}+"
|
|
158
|
+
elsif first == last
|
|
159
|
+
first
|
|
160
|
+
else
|
|
161
|
+
"#{first}–#{last}"
|
|
162
|
+
end
|
|
163
|
+
"ActiveRecord #{range}"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def build_content(group)
|
|
167
|
+
requirements = group ? group.first.requirements : []
|
|
168
|
+
sqlite3 = [%("sqlite3"), *requirements.map(&:inspect), "platforms: [:ruby]"].join(", ")
|
|
169
|
+
notes = []
|
|
170
|
+
notes << "# sqlite3 requirement from kettle-rb: #{group.last.source}" if group
|
|
171
|
+
unfixed = group ? unfixed_sqlite3_advisories(group.first.series) : []
|
|
172
|
+
notes << "# kettle-rb: no sqlite3 release allowed here fixes #{unfixed.join(", ")}" unless unfixed.empty?
|
|
173
|
+
|
|
89
174
|
<<~GEMFILE
|
|
90
175
|
# frozen_string_literal: true
|
|
91
176
|
|
|
92
177
|
#{GENERATED_HEADER}
|
|
93
|
-
# Database drivers for #{
|
|
178
|
+
# Database drivers for #{label(group)}: sqlite3 on MRI/TruffleRuby,
|
|
94
179
|
# activerecord-jdbcsqlite3-adapter on JRuby (its release series tracks ActiveRecord).
|
|
180
|
+
#{notes.join("\n")}
|
|
95
181
|
gem #{sqlite3}
|
|
96
182
|
|
|
97
183
|
platforms :jruby do
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "yaml"
|
|
4
4
|
require "fileutils"
|
|
5
|
+
require "rbconfig"
|
|
5
6
|
require "rubygems/specification"
|
|
6
7
|
|
|
7
8
|
module Kettle
|
|
@@ -59,10 +60,49 @@ module Kettle
|
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
|
|
63
|
+
# @return [Array<String>] command-line options accepted by {#run}
|
|
64
|
+
OPTIONS = %w[--scaffold --resolve --force -v --version -h --help].freeze
|
|
65
|
+
|
|
66
|
+
# @return [String] usage text printed by +--help+
|
|
67
|
+
USAGE = <<~USAGE
|
|
68
|
+
Usage: kettle-jem-appraisals [--scaffold | --resolve] [--force]
|
|
69
|
+
|
|
70
|
+
Generates an Appraisal matrix for the gem in the current directory.
|
|
71
|
+
Without a mode flag, scaffolds appraisal_matrix in #{CONFIG_FILE} when it
|
|
72
|
+
has no resolved versions, and resolves it otherwise.
|
|
73
|
+
|
|
74
|
+
Options:
|
|
75
|
+
--scaffold Force scaffold mode (even if config exists)
|
|
76
|
+
--resolve Force resolve mode
|
|
77
|
+
--force Bypass freshness TTL and re-resolve
|
|
78
|
+
-v, --version Print the version and exit
|
|
79
|
+
-h, --help Print this help and exit
|
|
80
|
+
USAGE
|
|
81
|
+
|
|
62
82
|
# Detects the appropriate mode and dispatches to scaffold or resolve.
|
|
63
83
|
#
|
|
84
|
+
# Prints usage for +-h+/+--help+ and the version for +-v+/+--version+
|
|
85
|
+
# without touching any files, and exits when given an unknown option.
|
|
86
|
+
#
|
|
64
87
|
# @return [void]
|
|
65
88
|
def run
|
|
89
|
+
if args.include?("-h") || args.include?("--help")
|
|
90
|
+
puts USAGE
|
|
91
|
+
return
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if args.include?("-v") || args.include?("--version")
|
|
95
|
+
puts Version::VERSION
|
|
96
|
+
return
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
unknown = args - OPTIONS
|
|
100
|
+
unless unknown.empty?
|
|
101
|
+
warn "Unknown option(s): #{unknown.join(" ")}"
|
|
102
|
+
warn USAGE
|
|
103
|
+
exit(1)
|
|
104
|
+
end
|
|
105
|
+
|
|
66
106
|
mode = detect_mode
|
|
67
107
|
case mode
|
|
68
108
|
when :scaffold
|
|
@@ -267,6 +307,7 @@ module Kettle
|
|
|
267
307
|
)
|
|
268
308
|
annotate_extra_gemfiles(appraisal_entries, matrix_extra_gemfiles(matrix))
|
|
269
309
|
annotate_activerecord_support(appraisal_entries, tier1_gems, matrix)
|
|
310
|
+
warn_security_advisories(appraisal_entries)
|
|
270
311
|
annotate_standard_appraisal_collapses(appraisal_entries, bucket_ranges, matrix)
|
|
271
312
|
|
|
272
313
|
puts " 📊 Generated #{appraisal_entries.size} appraisal entries"
|
|
@@ -295,19 +336,27 @@ module Kettle
|
|
|
295
336
|
config[APPRAISAL_MATRIX_KEY] = matrix
|
|
296
337
|
write_config(config)
|
|
297
338
|
|
|
298
|
-
|
|
299
|
-
if File.exist?(File.join(project_dir, "bin", "appraisal"))
|
|
300
|
-
puts " 🔧 Running bin/appraisal generate..."
|
|
301
|
-
system("bin/appraisal", "generate", chdir: project_dir)
|
|
302
|
-
else
|
|
303
|
-
puts " ⚠️ bin/appraisal not found — run `bundle binstubs appraisal2` then `bin/appraisal generate`"
|
|
304
|
-
end
|
|
339
|
+
run_appraisal_generate
|
|
305
340
|
|
|
306
341
|
puts " ✅ Resolve complete"
|
|
307
342
|
end
|
|
308
343
|
|
|
309
344
|
# ── Helpers ──────────────────────────────────────────────────────
|
|
310
345
|
|
|
346
|
+
# Runs +bin/appraisal generate+ when the binstub exists, exiting when it fails.
|
|
347
|
+
def run_appraisal_generate
|
|
348
|
+
unless File.exist?(File.join(project_dir, "bin", "appraisal"))
|
|
349
|
+
puts " ⚠️ bin/appraisal not found — run `bundle binstubs appraisal2` then `bin/appraisal generate`"
|
|
350
|
+
return
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
puts " 🔧 Running bin/appraisal generate..."
|
|
354
|
+
return if system(RbConfig.ruby, "bin/appraisal", "generate", chdir: project_dir)
|
|
355
|
+
|
|
356
|
+
warn " ❌ bin/appraisal generate failed (#{$?.inspect}); Appraisals and gemfiles/ may be incomplete"
|
|
357
|
+
exit(1)
|
|
358
|
+
end
|
|
359
|
+
|
|
311
360
|
# Removes stale kja-* flat gemfiles from gemfiles/ that are no longer
|
|
312
361
|
# in the current matrix. Only touches files matching the PREFIX pattern.
|
|
313
362
|
def cleanup_stale_gemfiles(current_entries)
|
|
@@ -393,6 +442,14 @@ module Kettle
|
|
|
393
442
|
# that version is the best choice).
|
|
394
443
|
#
|
|
395
444
|
# Tier2 versions are all compatible versions for each tier1's bucket.
|
|
445
|
+
# Reports selected versions that could not be assigned to any Ruby bucket.
|
|
446
|
+
def warn_unassigned_versions(gem_name, versions, assignments)
|
|
447
|
+
missing = versions - assignments.map { |assignment| assignment[:version] }
|
|
448
|
+
return if missing.empty?
|
|
449
|
+
|
|
450
|
+
warn " ⚠️ #{gem_name} #{missing.join(", ")} not assigned to any Ruby bucket (unknown required_ruby_version?); left out of the matrix"
|
|
451
|
+
end
|
|
452
|
+
|
|
396
453
|
def build_matrix(tier1_gems, tier2_gems, ruby_series, bucket_ranges, all_seams, all_versions_by_gem, resolver, builder, gemfile_gen, sub_resolver)
|
|
397
454
|
entries = []
|
|
398
455
|
|
|
@@ -415,6 +472,7 @@ module Kettle
|
|
|
415
472
|
puts " ⚠️ No bucket assignments for #{t1_name}, falling back to latest bucket"
|
|
416
473
|
t1_assignments = t1_versions.map { |v| {version: v, bucket: ruby_series.last} }
|
|
417
474
|
end
|
|
475
|
+
warn_unassigned_versions(t1_name, t1_versions, t1_assignments)
|
|
418
476
|
|
|
419
477
|
# Show assignments
|
|
420
478
|
t1_assignments.each do |a|
|
|
@@ -609,8 +667,9 @@ module Kettle
|
|
|
609
667
|
end.uniq
|
|
610
668
|
end
|
|
611
669
|
|
|
612
|
-
# Generates the ActiveRecord database support gemfiles
|
|
613
|
-
# matching each ActiveRecord entry's version to its extra gemfiles.
|
|
670
|
+
# Generates the ActiveRecord database support gemfiles the matrix needs and
|
|
671
|
+
# adds the one matching each ActiveRecord entry's version to its extra gemfiles.
|
|
672
|
+
# Warns when no sqlite3 release an entry's support gemfile allows fixes an advisory.
|
|
614
673
|
# Skipped when disabled via +activerecord_support+, when activerecord is not
|
|
615
674
|
# a tier1 gem, or when +appraisal_gemfiles+ already names a support gemfile.
|
|
616
675
|
def annotate_activerecord_support(appraisal_entries, tier1_gems, matrix)
|
|
@@ -618,16 +677,43 @@ module Kettle
|
|
|
618
677
|
return unless tier1_gems.any? { |gem_config| gem_config["name"] == "activerecord" }
|
|
619
678
|
return if matrix_extra_gemfiles(matrix).any? { |path| ActiveRecordSupportGemfileGenerator.support_gemfile?(path) }
|
|
620
679
|
|
|
680
|
+
activerecord_entries = appraisal_entries.select { |entry| entry[:tier1_name] == "activerecord" && entry[:tier1_version] }
|
|
681
|
+
versions = activerecord_entries.map { |entry| entry[:tier1_version] }
|
|
621
682
|
generator = ActiveRecordSupportGemfileGenerator.new(base_dir: project_dir)
|
|
622
|
-
generator.generate.each do |path, status|
|
|
623
|
-
|
|
683
|
+
generator.generate(versions).each do |path, status|
|
|
684
|
+
label = {written: "Wrote", kept: "Kept hand-maintained", removed: "Removed stale generated"}.fetch(status)
|
|
685
|
+
puts " 🗄️ #{label} #{path}"
|
|
624
686
|
end
|
|
625
|
-
|
|
626
|
-
next unless entry[:tier1_name] == "activerecord" && entry[:tier1_version]
|
|
627
|
-
|
|
687
|
+
activerecord_entries.each do |entry|
|
|
628
688
|
support = generator.eval_path_for(entry[:tier1_version])
|
|
629
689
|
entry[:extra_gemfiles] = [support, *Array(entry[:extra_gemfiles])].uniq
|
|
630
690
|
end
|
|
691
|
+
versions.group_by { |version| generator.eval_path_for(version) }.each do |path, grouped|
|
|
692
|
+
unfixed = generator.unfixed_sqlite3_advisories(grouped.first)
|
|
693
|
+
next if unfixed.empty?
|
|
694
|
+
|
|
695
|
+
warn " ⚠️ kettle-rb: no sqlite3 release allowed for activerecord #{grouped.uniq.join(", ")} (#{path}) fixes #{unfixed.join(", ")}"
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
# Warns about tracked gem versions in the matrix whose minor series has
|
|
700
|
+
# advisories no release fixes, or whose exact patch version is below the
|
|
701
|
+
# series' security floor (from +Kettle::Rb::GemFloors+).
|
|
702
|
+
def warn_security_advisories(appraisal_entries)
|
|
703
|
+
pairs = appraisal_entries.flat_map { |entry|
|
|
704
|
+
[[entry[:tier1_name], entry[:tier1_version]], [entry[:tier2_name], entry[:tier2_version]]]
|
|
705
|
+
}
|
|
706
|
+
messages = pairs.filter_map { |name, version| [name, version] if name && version && Kettle::Rb::GemFloors.tracked?(name) }.flat_map { |name, version|
|
|
707
|
+
notes = []
|
|
708
|
+
unpatched = Kettle::Rb::GemFloors.unpatched_advisories(name, version)
|
|
709
|
+
notes << "no #{name} #{Kettle::Rb::GemFloors.series_for(version)} release fixes #{unpatched.join(", ")}" unless unpatched.empty?
|
|
710
|
+
floor = Kettle::Rb::GemFloors.floor(name, version)
|
|
711
|
+
if floor && version.to_s.split(".").length >= 3 && Gem::Version.new(floor) > Gem::Version.new(version.to_s)
|
|
712
|
+
notes << "#{name} #{version} is pinned below the security floor #{floor}"
|
|
713
|
+
end
|
|
714
|
+
notes
|
|
715
|
+
}
|
|
716
|
+
messages.uniq.each { |message| warn " ⚠️ kettle-rb: #{message}" }
|
|
631
717
|
end
|
|
632
718
|
|
|
633
719
|
def activerecord_support_enabled?(matrix)
|
|
@@ -115,7 +115,11 @@ module Kettle
|
|
|
115
115
|
next_seam_ruby = find_next_seam_ruby(ver, ver_min_ruby, all_versions, version_min_ruby)
|
|
116
116
|
|
|
117
117
|
bucket = if next_seam_ruby
|
|
118
|
-
|
|
118
|
+
# When the next seam is at or below the project's Ruby floor, no
|
|
119
|
+
# bucket sits below it; test this version on the lowest bucket
|
|
120
|
+
# that can run it instead of dropping it.
|
|
121
|
+
find_bucket_below(next_seam_ruby, buckets, bucket_ranges) ||
|
|
122
|
+
find_lowest_runnable_bucket(ver_min_ruby, buckets, bucket_ranges)
|
|
119
123
|
else
|
|
120
124
|
# This is in the latest seam range — catch-all bucket
|
|
121
125
|
buckets.last
|
|
@@ -130,6 +134,14 @@ module Kettle
|
|
|
130
134
|
|
|
131
135
|
private
|
|
132
136
|
|
|
137
|
+
# Finds the lowest bucket whose Ruby ceiling can run a version requiring +min_ruby+.
|
|
138
|
+
def find_lowest_runnable_bucket(min_ruby, buckets, bucket_ranges)
|
|
139
|
+
buckets.find { |bucket|
|
|
140
|
+
range = bucket_ranges[bucket]
|
|
141
|
+
range && range[:ceiling] >= min_ruby
|
|
142
|
+
}
|
|
143
|
+
end
|
|
144
|
+
|
|
133
145
|
# One entry per major version (the latest minor of each).
|
|
134
146
|
def select_major(by_major)
|
|
135
147
|
by_major.map { |entry| entry[:minors].last }
|
|
@@ -190,6 +202,9 @@ module Kettle
|
|
|
190
202
|
end
|
|
191
203
|
end
|
|
192
204
|
|
|
205
|
+
# Explicit requirements declare the oldest supported version, so test it.
|
|
206
|
+
versions << by_major.first[:minors].first if requirements && !requirements.empty?
|
|
207
|
+
|
|
193
208
|
versions.uniq.sort_by { |v| Gem::Version.new(v) }
|
|
194
209
|
end
|
|
195
210
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "kettle/rb"
|
|
4
|
+
|
|
3
5
|
module Kettle
|
|
4
6
|
module Jem
|
|
5
7
|
module Appraisals
|
|
@@ -8,6 +10,11 @@ module Kettle
|
|
|
8
10
|
# Creates per-version gemfiles organized by gem name and Ruby series:
|
|
9
11
|
# +gemfiles/modular/{gem_name}/{ruby_series}/v{version}.gemfile+
|
|
10
12
|
#
|
|
13
|
+
# Gems tracked by +Kettle::Rb::GemFloors+ get their minor series' security
|
|
14
|
+
# floor (e.g. +"~> 7.1.0", ">= 7.1.6"+). Exact patch versions stay pinned.
|
|
15
|
+
# A comment notes advisories that no release in the series fixes, and an
|
|
16
|
+
# exact patch version below the floor.
|
|
17
|
+
#
|
|
11
18
|
# @example
|
|
12
19
|
# gen = ModularGemfileGenerator.new(base_dir: "/path/to/project")
|
|
13
20
|
# gen.generate(gem_name: "activerecord", version: "7.1", ruby_series: "r3")
|
|
@@ -66,15 +73,11 @@ module Kettle
|
|
|
66
73
|
private
|
|
67
74
|
|
|
68
75
|
def build_content(gem_name, version, sub_deps)
|
|
69
|
-
lines =
|
|
70
|
-
|
|
71
|
-
"",
|
|
72
|
-
"# Generated by kettle-jem-appraisals",
|
|
73
|
-
"gem #{gem_name.inspect}, #{version_requirement(version).inspect}"
|
|
74
|
-
]
|
|
76
|
+
lines = header_lines
|
|
77
|
+
lines.concat(gem_lines(gem_name, version, pinned_requirements(gem_name, version)))
|
|
75
78
|
|
|
76
79
|
sub_deps.each do |dep_name, dep_version|
|
|
77
|
-
lines
|
|
80
|
+
lines.concat(gem_lines(dep_name, dep_version, floored_requirements(dep_name, dep_version, ["~> #{dep_version}"])))
|
|
78
81
|
end
|
|
79
82
|
|
|
80
83
|
lines << ""
|
|
@@ -82,19 +85,64 @@ module Kettle
|
|
|
82
85
|
end
|
|
83
86
|
|
|
84
87
|
def build_tier2_content(gem_name, version)
|
|
85
|
-
lines =
|
|
88
|
+
lines = header_lines
|
|
89
|
+
lines.concat(gem_lines(gem_name, version, pinned_requirements(gem_name, version)))
|
|
90
|
+
lines << ""
|
|
91
|
+
"#{lines.join("\n")}\n"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def header_lines
|
|
95
|
+
[
|
|
86
96
|
"# frozen_string_literal: true",
|
|
87
97
|
"",
|
|
88
|
-
"# Generated by kettle-jem-appraisals"
|
|
89
|
-
"gem #{gem_name.inspect}, #{version_requirement(version).inspect}",
|
|
90
|
-
""
|
|
98
|
+
"# Generated by kettle-jem-appraisals"
|
|
91
99
|
]
|
|
92
|
-
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def gem_lines(gem_name, version, requirements)
|
|
103
|
+
advisory_notes(gem_name, version, requirements) + ["gem #{[gem_name, *requirements].map(&:inspect).join(", ")}"]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Minor versions get the series' security floor; exact patch versions stay pinned.
|
|
107
|
+
def pinned_requirements(gem_name, version)
|
|
108
|
+
requirement = version_requirement(version)
|
|
109
|
+
return [requirement] if exact_patch?(version)
|
|
110
|
+
|
|
111
|
+
floored_requirements(gem_name, version, [requirement])
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def floored_requirements(gem_name, version, requirements)
|
|
115
|
+
floor = floor_above(gem_name, version)
|
|
116
|
+
floor ? requirements + [">= #{floor}"] : requirements
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def advisory_notes(gem_name, version, requirements)
|
|
120
|
+
notes = []
|
|
121
|
+
unpatched = Kettle::Rb::GemFloors.unpatched_advisories(gem_name, version)
|
|
122
|
+
unless unpatched.empty?
|
|
123
|
+
series = Kettle::Rb::GemFloors.series_for(version)
|
|
124
|
+
notes << "# kettle-rb: no #{gem_name} #{series} release fixes #{unpatched.join(", ")}"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
floor = floor_above(gem_name, version)
|
|
128
|
+
if floor && !requirements.include?(">= #{floor}")
|
|
129
|
+
notes << "# kettle-rb: #{gem_name} #{version} is below the #{gem_name} security floor #{floor}"
|
|
130
|
+
end
|
|
131
|
+
notes
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# @return [String, nil] the security floor when it is newer than +version+
|
|
135
|
+
def floor_above(gem_name, version)
|
|
136
|
+
floor = Kettle::Rb::GemFloors.floor(gem_name, version)
|
|
137
|
+
floor if floor && Gem::Version.new(floor) > Gem::Version.new(version)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def exact_patch?(version)
|
|
141
|
+
version.to_s.split(".").length >= 3
|
|
93
142
|
end
|
|
94
143
|
|
|
95
144
|
def version_requirement(version)
|
|
96
|
-
|
|
97
|
-
if segments.length >= 3
|
|
145
|
+
if exact_patch?(version)
|
|
98
146
|
"~> #{version}"
|
|
99
147
|
else
|
|
100
148
|
"~> #{version}.0"
|
|
@@ -6,7 +6,7 @@ module Kettle
|
|
|
6
6
|
# Version namespace for this gem.
|
|
7
7
|
module Version
|
|
8
8
|
# Current gem version.
|
|
9
|
-
VERSION = "0.1.
|
|
9
|
+
VERSION = "0.1.6"
|
|
10
10
|
end
|
|
11
11
|
# Current gem version exposed at the traditional constant location.
|
|
12
12
|
VERSION = Version::VERSION # Traditional Constant Location
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kettle-jem-appraisals
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -57,6 +57,26 @@ dependencies:
|
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
59
|
version: 7.1.28
|
|
60
|
+
- !ruby/object:Gem::Dependency
|
|
61
|
+
name: kettle-rb
|
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - "~>"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '0.1'
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 0.1.14
|
|
70
|
+
type: :runtime
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - "~>"
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0.1'
|
|
77
|
+
- - ">="
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: 0.1.14
|
|
60
80
|
- !ruby/object:Gem::Dependency
|
|
61
81
|
name: version_gem
|
|
62
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,7 +106,7 @@ dependencies:
|
|
|
86
106
|
version: '3.1'
|
|
87
107
|
- - ">="
|
|
88
108
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: 3.1.
|
|
109
|
+
version: 3.1.5
|
|
90
110
|
type: :development
|
|
91
111
|
prerelease: false
|
|
92
112
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -96,7 +116,7 @@ dependencies:
|
|
|
96
116
|
version: '3.1'
|
|
97
117
|
- - ">="
|
|
98
118
|
- !ruby/object:Gem::Version
|
|
99
|
-
version: 3.1.
|
|
119
|
+
version: 3.1.5
|
|
100
120
|
- !ruby/object:Gem::Dependency
|
|
101
121
|
name: bundler-audit
|
|
102
122
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -174,7 +194,7 @@ dependencies:
|
|
|
174
194
|
version: '3.2'
|
|
175
195
|
- - ">="
|
|
176
196
|
- !ruby/object:Gem::Version
|
|
177
|
-
version: 3.2.
|
|
197
|
+
version: 3.2.5
|
|
178
198
|
type: :development
|
|
179
199
|
prerelease: false
|
|
180
200
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -184,7 +204,7 @@ dependencies:
|
|
|
184
204
|
version: '3.2'
|
|
185
205
|
- - ">="
|
|
186
206
|
- !ruby/object:Gem::Version
|
|
187
|
-
version: 3.2.
|
|
207
|
+
version: 3.2.5
|
|
188
208
|
- !ruby/object:Gem::Dependency
|
|
189
209
|
name: kettle-test
|
|
190
210
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -194,7 +214,7 @@ dependencies:
|
|
|
194
214
|
version: '2.0'
|
|
195
215
|
- - ">="
|
|
196
216
|
- !ruby/object:Gem::Version
|
|
197
|
-
version: 2.0.
|
|
217
|
+
version: 2.0.23
|
|
198
218
|
type: :development
|
|
199
219
|
prerelease: false
|
|
200
220
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -204,7 +224,7 @@ dependencies:
|
|
|
204
224
|
version: '2.0'
|
|
205
225
|
- - ">="
|
|
206
226
|
- !ruby/object:Gem::Version
|
|
207
|
-
version: 2.0.
|
|
227
|
+
version: 2.0.23
|
|
208
228
|
- !ruby/object:Gem::Dependency
|
|
209
229
|
name: turbo_tests2
|
|
210
230
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -214,7 +234,7 @@ dependencies:
|
|
|
214
234
|
version: '3.2'
|
|
215
235
|
- - ">="
|
|
216
236
|
- !ruby/object:Gem::Version
|
|
217
|
-
version: 3.2.
|
|
237
|
+
version: 3.2.12
|
|
218
238
|
type: :development
|
|
219
239
|
prerelease: false
|
|
220
240
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -224,7 +244,7 @@ dependencies:
|
|
|
224
244
|
version: '3.2'
|
|
225
245
|
- - ">="
|
|
226
246
|
- !ruby/object:Gem::Version
|
|
227
|
-
version: 3.2.
|
|
247
|
+
version: 3.2.12
|
|
228
248
|
- !ruby/object:Gem::Dependency
|
|
229
249
|
name: ruby-progressbar
|
|
230
250
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -248,7 +268,7 @@ dependencies:
|
|
|
248
268
|
version: '1.0'
|
|
249
269
|
- - ">="
|
|
250
270
|
- !ruby/object:Gem::Version
|
|
251
|
-
version: 1.0.
|
|
271
|
+
version: 1.0.9
|
|
252
272
|
type: :development
|
|
253
273
|
prerelease: false
|
|
254
274
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -258,7 +278,7 @@ dependencies:
|
|
|
258
278
|
version: '1.0'
|
|
259
279
|
- - ">="
|
|
260
280
|
- !ruby/object:Gem::Version
|
|
261
|
-
version: 1.0.
|
|
281
|
+
version: 1.0.9
|
|
262
282
|
- !ruby/object:Gem::Dependency
|
|
263
283
|
name: gitmoji-regex
|
|
264
284
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -268,7 +288,7 @@ dependencies:
|
|
|
268
288
|
version: '2.0'
|
|
269
289
|
- - ">="
|
|
270
290
|
- !ruby/object:Gem::Version
|
|
271
|
-
version: 2.0.
|
|
291
|
+
version: 2.0.13
|
|
272
292
|
type: :development
|
|
273
293
|
prerelease: false
|
|
274
294
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -278,7 +298,7 @@ dependencies:
|
|
|
278
298
|
version: '2.0'
|
|
279
299
|
- - ">="
|
|
280
300
|
- !ruby/object:Gem::Version
|
|
281
|
-
version: 2.0.
|
|
301
|
+
version: 2.0.13
|
|
282
302
|
description: "\U0001F372 Kettle::Jem::Appraisals auto-generates CI test matrices from
|
|
283
303
|
RubyGems API data. Scaffolds tier1/tier2 gem lists from gemspec, resolves version
|
|
284
304
|
spreads per mode (major/minor/minor-minmax/semver), generates modular gemfiles and
|
|
@@ -315,10 +335,10 @@ licenses:
|
|
|
315
335
|
- AGPL-3.0-only
|
|
316
336
|
metadata:
|
|
317
337
|
homepage_uri: https://kettle-jem-appraisals.galtzo.com
|
|
318
|
-
source_code_uri: https://github.com/appraisal-rb/kettle-jem-appraisals/tree/v0.1.
|
|
319
|
-
changelog_uri: https://github.com/appraisal-rb/kettle-jem-appraisals/blob/v0.1.
|
|
338
|
+
source_code_uri: https://github.com/appraisal-rb/kettle-jem-appraisals/tree/v0.1.6
|
|
339
|
+
changelog_uri: https://github.com/appraisal-rb/kettle-jem-appraisals/blob/v0.1.6/CHANGELOG.md
|
|
320
340
|
bug_tracker_uri: https://github.com/appraisal-rb/kettle-jem-appraisals/issues
|
|
321
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-jem-appraisals/0.1.
|
|
341
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-jem-appraisals/0.1.6
|
|
322
342
|
funding_uri: https://github.com/sponsors/pboling
|
|
323
343
|
wiki_uri: https://github.com/appraisal-rb/kettle-jem-appraisals/wiki
|
|
324
344
|
news_uri: https://www.railsbling.com/tags/kettle-jem-appraisals
|
|
@@ -349,7 +369,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
349
369
|
- !ruby/object:Gem::Version
|
|
350
370
|
version: '0'
|
|
351
371
|
requirements: []
|
|
352
|
-
rubygems_version: 4.0.
|
|
372
|
+
rubygems_version: 4.0.20
|
|
353
373
|
specification_version: 4
|
|
354
374
|
summary: "\U0001F372 Auto-generate Appraisal matrices for kettle-jem managed gems"
|
|
355
375
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|