kettle-dev 1.2.4 → 2.0.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.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +232 -3
  4. data/CITATION.cff +6 -6
  5. data/CONTRIBUTING.md +64 -46
  6. data/FUNDING.md +1 -1
  7. data/LICENSE.md +12 -0
  8. data/README.md +448 -457
  9. data/certs/pboling.pem +27 -0
  10. data/exe/kettle-changelog +24 -13
  11. data/exe/kettle-check-eof +7 -0
  12. data/exe/kettle-check-eof.sh +118 -0
  13. data/exe/kettle-dev-setup +12 -63
  14. data/exe/kettle-gh-release +82 -0
  15. data/lib/kettle/dev/changelog_cli.rb +373 -62
  16. data/lib/kettle/dev/ci_monitor.rb +2 -2
  17. data/lib/kettle/dev/dvcs_cli.rb +1 -1
  18. data/lib/kettle/dev/gem_spec_reader.rb +100 -10
  19. data/lib/kettle/dev/git_adapter.rb +37 -1
  20. data/lib/kettle/dev/open_collective_config.rb +15 -3
  21. data/lib/kettle/dev/pre_release_cli.rb +4 -4
  22. data/lib/kettle/dev/rakelib/reek.rake +9 -6
  23. data/lib/kettle/dev/rakelib/spec_test.rake +25 -25
  24. data/lib/kettle/dev/rakelib/yard.rake +17 -17
  25. data/lib/kettle/dev/readme_backers.rb +4 -4
  26. data/lib/kettle/dev/release_cli.rb +27 -24
  27. data/lib/kettle/dev/tasks/ci_task.rb +4 -4
  28. data/lib/kettle/dev/version.rb +2 -87
  29. data/lib/kettle/dev.rb +31 -17
  30. data/sig/kettle/dev/source_merger.rbs +40 -56
  31. data/sig/kettle/dev/version.rbs +8 -0
  32. data.tar.gz.sig +0 -0
  33. metadata +63 -165
  34. metadata.gz.sig +0 -0
  35. data/.aiignore.example +0 -19
  36. data/.devcontainer/apt-install/devcontainer-feature.json +0 -9
  37. data/.devcontainer/apt-install/install.sh +0 -11
  38. data/.devcontainer/devcontainer.json +0 -28
  39. data/.env.local.example +0 -31
  40. data/.envrc +0 -47
  41. data/.envrc.example +0 -51
  42. data/.envrc.no-osc.example +0 -51
  43. data/.git-hooks/commit-msg +0 -54
  44. data/.git-hooks/commit-subjects-goalie.txt +0 -8
  45. data/.git-hooks/footer-template.erb.txt +0 -16
  46. data/.git-hooks/prepare-commit-msg +0 -8
  47. data/.github/.codecov.yml.example +0 -14
  48. data/.github/FUNDING.yml +0 -13
  49. data/.github/FUNDING.yml.no-osc.example +0 -13
  50. data/.github/dependabot.yml +0 -13
  51. data/.github/workflows/ancient.yml +0 -83
  52. data/.github/workflows/ancient.yml.example +0 -81
  53. data/.github/workflows/auto-assign.yml +0 -21
  54. data/.github/workflows/codeql-analysis.yml +0 -70
  55. data/.github/workflows/coverage.yml +0 -127
  56. data/.github/workflows/coverage.yml.example +0 -127
  57. data/.github/workflows/current.yml +0 -116
  58. data/.github/workflows/current.yml.example +0 -115
  59. data/.github/workflows/dep-heads.yml +0 -117
  60. data/.github/workflows/dependency-review.yml +0 -20
  61. data/.github/workflows/discord-notifier.yml.example +0 -39
  62. data/.github/workflows/heads.yml +0 -117
  63. data/.github/workflows/heads.yml.example +0 -116
  64. data/.github/workflows/jruby.yml +0 -82
  65. data/.github/workflows/jruby.yml.example +0 -72
  66. data/.github/workflows/legacy.yml +0 -76
  67. data/.github/workflows/license-eye.yml +0 -40
  68. data/.github/workflows/locked_deps.yml +0 -85
  69. data/.github/workflows/opencollective.yml +0 -40
  70. data/.github/workflows/style.yml +0 -67
  71. data/.github/workflows/supported.yml +0 -75
  72. data/.github/workflows/truffle.yml +0 -99
  73. data/.github/workflows/unlocked_deps.yml +0 -84
  74. data/.github/workflows/unsupported.yml +0 -76
  75. data/.gitignore +0 -50
  76. data/.gitlab-ci.yml.example +0 -134
  77. data/.idea/.gitignore +0 -45
  78. data/.junie/guidelines-rbs.md +0 -49
  79. data/.junie/guidelines.md +0 -141
  80. data/.junie/guidelines.md.example +0 -140
  81. data/.licenserc.yaml +0 -7
  82. data/.opencollective.yml +0 -3
  83. data/.opencollective.yml.example +0 -3
  84. data/.qlty/qlty.toml +0 -79
  85. data/.rspec +0 -9
  86. data/.rubocop.yml +0 -13
  87. data/.rubocop_rspec.yml +0 -33
  88. data/.simplecov +0 -16
  89. data/.simplecov.example +0 -11
  90. data/.tool-versions +0 -1
  91. data/.yardignore +0 -13
  92. data/.yardopts +0 -14
  93. data/Appraisal.root.gemfile +0 -10
  94. data/Appraisals +0 -151
  95. data/Appraisals.example +0 -102
  96. data/CHANGELOG.md.example +0 -47
  97. data/CONTRIBUTING.md.example +0 -227
  98. data/FUNDING.md.no-osc.example +0 -63
  99. data/Gemfile +0 -40
  100. data/Gemfile.example +0 -34
  101. data/LICENSE.txt +0 -21
  102. data/README.md.example +0 -570
  103. data/README.md.no-osc.example +0 -536
  104. data/REEK +0 -0
  105. data/Rakefile.example +0 -68
  106. data/bin/setup +0 -8
  107. data/gemfiles/modular/coverage.gemfile +0 -6
  108. data/gemfiles/modular/debug.gemfile +0 -13
  109. data/gemfiles/modular/documentation.gemfile +0 -14
  110. data/gemfiles/modular/erb/r2/v3.0.gemfile +0 -1
  111. data/gemfiles/modular/erb/r2.3/default.gemfile +0 -6
  112. data/gemfiles/modular/erb/r2.6/v2.2.gemfile +0 -3
  113. data/gemfiles/modular/erb/r3/v5.0.gemfile +0 -1
  114. data/gemfiles/modular/erb/r3.1/v4.0.gemfile +0 -2
  115. data/gemfiles/modular/erb/vHEAD.gemfile +0 -2
  116. data/gemfiles/modular/injected.gemfile +0 -60
  117. data/gemfiles/modular/mutex_m/r2/v0.3.gemfile +0 -2
  118. data/gemfiles/modular/mutex_m/r2.4/v0.1.gemfile +0 -3
  119. data/gemfiles/modular/mutex_m/r3/v0.3.gemfile +0 -2
  120. data/gemfiles/modular/mutex_m/vHEAD.gemfile +0 -2
  121. data/gemfiles/modular/optional.gemfile +0 -8
  122. data/gemfiles/modular/optional.gemfile.example +0 -5
  123. data/gemfiles/modular/runtime_heads.gemfile +0 -10
  124. data/gemfiles/modular/runtime_heads.gemfile.example +0 -8
  125. data/gemfiles/modular/stringio/r2/v3.0.gemfile +0 -5
  126. data/gemfiles/modular/stringio/r2.4/v0.0.2.gemfile +0 -4
  127. data/gemfiles/modular/stringio/r3/v3.0.gemfile +0 -5
  128. data/gemfiles/modular/stringio/vHEAD.gemfile +0 -2
  129. data/gemfiles/modular/style.gemfile +0 -25
  130. data/gemfiles/modular/style.gemfile.example +0 -25
  131. data/gemfiles/modular/templating.gemfile +0 -3
  132. data/gemfiles/modular/x_std_libs/r2/libs.gemfile +0 -3
  133. data/gemfiles/modular/x_std_libs/r2.3/libs.gemfile +0 -3
  134. data/gemfiles/modular/x_std_libs/r2.4/libs.gemfile +0 -3
  135. data/gemfiles/modular/x_std_libs/r2.6/libs.gemfile +0 -3
  136. data/gemfiles/modular/x_std_libs/r3/libs.gemfile +0 -3
  137. data/gemfiles/modular/x_std_libs/r3.1/libs.gemfile +0 -3
  138. data/gemfiles/modular/x_std_libs/vHEAD.gemfile +0 -3
  139. data/gemfiles/modular/x_std_libs.gemfile +0 -2
  140. data/kettle-dev.gemspec.example +0 -154
  141. data/lib/kettle/dev/modular_gemfiles.rb +0 -119
  142. data/lib/kettle/dev/prism_appraisals.rb +0 -351
  143. data/lib/kettle/dev/prism_gemfile.rb +0 -177
  144. data/lib/kettle/dev/prism_gemspec.rb +0 -284
  145. data/lib/kettle/dev/prism_utils.rb +0 -201
  146. data/lib/kettle/dev/rakelib/install.rake +0 -10
  147. data/lib/kettle/dev/rakelib/template.rake +0 -10
  148. data/lib/kettle/dev/setup_cli.rb +0 -403
  149. data/lib/kettle/dev/source_merger.rb +0 -655
  150. data/lib/kettle/dev/tasks/install_task.rb +0 -553
  151. data/lib/kettle/dev/tasks/template_task.rb +0 -975
  152. data/lib/kettle/dev/template_helpers.rb +0 -685
data/README.md CHANGED
@@ -1,50 +1,17 @@
1
- | 📍 NOTE |
2
- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
3
- | RubyGems (the [GitHub org][rubygems-org], not the website) [suffered][draper-security] a [hostile takeover][ellen-takeover] in September 2025. |
4
- | Ultimately [4 maintainers][simi-removed] were [hard removed][martin-removed] and a reason has been given for only 1 of those, while 2 others resigned in protest. |
5
- | It is a [complicated story][draper-takeover] which is difficult to [parse quickly][draper-lies]. |
6
- | Simply put - there was active policy for adding or removing maintainers/owners of [rubygems][rubygems-maint-policy] and [bundler][bundler-maint-policy], and those [policies were not followed][policy-fail]. |
7
- | I'm adding notes like this to gems because I [don't condone theft][draper-theft] of repositories or gems from their rightful owners. |
8
- | If a similar theft happened with my repos/gems, I'd hope some would stand up for me. |
9
- | Disenfranchised former-maintainers have started [gem.coop][gem-coop]. |
10
- | Once available I will publish there exclusively; unless RubyCentral makes amends with the community. |
11
- | The ["Technology for Humans: Joel Draper"][reinteractive-podcast] podcast episode by [reinteractive][reinteractive] is the most cogent summary I'm aware of. |
12
- | See [here][gem-naming], [here][gem-coop] and [here][martin-ann] for more info on what comes next. |
13
- | What I'm doing: A (WIP) proposal for [bundler/gem scopes][gem-scopes], and a (WIP) proposal for a federated [gem server][gem-server]. |
14
-
15
- [rubygems-org]: https://github.com/rubygems/
16
- [draper-security]: https://joel.drapper.me/p/ruby-central-security-measures/
17
- [draper-takeover]: https://joel.drapper.me/p/ruby-central-takeover/
18
- [ellen-takeover]: https://pup-e.com/blog/goodbye-rubygems/
19
- [simi-removed]: https://www.reddit.com/r/ruby/s/gOk42POCaV
20
- [martin-removed]: https://bsky.app/profile/martinemde.com/post/3m3occezxxs2q
21
- [draper-lies]: https://joel.drapper.me/p/ruby-central-fact-check/
22
- [draper-theft]: https://joel.drapper.me/p/ruby-central/
23
- [reinteractive]: https://reinteractive.com/ruby-on-rails
24
- [gem-coop]: https://gem.coop
25
- [gem-naming]: https://github.com/gem-coop/gem.coop/issues/12
26
- [martin-ann]: https://martinemde.com/2025/10/05/announcing-gem-coop.html
27
- [gem-scopes]: https://github.com/galtzo-floss/bundle-namespace
28
- [gem-server]: https://github.com/galtzo-floss/gem-server
29
- [reinteractive-podcast]: https://youtu.be/_H4qbtC5qzU?si=BvuBU90R2wAqD2E6
30
- [bundler-maint-policy]: https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/bundler/playbooks/TEAM_CHANGES.md
31
- [rubygems-maint-policy]: https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/rubygems/POLICIES.md?plain=1#L187-L196
32
- [policy-fail]: https://www.reddit.com/r/ruby/comments/1ove9vp/rubycentral_hates_this_one_fact/
33
-
34
- [![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-i]][🖼️galtzo-discord] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![kettle-dev Logo by Aboling0, CC BY-SA 4.0][🖼️kettle-dev-i]][🖼️kettle-dev]
35
-
36
- [🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
37
- [🖼️galtzo-discord]: https://discord.gg/3qme4XHNKN
1
+ [![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-floss-i]][🖼️galtzo-floss] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![kettle-rb Logo by Aboling0, CC BY-SA 4.0][🖼️kettle-rb-i]][🖼️kettle-rb]
2
+
3
+ [🖼️galtzo-floss-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
4
+ [🖼️galtzo-floss]: https://discord.gg/3qme4XHNKN
38
5
  [🖼️ruby-lang-i]: https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg
39
6
  [🖼️ruby-lang]: https://www.ruby-lang.org/
40
- [🖼️kettle-dev-i]: https://logos.galtzo.com/assets/images/kettle-rb/kettle-dev/avatar-192px.svg
41
- [🖼️kettle-dev]: https://github.com/kettle-rb/kettle-dev
7
+ [🖼️kettle-rb-i]: https://logos.galtzo.com/assets/images/kettle-rb/avatar-192px.svg
8
+ [🖼️kettle-rb]: https://github.com/kettle-rb
42
9
 
43
10
  # 🍲 Kettle::Dev
44
11
 
45
- [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
12
+ [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: AGPL-3.0-only][📄license-img]][📄license] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL]
46
13
 
47
- `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord].
14
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-floss], as I may have missed the [discord notification][🖼️galtzo-floss].
48
15
 
49
16
  ---
50
17
 
@@ -52,6 +19,13 @@
52
19
 
53
20
  [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate at ko-fi.com][🖇kofi-img]][🖇kofi]
54
21
 
22
+ <details>
23
+ <summary>👣 How will this project approach the September 2025 hostile takeover of RubyGems? 🚑️</summary>
24
+
25
+ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo).
26
+
27
+ </details>
28
+
55
29
  ## 🌻 Synopsis
56
30
 
57
31
  Run the one-time project bootstrapper:
@@ -81,46 +55,195 @@ bundle exec rake kettle:dev:install
81
55
  Making sure to review the changes, and retain overwritten bits that matter.
82
56
 
83
57
  Later, when ready to release:
58
+
84
59
  ```console
85
60
  bin/kettle-changelog
86
61
  bin/kettle-release
87
62
  ```
88
63
 
64
+ ### The `*-merge` Gem Family
65
+
66
+ The `*-merge` gem family provides intelligent, AST-based merging for various file formats. At the foundation is [tree_haver][tree_haver], which provides a unified cross-Ruby parsing API that works seamlessly across MRI, JRuby, and TruffleRuby.
67
+
68
+ | Gem | Version / CI | Language<br>/ Format | Parser Backend(s) | Description |
69
+ |------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------:|----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
70
+ | [tree_haver][tree_haver] | [![Version][tree_haver-gem-i]][tree_haver-gem] <br/> [![CI][tree_haver-ci-i]][tree_haver-ci] | Multi | Supported Backends: MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus, Parslet | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
71
+ | [ast-merge][ast-merge] | [![Version][ast-merge-gem-i]][ast-merge-gem] <br/> [![CI][ast-merge-ci-i]][ast-merge-ci] | Text | internal | **Infrastructure**: Shared base classes and merge logic for all `*-merge` gems |
72
+ | [bash-merge][bash-merge] | [![Version][bash-merge-gem-i]][bash-merge-gem] <br/> [![CI][bash-merge-ci-i]][bash-merge-ci] | Bash | [tree-sitter-bash][ts-bash] (via tree_haver) | Smart merge for Bash scripts |
73
+ | [commonmarker-merge][commonmarker-merge] | [![Version][commonmarker-merge-gem-i]][commonmarker-merge-gem] <br/> [![CI][commonmarker-merge-ci-i]][commonmarker-merge-ci] | Markdown | [Commonmarker][commonmarker] (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
74
+ | [dotenv-merge][dotenv-merge] | [![Version][dotenv-merge-gem-i]][dotenv-merge-gem] <br/> [![CI][dotenv-merge-ci-i]][dotenv-merge-ci] | Dotenv | internal | Smart merge for `.env` files |
75
+ | [json-merge][json-merge] | [![Version][json-merge-gem-i]][json-merge-gem] <br/> [![CI][json-merge-ci-i]][json-merge-ci] | JSON | [tree-sitter-json][ts-json] (via tree_haver) | Smart merge for JSON files |
76
+ | [jsonc-merge][jsonc-merge] | [![Version][jsonc-merge-gem-i]][jsonc-merge-gem] <br/> [![CI][jsonc-merge-ci-i]][jsonc-merge-ci] | JSONC | [tree-sitter-jsonc][ts-jsonc] (via tree_haver) | ⚠️ Proof of concept; Smart merge for JSON with Comments |
77
+ | [markdown-merge][markdown-merge] | [![Version][markdown-merge-gem-i]][markdown-merge-gem] <br/> [![CI][markdown-merge-ci-i]][markdown-merge-ci] | Markdown | [Commonmarker][commonmarker] / [Markly][markly] (via tree_haver), [Parslet][parslet] | **Foundation**: Shared base for Markdown mergers with inner code block merging |
78
+ | [markly-merge][markly-merge] | [![Version][markly-merge-gem-i]][markly-merge-gem] <br/> [![CI][markly-merge-ci-i]][markly-merge-ci] | Markdown | [Markly][markly] (via tree_haver) | Smart merge for Markdown (CommonMark via cmark-gfm C) |
79
+ | [prism-merge][prism-merge] | [![Version][prism-merge-gem-i]][prism-merge-gem] <br/> [![CI][prism-merge-ci-i]][prism-merge-ci] | Ruby | [Prism][prism] (`prism` std lib gem) | Smart merge for Ruby source files |
80
+ | [psych-merge][psych-merge] | [![Version][psych-merge-gem-i]][psych-merge-gem] <br/> [![CI][psych-merge-ci-i]][psych-merge-ci] | YAML | [Psych][psych] (`psych` std lib gem) | Smart merge for YAML files |
81
+ | [rbs-merge][rbs-merge] | [![Version][rbs-merge-gem-i]][rbs-merge-gem] <br/> [![CI][rbs-merge-ci-i]][rbs-merge-ci] | RBS | [tree-sitter-rbs][ts-rbs] (via tree_haver), [RBS][rbs] (`rbs` std lib gem) | Smart merge for Ruby type signatures |
82
+ | [toml-merge][toml-merge] | [![Version][toml-merge-gem-i]][toml-merge-gem] <br/> [![CI][toml-merge-ci-i]][toml-merge-ci] | TOML | [Parslet + toml][toml], [Citrus + toml-rb][toml-rb], [tree-sitter-toml][ts-toml] (all via tree_haver) | Smart merge for TOML files |
83
+
84
+ #### Backend Platform Compatibility
85
+
86
+ tree_haver supports multiple parsing backends, but not all backends work on all Ruby platforms:
87
+
88
+ | Platform 👉️<br> TreeHaver Backend 👇️ | MRI | JRuby | TruffleRuby | Notes |
89
+ |-------------------------------------------------|:---:|:-----:|:-----------:|----------------------------------------------------------------------------|
90
+ | **MRI** ([ruby_tree_sitter][ruby_tree_sitter]) | ✅ | ❌ | ❌ | C extension, MRI only |
91
+ | **Rust** ([tree_stump][tree_stump]) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
92
+ | **FFI** ([ffi][ffi]) | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
93
+ | **Java** ([jtreesitter][jtreesitter]) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
94
+ | **Prism** ([prism][prism]) | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
95
+ | **Psych** ([psych][psych]) | ✅ | ✅ | ✅ | YAML parsing, stdlib |
96
+ | **Citrus** ([citrus][citrus]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
97
+ | **Parslet** ([parslet][parslet]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
98
+ | **Commonmarker** ([commonmarker][commonmarker]) | ✅ | ❌ | ❓ | Rust extension for Markdown (via [commonmarker-merge][commonmarker-merge]) |
99
+ | **Markly** ([markly][markly]) | ✅ | ❌ | ❓ | C extension for Markdown (via [markly-merge][markly-merge]) |
100
+
101
+ **Legend**: ✅ = Works, ❌ = Does not work, ❓ = Untested
102
+
103
+ **Why some backends don't work on certain platforms**:
104
+
105
+ - **JRuby**: Runs on the JVM; cannot load native C/Rust extensions (`.so` files)
106
+ - **TruffleRuby**: Has C API emulation via Sulong/LLVM, but it doesn't expose all MRI internals that native extensions require (e.g., `RBasic.flags`, `rb_gc_writebarrier`)
107
+ - **FFI on TruffleRuby**: TruffleRuby's FFI implementation doesn't support returning structs by value, which tree-sitter's C API requires
108
+
109
+ **Example implementations** for the gem templating use case:
110
+
111
+ | Gem | Purpose | Description |
112
+ |--------------------------|-----------------|-----------------------------------------------|
113
+ | [kettle-dev][kettle-dev] | Gem Development | Development tooling, CI automation, and release workflows |
114
+ | [kettle-jem][kettle-jem] | Gem Templating | Gem template library with smart merge support |
115
+
116
+ [tree_haver]: https://github.com/kettle-rb/tree_haver
117
+ [ast-merge]: https://github.com/kettle-rb/ast-merge
118
+ [prism-merge]: https://github.com/kettle-rb/prism-merge
119
+ [psych-merge]: https://github.com/kettle-rb/psych-merge
120
+ [json-merge]: https://github.com/kettle-rb/json-merge
121
+ [jsonc-merge]: https://github.com/kettle-rb/jsonc-merge
122
+ [bash-merge]: https://github.com/kettle-rb/bash-merge
123
+ [rbs-merge]: https://github.com/kettle-rb/rbs-merge
124
+ [dotenv-merge]: https://github.com/kettle-rb/dotenv-merge
125
+ [toml-merge]: https://github.com/kettle-rb/toml-merge
126
+ [markdown-merge]: https://github.com/kettle-rb/markdown-merge
127
+ [markly-merge]: https://github.com/kettle-rb/markly-merge
128
+ [commonmarker-merge]: https://github.com/kettle-rb/commonmarker-merge
129
+ [kettle-dev]: https://github.com/kettle-rb/kettle-dev
130
+ [kettle-jem]: https://github.com/kettle-rb/kettle-jem
131
+ [tree_haver-gem]: https://bestgems.org/gems/tree_haver
132
+ [ast-merge-gem]: https://bestgems.org/gems/ast-merge
133
+ [prism-merge-gem]: https://bestgems.org/gems/prism-merge
134
+ [psych-merge-gem]: https://bestgems.org/gems/psych-merge
135
+ [json-merge-gem]: https://bestgems.org/gems/json-merge
136
+ [jsonc-merge-gem]: https://bestgems.org/gems/jsonc-merge
137
+ [bash-merge-gem]: https://bestgems.org/gems/bash-merge
138
+ [rbs-merge-gem]: https://bestgems.org/gems/rbs-merge
139
+ [dotenv-merge-gem]: https://bestgems.org/gems/dotenv-merge
140
+ [toml-merge-gem]: https://bestgems.org/gems/toml-merge
141
+ [markdown-merge-gem]: https://bestgems.org/gems/markdown-merge
142
+ [markly-merge-gem]: https://bestgems.org/gems/markly-merge
143
+ [commonmarker-merge-gem]: https://bestgems.org/gems/commonmarker-merge
144
+ [kettle-dev-gem]: https://bestgems.org/gems/kettle-dev
145
+ [kettle-jem-gem]: https://bestgems.org/gems/kettle-jem
146
+ [tree_haver-gem-i]: https://img.shields.io/gem/v/tree_haver.svg
147
+ [ast-merge-gem-i]: https://img.shields.io/gem/v/ast-merge.svg
148
+ [prism-merge-gem-i]: https://img.shields.io/gem/v/prism-merge.svg
149
+ [psych-merge-gem-i]: https://img.shields.io/gem/v/psych-merge.svg
150
+ [json-merge-gem-i]: https://img.shields.io/gem/v/json-merge.svg
151
+ [jsonc-merge-gem-i]: https://img.shields.io/gem/v/jsonc-merge.svg
152
+ [bash-merge-gem-i]: https://img.shields.io/gem/v/bash-merge.svg
153
+ [rbs-merge-gem-i]: https://img.shields.io/gem/v/rbs-merge.svg
154
+ [dotenv-merge-gem-i]: https://img.shields.io/gem/v/dotenv-merge.svg
155
+ [toml-merge-gem-i]: https://img.shields.io/gem/v/toml-merge.svg
156
+ [markdown-merge-gem-i]: https://img.shields.io/gem/v/markdown-merge.svg
157
+ [markly-merge-gem-i]: https://img.shields.io/gem/v/markly-merge.svg
158
+ [commonmarker-merge-gem-i]: https://img.shields.io/gem/v/commonmarker-merge.svg
159
+ [kettle-dev-gem-i]: https://img.shields.io/gem/v/kettle-dev.svg
160
+ [kettle-jem-gem-i]: https://img.shields.io/gem/v/kettle-jem.svg
161
+ [tree_haver-ci-i]: https://github.com/kettle-rb/tree_haver/actions/workflows/current.yml/badge.svg
162
+ [ast-merge-ci-i]: https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml/badge.svg
163
+ [prism-merge-ci-i]: https://github.com/kettle-rb/prism-merge/actions/workflows/current.yml/badge.svg
164
+ [psych-merge-ci-i]: https://github.com/kettle-rb/psych-merge/actions/workflows/current.yml/badge.svg
165
+ [json-merge-ci-i]: https://github.com/kettle-rb/json-merge/actions/workflows/current.yml/badge.svg
166
+ [jsonc-merge-ci-i]: https://github.com/kettle-rb/jsonc-merge/actions/workflows/current.yml/badge.svg
167
+ [bash-merge-ci-i]: https://github.com/kettle-rb/bash-merge/actions/workflows/current.yml/badge.svg
168
+ [rbs-merge-ci-i]: https://github.com/kettle-rb/rbs-merge/actions/workflows/current.yml/badge.svg
169
+ [dotenv-merge-ci-i]: https://github.com/kettle-rb/dotenv-merge/actions/workflows/current.yml/badge.svg
170
+ [toml-merge-ci-i]: https://github.com/kettle-rb/toml-merge/actions/workflows/current.yml/badge.svg
171
+ [markdown-merge-ci-i]: https://github.com/kettle-rb/markdown-merge/actions/workflows/current.yml/badge.svg
172
+ [markly-merge-ci-i]: https://github.com/kettle-rb/markly-merge/actions/workflows/current.yml/badge.svg
173
+ [commonmarker-merge-ci-i]: https://github.com/kettle-rb/commonmarker-merge/actions/workflows/current.yml/badge.svg
174
+ [kettle-dev-ci-i]: https://github.com/kettle-rb/kettle-dev/actions/workflows/current.yml/badge.svg
175
+ [kettle-jem-ci-i]: https://github.com/kettle-rb/kettle-jem/actions/workflows/current.yml/badge.svg
176
+ [tree_haver-ci]: https://github.com/kettle-rb/tree_haver/actions/workflows/current.yml
177
+ [ast-merge-ci]: https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml
178
+ [prism-merge-ci]: https://github.com/kettle-rb/prism-merge/actions/workflows/current.yml
179
+ [psych-merge-ci]: https://github.com/kettle-rb/psych-merge/actions/workflows/current.yml
180
+ [json-merge-ci]: https://github.com/kettle-rb/json-merge/actions/workflows/current.yml
181
+ [jsonc-merge-ci]: https://github.com/kettle-rb/jsonc-merge/actions/workflows/current.yml
182
+ [bash-merge-ci]: https://github.com/kettle-rb/bash-merge/actions/workflows/current.yml
183
+ [rbs-merge-ci]: https://github.com/kettle-rb/rbs-merge/actions/workflows/current.yml
184
+ [dotenv-merge-ci]: https://github.com/kettle-rb/dotenv-merge/actions/workflows/current.yml
185
+ [toml-merge-ci]: https://github.com/kettle-rb/toml-merge/actions/workflows/current.yml
186
+ [markdown-merge-ci]: https://github.com/kettle-rb/markdown-merge/actions/workflows/current.yml
187
+ [markly-merge-ci]: https://github.com/kettle-rb/markly-merge/actions/workflows/current.yml
188
+ [commonmarker-merge-ci]: https://github.com/kettle-rb/commonmarker-merge/actions/workflows/current.yml
189
+ [kettle-dev-ci]: https://github.com/kettle-rb/kettle-dev/actions/workflows/current.yml
190
+ [kettle-jem-ci]: https://github.com/kettle-rb/kettle-jem/actions/workflows/current.yml
191
+ [prism]: https://github.com/ruby/prism
192
+ [psych]: https://github.com/ruby/psych
193
+ [ffi]: https://github.com/ffi/ffi
194
+ [ts-json]: https://github.com/tree-sitter/tree-sitter-json
195
+ [ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
196
+ [ts-bash]: https://github.com/tree-sitter/tree-sitter-bash
197
+ [ts-rbs]: https://github.com/joker1007/tree-sitter-rbs
198
+ [ts-toml]: https://github.com/tree-sitter-grammars/tree-sitter-toml
199
+ [dotenv]: https://github.com/bkeepers/dotenv
200
+ [rbs]: https://github.com/ruby/rbs
201
+ [toml-rb]: https://github.com/emancu/toml-rb
202
+ [toml]: https://github.com/jm/toml
203
+ [markly]: https://github.com/ioquatix/markly
204
+ [commonmarker]: https://github.com/gjtorikian/commonmarker
205
+ [ruby_tree_sitter]: https://github.com/Faveod/ruby-tree-sitter
206
+ [tree_stump]: https://github.com/joker1007/tree_stump
207
+ [jtreesitter]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
208
+ [citrus]: https://github.com/mjackson/citrus
209
+ [parslet]: https://github.com/kschiess/parslet
210
+
89
211
  ## 💡 Info you can shake a stick at
90
212
 
91
- | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
92
- |-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
93
- | Works with JRuby | ![JRuby 9.1 Compat][💎jruby-9.1i] ![JRuby 9.2 Compat][💎jruby-9.2i] ![JRuby 9.3 Compat][💎jruby-9.3i] <br/> [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎10-j-wf] [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf] |
94
- | Works with Truffle Ruby | ![Truffle Ruby 22.3 Compat][💎truby-22.3i] ![Truffle Ruby 23.0 Compat][💎truby-23.0i] <br/> [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] |
95
- | Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎4-lg-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎6-s-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] |
96
- | Works with MRI Ruby 2 | [![Ruby 2.3 Compat][💎ruby-2.3i]][🚎1-an-wf] [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎1-an-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎1-an-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎7-us-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎7-us-wf] |
97
- | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
98
- | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
99
- | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitLab Wiki][📜gl-wiki-img]][📜gl-wiki] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] |
100
- | Compliance | [![License: MIT][📄license-img]][📄license-ref] [![Compatible with Apache Software Projects: Verified by SkyWalking Eyes][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
101
- | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
102
- | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
103
- | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
213
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
214
+ |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
215
+ | Works with JRuby | [![JRuby 9.2 Compat][💎jruby-9.2i]][🚎jruby-9.2-wf] [![JRuby 9.3 Compat][💎jruby-9.3i]][🚎jruby-9.3-wf] <br/> [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎jruby-9.4-wf] [![JRuby current Compat][💎jruby-c-i]][🚎10-j-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf]|
216
+ | Works with Truffle Ruby | [![Truffle Ruby 22.3 Compat][💎truby-22.3i]][🚎truby-22.3-wf] [![Truffle Ruby 23.0 Compat][💎truby-23.0i]][🚎truby-23.0-wf] [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎truby-23.1-wf] <br/> [![Truffle Ruby 24.2 Compat][💎truby-24.2i]][🚎truby-24.2-wf] [![Truffle Ruby 25.0 Compat][💎truby-25.0i]][🚎truby-25.0-wf] [![Truffle Ruby current Compat][💎truby-c-i]][🚎9-t-wf]|
217
+ | Works with MRI Ruby 4 | [![Ruby 4.0 Compat][💎ruby-4.0i]][🚎11-c-wf] [![Ruby current Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf]|
218
+ | Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎ruby-3.0-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎ruby-3.1-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎ruby-3.2-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎ruby-3.3-wf] [![Ruby 3.4 Compat][💎ruby-3.4i]][🚎ruby-3.4-wf]|
219
+ | Works with MRI Ruby 2 | [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎ruby-2.4-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎ruby-2.5-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎ruby-2.6-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎ruby-2.7-wf]|
220
+ | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
221
+ | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
222
+ | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitLab Wiki][📜gl-wiki-img]][📜gl-wiki] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] |
223
+ | Compliance | [![License: AGPL-3.0-only][📄license-img]][📄license] [![Apache license compatibility: Category X][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
224
+ | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
225
+ | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
226
+ | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
104
227
 
105
228
  ### Compatibility
106
229
 
107
- Compatible with MRI Ruby 2.3+, and concordant releases of JRuby, and TruffleRuby.
230
+ Compatible with MRI Ruby 2.4.0+, and concordant releases of JRuby, and TruffleRuby.
108
231
 
109
- | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
232
+ | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
110
233
  |------------------------------------------------|--------------------------------------------------------|
111
- | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
234
+ | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
112
235
 
113
236
  ### Federated DVCS
114
237
 
115
238
  <details markdown="1">
116
- <summary>Find this repo on federated forges (Coming soon!)</summary>
239
+ <summary>Find this repo on federated forges (Coming soon!)</summary>
117
240
 
118
- | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
241
+ | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
119
242
  |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
120
- | 🧪 [kettle-rb/kettle-dev on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜gl-wiki] | 🐭 Tiny Matrix | ➖ |
121
- | 🧊 [kettle-rb/kettle-dev on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
122
- | 🐙 [kettle-rb/kettle-dev on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | [💚][📜gh-wiki] | 💯 Full Matrix | [💚][gh-discussions] |
123
- | 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] |
243
+ | 🧪 [kettle-rb/kettle-dev on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜gl-wiki] | 🐭 Tiny Matrix | ➖ |
244
+ | 🧊 [kettle-rb/kettle-dev on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
245
+ | 🐙 [kettle-rb/kettle-dev on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | [💚][📜gh-wiki] | 💯 Full Matrix | [💚][gh-discussions] |
246
+ | 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] |
124
247
 
125
248
  </details>
126
249
 
@@ -131,7 +254,7 @@ Compatible with MRI Ruby 2.3+, and concordant releases of JRuby, and TruffleRuby
131
254
  Available as part of the Tidelift Subscription.
132
255
 
133
256
  <details markdown="1">
134
- <summary>Need enterprise-level guarantees?</summary>
257
+ <summary>Need enterprise-level guarantees?</summary>
135
258
 
136
259
  The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
137
260
 
@@ -163,45 +286,11 @@ If bundler is not being used to manage dependencies, install the gem by executin
163
286
  gem install kettle-dev
164
287
  ```
165
288
 
166
- ### 🔒 Secure Installation
167
-
168
- <details markdown="1">
169
- <summary>For Medium or High Security Installations</summary>
170
-
171
- This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by
172
- [stone_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with
173
- by following the instructions below.
174
-
175
- Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate:
176
-
177
- ```console
178
- gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem)
179
- ```
180
-
181
- You only need to do that once. Then proceed to install with:
182
-
183
- ```console
184
- gem install kettle-dev -P HighSecurity
185
- ```
186
-
187
- The `HighSecurity` trust profile will verify signed gems, and not allow the installation of unsigned dependencies.
188
-
189
- If you want to up your security game full-time:
190
-
191
- ```console
192
- bundle config set --global trust-policy MediumSecurity
193
- ```
194
-
195
- `MediumSecurity` instead of `HighSecurity` is necessary if not all the gems you use are signed.
196
-
197
- NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine.
198
-
199
- </details>
200
-
201
289
  ## ⚙️ Configuration
202
290
 
203
291
  Note on executables vs Rake tasks
204
- - Executable scripts provided by this gem (exe/* and installed binstubs) work when the gem is installed as a system gem (gem install kettle-dev). They do not require the gem to be in your bundle to run.
292
+
293
+ - Executable scripts provided by this gem (exe/\* and installed binstubs) work when the gem is installed as a system gem (gem install kettle-dev). They do not require the gem to be in your bundle to run.
205
294
  - The Rake tasks provided by this gem require kettle-dev to be declared as a development dependency in your Gemfile and loaded in your project's Rakefile. Ensure your Gemfile includes:
206
295
  ```ruby
207
296
  group :development do
@@ -255,9 +344,11 @@ kettle-dev-setup --allowed=true --force
255
344
  You'll be able to compare the changes with your diff tool, and certainly revert some of them.
256
345
 
257
346
  For your protection:
347
+
258
348
  - it won't run if git doesn't start out porcelain clean.
349
+ After bootstrapping, to update the template to the latest version from a new release of this gem, run:
259
350
 
260
- After bootstrapping, to update the template to the latest version from a new release of this gem, run:
351
+ <!-- end list -->
261
352
 
262
353
  ```console
263
354
  bundle exec rake kettle:dev:install
@@ -271,172 +362,177 @@ It may have some prompts, which can mostly be avoided by running with options:
271
362
  bundle exec rake kettle:dev:install allowed=true force=true
272
363
  ```
273
364
 
274
- Hopefully, all the files that get overwritten are tracked in git!
365
+ Hopefully, all the files that get overwritten are tracked in git\!
275
366
  I wrote this for myself, and it fits my patterns of development.
276
367
 
277
368
  The install task will write a report at the end with:
278
- 1. A file list summary of the changes made.
279
- 2. Next steps for using the tools.
280
- 3. A warning about .env.local (DO NOT COMMIT IT, as it will likely have secrets added)
281
369
 
282
- That’s it. Once installed, kettle-dev:
370
+ 1. A file list summary of the changes made.
371
+ 2. Next steps for using the tools.
372
+ 3. A warning about .env.local (DO NOT COMMIT IT, as it will likely have secrets added)
373
+ That’s it. Once installed, kettle-dev:
374
+
375
+ <!-- end list -->
376
+
283
377
  - Registers RuboCop-LTS tasks and wires your default Rake task to run the gradual linter.
284
- - Locally: default task prefers `rubocop_gradual:autocorrect`.
285
- - On CI (`CI=true`): default task prefers `rubocop_gradual:check`.
378
+ - Locally: default task prefers `rubocop_gradual:autocorrect`.
379
+ - On CI (`CI=true`): default task prefers `rubocop_gradual:check`.
286
380
  - Integrates optional coverage tasks via kettle-soup-cover (enabled locally when present).
287
381
  - Adds gem-shipped Rake tasks from `lib/kettle/dev/rakelib`, including:
288
- - `ci:act` — interactive selector for running GitHub Actions workflows via `act`.
289
- - `kettle:dev:install` — copies this repo’s .github automation, offers to install .git-hooks templates, and overwrites many files in your project.
290
- - Grapheme syncing: detects the grapheme (e.g., emoji) immediately following the first `#` H1 in README.md and ensures the same grapheme, followed by a single space, prefixes both `spec.summary` and `spec.description` in your gemspec. If the H1 has none, you’ll be prompted to enter one; tests use an input adapter, so runs never hang in CI.
291
- - option: force: When truthy (1, true, y, yes), treat all y/N prompts as Yes. Useful for non-interactive runs or to accept defaults quickly. Example: `bundle exec rake kettle:dev:template force=true`
292
- - option: allowed: When truthy (1, true, y, yes), resume task after you have reviewed `.envrc`/`.env.local` and run `direnv allow`. If either file is created or updated, the task will abort with instructions unless `allowed=true` is present. Example: `bundle exec rake kettle:dev:install allowed=true`
293
- - option: only: A comma-separated list of glob patterns to include in templating. Any destination file whose path+filename does not match one of the patterns is excluded. Patterns are matched relative to your project root. Examples: `only="README.md,.github/**"`, `only="docs/**,lib/**/*.rb"`.
294
- - option: include: A comma-separated list of glob patterns that opt-in additional, non-default files. Currently, `.github/workflows/discord-notifier.yml` is not copied by default and will only be copied when `include` matches it (e.g., `include=".github/workflows/discord-notifier.yml"`).
295
- - `kettle:dev:template` — templates files from this gem into your project (e.g., .github workflows, .devcontainer, .qlty, modular Gemfiles, README/CONTRIBUTING stubs). You can run this independently to refresh templates without the extra install prompts.
296
- - option: force: When truthy (1, true, y, yes), treat all y/N prompts as Yes. Useful for non-interactive runs or to accept defaults quickly. Example: `bundle exec rake kettle:dev:template force=true`
297
- - option: allowed: When truthy (1, true, y, yes), resume task after you have reviewed `.envrc`/`.env.local` and run `direnv allow`. If either file is created or updated, the task will abort with instructions unless `allowed=true` is present. Example: `bundle exec rake kettle:dev:template allowed=true`
298
- - option: only: Same as for install; limits which destination files are written based on glob patterns relative to the project root.
299
- - option: include: Same as for install; opts into optional files (e.g., `.github/workflows/discord-notifier.yml`).
300
-
301
- Recommended one-time setup in your project:
382
+ - `ci:act` — interactive selector for running GitHub Actions workflows via `act`.
383
+ - `kettle:dev:install` — copies this repo’s .github automation, offers to install .git-hooks templates, and overwrites many files in your project.
384
+ - Grapheme syncing: detects the grapheme (e.g., emoji) immediately following the first `#` H1 in README.md and ensures the same grapheme, followed by a single space, prefixes both `spec.summary` and `spec.description` in your gemspec. If the H1 has none, you’ll be prompted to enter one; tests use an input adapter, so runs never hang in CI.
385
+ - option: force: When truthy (1, true, y, yes), treat all y/N prompts as Yes. Useful for non-interactive runs or to accept defaults quickly. Example: `bundle exec rake kettle:dev:install force=true`
386
+ - option: allowed: When truthy (1, true, y, yes), resume task after you have reviewed `.envrc`/`.env.local` and run `direnv allow`. If either file is created or updated, the task will abort with instructions unless `allowed=true` is present. Example: `bundle exec rake kettle:dev:install allowed=true`
387
+ - option: only: A comma-separated list of glob patterns to include in templating. Any destination file whose path+filename does not match one of the patterns is excluded. Patterns are matched relative to your project root. Examples: `only="README.md,.github/**"`, `only="docs/**,lib/**/*.rb"`.
388
+ - option: include: A comma-separated list of glob patterns that opt-in additional, non-default files. Currently, `.github/workflows/discord-notifier.yml` is not copied by default and will only be copied when `include` matches it (e.g., `include=".github/workflows/discord-notifier.yml"`).
389
+ - `kettle:jem:template` (provided by [kettle-jem][kettle-jem]) — templates files from this gem into your project (e.g., .github workflows, .devcontainer, .qlty, modular Gemfiles, README/CONTRIBUTING stubs). You can run this independently to refresh templates without the extra install prompts.
390
+ - option: force: When truthy (1, true, y, yes), treat all y/N prompts as Yes. Useful for non-interactive runs or to accept defaults quickly. Example: `bundle exec rake kettle:dev:install force=true`
391
+ - option: allowed: When truthy (1, true, y, yes), resume task after you have reviewed `.envrc`/`.env.local` and run `direnv allow`. If either file is created or updated, the task will abort with instructions unless `allowed=true` is present. Example: `bundle exec rake kettle:jem:template allowed=true`
392
+ - option: only: Same as for install; limits which destination files are written based on glob patterns relative to the project root.
393
+ - option: include: Same as for install; opts into optional files (e.g., `.github/workflows/discord-notifier.yml`).
394
+ Recommended one-time setup in your project:
302
395
  - Install binstubs so kettle-dev executables are available under `./bin`:
303
- - `bundle binstubs kettle-dev --path bin`
396
+ - `bundle binstubs kettle-dev --path bin`
304
397
  - Use direnv (recommended) so `./bin` is on PATH automatically:
305
- - `brew install direnv`
306
- - In your project’s `.envrc` add:
307
- - `# Run any command in this library's bin/ without the bin/ prefix!`
308
- - `PATH_add bin`
398
+ - `brew install direnv`
399
+ - In your project’s `.envrc` add:
400
+ - `# Run any command in this library's bin/ without the bin/ prefix!`
401
+ - `PATH_add bin`
309
402
  - Configure shared git hooks path (optional, recommended):
310
- - `git config --global core.hooksPath .git-hooks`
403
+ - `git config --global core.hooksPath .git-hooks`
311
404
  - Install project automation and sample hooks/templates:
312
- - `bundle exec rake kettle:dev:install` and follow prompts (copies .github and installs .git-hooks templates locally or globally).
313
-
314
- See the next section for environment variables that tweak behavior.
405
+ - `bundle exec rake kettle:dev:install` and follow prompts (copies .github and installs .git-hooks templates locally or globally).
406
+ See the next section for environment variables that tweak behavior.
315
407
 
316
408
  ### Environment Variables
317
409
 
318
410
  Below are the primary environment variables recognized by kettle-dev (and its integrated tools). Unless otherwise noted, set boolean values to the string "true" to enable.
319
411
 
320
412
  General/runtime
321
- - DEBUG: Enable extra internal logging for this library (default: false)
322
- - REQUIRE_BENCH: Enable `require_bench` to profile requires (default: false)
323
- - CI: When set to true, adjusts default rake tasks toward CI behavior
413
+
414
+ - `DEBUG`: Enable extra internal logging for this library (default: false)
415
+ - `REQUIRE_BENCH`: Enable `require_bench` to profile requires (default: false)
416
+ - `CI`: When set to true, adjusts default rake tasks toward CI behavior
324
417
 
325
418
  Coverage (kettle-soup-cover / SimpleCov)
326
- - K_SOUP_COV_DO: Enable coverage collection (default: true in .envrc)
327
- - K_SOUP_COV_FORMATTERS: Comma-separated list of formatters (html, xml, rcov, lcov, json, tty)
328
- - K_SOUP_COV_MIN_LINE: Minimum line coverage threshold (integer, e.g., 100)
329
- - K_SOUP_COV_MIN_BRANCH: Minimum branch coverage threshold (integer, e.g., 100)
330
- - K_SOUP_COV_MIN_HARD: Fail the run if thresholds are not met (true/false)
331
- - K_SOUP_COV_MULTI_FORMATTERS: Enable multiple formatters at once (true/false)
332
- - K_SOUP_COV_OPEN_BIN: Path to browser opener for HTML (empty disables auto-open)
333
- - MAX_ROWS: Limit console output rows for simplecov-console (e.g., 1)
419
+
420
+ - `K_SOUP_COV_DO`: Enable coverage collection (default: true in .envrc)
421
+ - `K_SOUP_COV_FORMATTERS`: Comma-separated list of formatters (html, xml, rcov, lcov, json, tty)
422
+ - `K_SOUP_COV_MIN_LINE`: Minimum line coverage threshold (integer, e.g., 100)
423
+ - `K_SOUP_COV_MIN_BRANCH`: Minimum branch coverage threshold (integer, e.g., 100)
424
+ - `K_SOUP_COV_MIN_HARD`: Fail the run if thresholds are not met (true/false)
425
+ - `K_SOUP_COV_MULTI_FORMATTERS`: Enable multiple formatters at once (true/false)
426
+ - `K_SOUP_COV_OPEN_BIN`: Path to browser opener for HTML (empty disables auto-open)
427
+ - `MAX_ROWS`: Limit console output rows for simplecov-console (e.g., 1)
428
+
334
429
  Tip: When running a single spec file locally, you may want `K_SOUP_COV_MIN_HARD=false` to avoid failing thresholds for a partial run.
335
430
 
336
431
  GitHub API and CI helpers
337
- - GITHUB_TOKEN or GH_TOKEN: Token used by `ci:act` and release workflow checks to query GitHub Actions status at higher rate limits
338
- - GITLAB_TOKEN or GL_TOKEN: Token used by `ci:act` and CI monitor to query GitLab pipeline status
432
+
433
+ - `GITHUB_TOKEN` or `GH_TOKEN`: Token used by `ci:act` and release workflow checks to query GitHub Actions status at higher rate limits
434
+ - `GITLAB_TOKEN` or `GL_TOKEN`: Token used by `ci:act` and CI monitor to query GitLab pipeline status
339
435
 
340
436
  Releasing and signing
341
- - SKIP_GEM_SIGNING: If set, skip gem signing during build/release
342
- - GEM_CERT_USER: Username for selecting your public cert in `certs/<USER>.pem` (defaults to $USER)
343
- - SOURCE_DATE_EPOCH: Reproducible build timestamp. `kettle-release` will set this automatically for the session.
437
+
438
+ - `SKIP_GEM_SIGNING`: If set, skip gem signing during build/release
439
+ - `GEM_CERT_USER`: Username for selecting your public cert in `certs/<USER>.pem` (defaults to $USER)
440
+ - `SOURCE_DATE_EPOCH`: Reproducible build timestamp. `kettle-release` will set this automatically for the session.
344
441
 
345
442
  Git hooks and commit message helpers (exe/kettle-commit-msg)
346
- - GIT_HOOK_BRANCH_VALIDATE: Branch name validation mode (e.g., `jira`) or `false` to disable
347
- - GIT_HOOK_FOOTER_APPEND: Append a footer to commit messages when goalie allows (true/false)
348
- - GIT_HOOK_FOOTER_SENTINEL: Required when footer append is enabled a unique first-line sentinel to prevent duplicates
349
- - GIT_HOOK_FOOTER_APPEND_DEBUG: Extra debug output in the footer template (true/false)
443
+
444
+ - `GIT_HOOK_BRANCH_VALIDATE`: Branch name validation mode (e.g., `jira`) or `false` to disable
445
+ - `GIT_HOOK_FOOTER_APPEND`: Append a footer to commit messages when goalie allows (true/false)
446
+ - `GIT_HOOK_FOOTER_SENTINEL`: Required when footer append is enabled a unique first-line sentinel to prevent duplicates
447
+ - `GIT_HOOK_FOOTER_APPEND_DEBUG`: Extra debug output in the footer template (true/false)
350
448
 
351
449
  For a quick starting point, this repository’s `.envrc` shows sane defaults, and `.env.local` can override them locally.
352
450
 
353
451
  ## 🔧 Basic Usage
354
452
 
355
453
  Common flows
454
+
356
455
  - Default quality workflow (locally):
357
- - `bundle exec rake` — runs the curated default task set (gradual RuboCop autocorrect, coverage if available, and other local tasks). On CI `CI=true`, the default task is adjusted to be CI-friendly.
456
+ - `bundle exec rake` — runs the curated default task set (gradual RuboCop autocorrect, coverage if available, and other local tasks). On CI `CI=true`, the default task is adjusted to be CI-friendly.
358
457
  - Run specs:
359
- - `bin/rspec` or `bundle exec rspec`
360
- - To run a subset without failing coverage thresholds: `K_SOUP_COV_MIN_HARD=false bin/rspec spec/path/to/file_spec.rb`
361
- - To produce multiple coverage reports: `K_SOUP_COV_FORMATTERS="html,xml,rcov,lcov,json,tty" bin/rspec`
458
+ - `bin/rspec` or `bundle exec rspec`
459
+ - To run a subset without failing coverage thresholds: `K_SOUP_COV_MIN_HARD=false bin/rspec spec/path/to/file_spec.rb`
460
+ - To produce multiple coverage reports: `K_SOUP_COV_FORMATTERS="html,xml,rcov,lcov,json,tty" bin/rspec`
362
461
  - Linting (Gradual):
363
- - `bundle exec rake rubocop_gradual:autocorrect`
364
- - `bundle exec rake rubocop_gradual:check` (CI-friendly)
462
+ - `bundle exec rake rubocop_gradual:autocorrect`
463
+ - `bundle exec rake rubocop_gradual:check` (CI-friendly)
365
464
  - Reek and docs:
366
- - `bundle exec rake reek` or `bundle exec rake reek:update`
367
- - `bundle exec rake yard`
368
-
369
- [Appraisals][💎appraisal2] helpers
465
+ - `bundle exec rake reek` or `bundle exec rake reek:update`
466
+ - `bundle exec rake yard`
467
+ [Appraisals][💎appraisal2] helpers
370
468
  - `bundle exec rake appraisal:isntall` — First time Appraisal setup.
371
469
  - `bundle exec rake appraisal:update` — Update Appraisal gemfiles and run RuboCop Gradual autocorrect.
372
- - `bundle exec rake appraisal:reset` — Delete all Appraisal lockfiles in gemfiles/ (*.gemfile.lock). Useful before regenerating appraisals or when switching Ruby versions.
373
-
374
- GitHub Actions local runner helper
470
+ - `bundle exec rake appraisal:reset` — Delete all Appraisal lockfiles in gemfiles/ (\*.gemfile.lock). Useful before regenerating appraisals or when switching Ruby versions.
471
+ GitHub Actions local runner helper
375
472
  - `bundle exec rake ci:act` — interactive menu shows workflows from `.github/workflows` with live status and short codes (first 3 letters of file name). Type a number or short code.
376
473
  - Non-interactive: `bundle exec rake ci:act[loc]` (short code), or `bundle exec rake ci:act[locked_deps.yml]` (filename).
377
-
378
- Setup tokens for API status (GitHub and GitLab)
474
+ Setup tokens for API status (GitHub and GitLab)
379
475
  - Purpose: ci:act displays the latest status for GitHub Actions runs and (when applicable) the latest GitLab pipeline for the current branch. Unauthenticated requests are rate-limited; private repositories require tokens. Provide tokens to get reliable status.
380
476
  - GitHub token (recommended: fine-grained):
381
- - Where to create: https://github.com/settings/personal-access-tokens
382
- - Fine-grained: “Tokens (fine-grained)” → Generate new token
383
- - Classic (fallback): “Tokens (classic)” → Generate new token
384
- - Minimum permissions:
385
- - Fine-grained: Repository access: Read-only for the target repository (or your org); Permissions → Actions: Read
386
- - Classic: For public repos, no scopes are strictly required, but rate limits are very low; for private repos, include the repo scope
387
- - Add to environment (.env.local via direnv):
388
- - GITHUB_TOKEN=your_token_here (or GH_TOKEN=…)
477
+ - Where to create: https://github.com/settings/personal-access-tokens
478
+ - Fine-grained: “Tokens (fine-grained)” → Generate new token
479
+ - Classic (fallback): “Tokens (classic)” → Generate new token
480
+ - Minimum permissions:
481
+ - Fine-grained: Repository access: Read-only for the target repository (or your org); Permissions → Actions: Read
482
+ - Classic: For public repos, no scopes are strictly required, but rate limits are very low; for private repos, include the repo scope
483
+ - Add to environment (`.env.local` via `direnv`):
484
+ - `GITHUB_TOKEN=your_token_here` (or `GH_TOKEN=…`)
389
485
  - GitLab token:
390
- - Where to create (gitlab.com): https://gitlab.com/-/user_settings/personal_access_tokens
391
- - Minimum scope: read_api (sufficient to read pipelines)
392
- - Add to environment (.env.local via direnv):
393
- - GITLAB_TOKEN=your_token_here (or GL_TOKEN=…)
486
+ - Where to create: [gitlab.com](https://gitlab.com/-/user_settings/personal_access_tokens)
487
+ - Minimum scope: `read_api` (sufficient to read pipelines)
488
+ - Add to environment (.env.local via direnv):
489
+ - `GITLAB_TOKEN=your_token_here` (or `GL_TOKEN=…`)
394
490
  - Load environment:
395
- - Save tokens in .env.local (never commit this file), then run: direnv allow
491
+ - Save tokens in `.env.local` (never commit this file), then run: `direnv allow`
396
492
  - Verify:
397
- - Run: bundle exec rake ci:act
398
- - The header will include Repo/Upstream/HEAD; entries will show “Latest GHA …” and “Latest GL … pipeline” with emoji status. On failure to authenticate or rate-limit, you’ll see a brief error/result code.
399
-
400
- Project automation bootstrap
493
+ - Run: bundle exec rake ci:act
494
+ - The header will include Repo/Upstream/HEAD; entries will show “Latest GHA …” and “Latest GL … pipeline” with emoji status. On failure to authenticate or rate-limit, you’ll see a brief error/result code.
495
+ Project automation bootstrap
401
496
  - `bundle exec rake kettle:dev:install` — copies the library’s `.github` folder into your project and offers to install `.git-hooks` templates locally or globally.
402
- - `bundle exec rake kettle:dev:template` — runs only the templating step used by install; useful to re-apply updates to templates (.github workflows, .devcontainer, .qlty, modular Gemfiles, README, and friends) without the `install` task’s extra prompts.
403
- - Also copies maintainer certificate `certs/pboling.pem` into your project when present (used for signed gem builds).
404
- - README carry-over during templating: when your project’s README.md is replaced by the template, selected sections from your existing README are preserved and merged into the new one. Specifically, the task carries over the following sections (matched case-insensitively):
405
- - "Synopsis"
406
- - "Configuration"
407
- - "Basic Usage"
408
- - Any section whose heading starts with "Note:" at any heading level (for example: "# NOTE: …", "## Note: …", or "### note: …").
409
- - Headings are recognized at any level using Markdown hashes (#, ##, ###, …).
497
+ - `bundle exec rake kettle:jem:template` — runs only the templating step used by install; useful to re-apply updates to templates (.github workflows, .devcontainer, .qlty, modular Gemfiles, README, and friends) without the `install` task’s extra prompts.
498
+ - Also copies maintainer certificate `certs/pboling.pem` into your project when present (used for signed gem builds).
499
+ - README carry-over during templating: when your project’s README.md is replaced by the template, selected sections from your existing README are preserved and merged into the new one. Specifically, the task carries over the following sections (matched case-insensitively):
500
+ - "Synopsis"
501
+ - "Configuration"
502
+ - "Basic Usage"
503
+ - Any section whose heading starts with "Note:" at any heading level (for example: "\# NOTE: …", "\#\# Note: …", or "\#\#\# note: …").
504
+ - Headings are recognized at any level using Markdown hashes (\#, \#\#, \#\#\#, …).
410
505
  - Notes about task options:
411
- - Non-interactive confirmations: append `force=true` to accept all y/N prompts as Yes, e.g., `bundle exec rake kettle:dev:template force=true`.
412
- - direnv review flow: if `.envrc` or `.env.local` is created or updated, the task stops and asks you to run `direnv allow`. After you review and allow, resume with `allowed=true`:
413
- - `bundle exec rake kettle:dev:template allowed=true`
414
- - `bundle exec rake kettle:dev:install allowed=true`
506
+ - Non-interactive confirmations: append `force=true` to accept all y/N prompts as Yes, e.g., `bundle exec rake kettle:jem:template force=true`.
507
+ - direnv review flow: if `.envrc` or `.env.local` is created or updated, the task stops and asks you to run `direnv allow`. After you review and allow, resume with `allowed=true`:
508
+ - `bundle exec rake kettle:jem:template allowed=true`
509
+ - `bundle exec rake kettle:dev:install allowed=true`
415
510
  - After that, set up binstubs and direnv for convenience:
416
- - `bundle binstubs kettle-dev --path bin`
417
- - Add to `.envrc`: `PATH_add bin` (so `bin/` tools run without the prefix)
511
+ - `bundle binstubs kettle-dev --path bin`
512
+ - Add to `.envrc`: `PATH_add bin` (so `bin/` tools run without the prefix)
418
513
 
419
514
  ### kettle-dvcs (normalize multi-forge remotes)
420
515
 
421
516
  - Script: `exe/kettle-dvcs` (install binstubs for convenience: `bundle binstubs kettle-dev --path bin`)
422
517
  - Purpose: Normalize git remotes across GitHub, GitLab, and Codeberg, and create an `all` remote that pushes to all and fetches only from your chosen origin.
423
518
  - Assumptions: org and repo names are identical across forges.
519
+ Usage:
424
520
 
425
- Usage:
521
+ <!-- end list -->
426
522
 
427
523
  ```console
428
524
  kettle-dvcs [options] [ORG] [REPO]
429
525
  ```
430
526
 
431
527
  Options:
528
+
432
529
  - `--origin [github|gitlab|codeberg]` Which forge to use as `origin` (default: github)
433
530
  - `--protocol [ssh|https]` URL style (default: ssh)
434
531
  - `--github-name NAME` Remote name for GitHub when not origin (default: gh)
435
532
  - `--gitlab-name NAME` Remote name for GitLab (default: gl)
436
533
  - `--codeberg-name NAME` Remote name for Codeberg (default: cb)
437
534
  - `--force` Non-interactive; accept defaults, and do not prompt for ORG/REPO
438
-
439
- Examples:
535
+ Examples:
440
536
  - Default, interactive (infers ORG/REPO from an existing remote when possible):
441
537
  ```console
442
538
  kettle-dvcs
@@ -451,171 +547,120 @@ Examples:
451
547
  ```
452
548
 
453
549
  What it does:
550
+
454
551
  - Ensures remotes exist and have consistent URLs for each forge.
455
- - Renames existing remotes when their URL already matches the desired target but their name does not (e.g., `gitlab` -> `gl`).
552
+ - Renames existing remotes when their URL already matches the desired target but their name does not (e.g., `gitlab` -\> `gl`).
456
553
  - Creates/refreshes an `all` remote that:
457
554
  - fetches only from your chosen `origin` forge.
458
555
  - has pushurls configured for all three forges so `git push all <branch>` updates all mirrors.
459
556
  - Prints `git remote -v` at the end.
460
557
  - Attempts to `git fetch` each forge remote to check availability:
461
- - If all succeed, the README’s federated DVCS summary line has “(Coming soon!)” removed.
558
+ - If all succeed, the README’s federated DVCS summary line has “(Coming soon\!)” removed.
462
559
  - If any fail, the script prints import links to help you create a mirror on that forge.
463
560
 
464
- ### Template .example files are preferred
465
-
466
- - The templating step dynamically prefers any `*.example` file present in this gem’s templates. When a `*.example` exists alongside the non-example template, the `.example` content is used, and the destination file is written without the `.example` suffix.
467
- - This applies across all templated files, including:
468
- - Root files like `.gitlab-ci.yml` (copied from `.gitlab-ci.yml.example` when present).
469
- - Nested files like `.github/workflows/coverage.yml` (copied from `.github/workflows/coverage.yml.example` when present).
470
- - This behavior is automatic for any future `*.example` files added to the templates.
471
- - Exception: `.env.local` is handled specially for safety. Regardless of whether the template provides `.env.local` or `.env.local.example`, the installer copies it to `.env.local.example` in your project, and will never create or overwrite `.env.local`.
472
-
473
561
  ### Releasing (maintainers)
474
562
 
475
563
  - Script: `exe/kettle-release` (run as `kettle-release`)
476
564
  - Purpose: guided release helper that:
477
- - Runs sanity checks (`bin/setup`, `bin/rake`), confirms version/changelog, optionally updates Appraisals, commits “🔖 Prepare release vX.Y.Z”.
478
- - Optionally runs your CI locally with `act` before any push:
479
- - Enable with env: `K_RELEASE_LOCAL_CI="true"` (run automatically) or `K_RELEASE_LOCAL_CI="ask"` (prompt [Y/n]).
480
- - Select workflow with `K_RELEASE_LOCAL_CI_WORKFLOW` (with or without .yml/.yaml). Defaults to `locked_deps.yml` if present; otherwise the first workflow discovered.
481
- - On failure, the release prep commit is soft-rolled-back (`git reset --soft HEAD^`) and the process aborts.
482
- - Ensures trunk sync and rebases feature as needed, pushes, monitors GitHub Actions with a progress bar, and merges feature to trunk on success.
483
- - Exports `SOURCE_DATE_EPOCH`, builds (optionally signed), creates gem checksums, and runs `bundle exec rake release` (prompts for signing key + RubyGems MFA OTP as needed).
565
+ - Runs sanity checks (`bin/setup`, `bin/rake`), confirms version/changelog, optionally updates Appraisals, regenerates docs via `bin/rake yard`, commits “🔖 Prepare release vX.Y.Z”.
566
+ - Optionally runs your CI locally with `act` before any push:
567
+ - Enable with env: `K_RELEASE_LOCAL_CI="true"` (run automatically) or `K_RELEASE_LOCAL_CI="ask"` (prompt \[Y/n\]).
568
+ - Select workflow with `K_RELEASE_LOCAL_CI_WORKFLOW` (with or without .yml/.yaml). Defaults to `locked_deps.yml` if present; otherwise the first workflow discovered.
569
+ - On failure, the release prep commit is soft-rolled-back (`git reset --soft HEAD^`) and the process aborts.
570
+ - Ensures trunk sync and rebases feature as needed, pushes, monitors GitHub Actions with a progress bar, and merges feature to trunk on success.
571
+ - Exports `SOURCE_DATE_EPOCH`, builds (optionally signed), creates gem checksums, and runs `bundle exec rake release` (prompts for signing key + RubyGems MFA OTP as needed).
484
572
  - Options:
485
- - start_step map (skip directly to a phase):
486
- 1. Verify Bundler >= 2.7 (always runs; start at 1 to do everything)
487
- 2. Detect version; RubyGems sanity check; confirm CHANGELOG/version; sync copyright years; update badges/headers
488
- 3. Run bin/setup
489
- 4. Run bin/rake (default task)
490
- 5. Run bin/rake appraisal:update if Appraisals present
491
- 6. Ensure git user configured; commit release prep
492
- 7. Optional local CI with `act` (controlled by K_RELEASE_LOCAL_CI)
493
- 8. Ensure trunk in sync across remotes; rebase feature as needed
494
- 9. Push current branch to remotes (or 'all' remote)
495
- 10. Monitor CI after push; abort on failures
496
- 11. Merge feature into trunk and push
497
- 12. Checkout trunk and pull latest
498
- 13. Gem signing checks/guidance (skip with SKIP_GEM_SIGNING=true)
499
- 14. Build gem (bundle exec rake build)
500
- 15. Release gem (bundle exec rake release)
501
- 16. Generate and validate checksums (bin/gem_checksums)
502
- 17. Push checksum commit
503
- 18. Create GitHub Release (requires GITHUB_TOKEN)
504
- 19. Push tags to remotes (final)
573
+ - `start_step` map (skip directly to a phase):
574
+ 1. Verify Bundler \>= 2.7 (always runs; start at 1 to do everything)
575
+ 2. Detect version; RubyGems sanity check; confirm CHANGELOG/version; sync copyright years; update badges/headers
576
+ 3. Run bin/setup
577
+ 4. Run bin/rake (default task)
578
+ 5. Run bin/rake appraisal:update if Appraisals present, then bin/rake yard
579
+ 6. Ensure git user configured; commit release prep
580
+ 7. Optional local CI with `act` (controlled by `K_RELEASE_LOCAL_CI`)
581
+ 8. Ensure trunk in sync across remotes; rebase feature as needed
582
+ 9. Push current branch to remotes (or 'all' remote)
583
+ 10. Monitor CI after push; abort on failures
584
+ 11. Merge feature into trunk and push
585
+ 12. Checkout trunk and pull latest
586
+ 13. Gem signing checks/guidance (skip with `SKIP_GEM_SIGNING=true`)
587
+ 14. Build gem (bundle exec rake build)
588
+ 15. Release gem (bundle exec rake release)
589
+ 16. Generate and validate checksums (`bin/gem_checksums`)
590
+ 17. Push checksum commit
591
+ 18. Create GitHub Release (requires `GITHUB_TOKEN`)
592
+ 19. Push tags to remotes (final)
505
593
  - Examples:
506
- - After intermittent CI failure, restart from monitoring: `bundle exec kettle-release start_step=10`
594
+ - After intermittent CI failure, restart from monitoring: `bundle exec kettle-release start_step=10`
507
595
  - Tips:
508
- - The commit message helper `exe/kettle-commit-msg` prefers project-local `.git-hooks` (then falls back to `~/.git-hooks`).
509
- - The goalie file `commit-subjects-goalie.txt` controls when a footer is appended; customize `footer-template.erb.txt` as you like.
596
+ - The commit message helper `exe/kettle-commit-msg` prefers project-local `.git-hooks` (then falls back to `~/.git-hooks`).
597
+ - The goalie file `commit-subjects-goalie.txt` controls when a footer is appended; customize `footer-template.erb.txt` as you like.
510
598
 
511
599
  ### Changelog generator
512
600
 
513
601
  - Script: `exe/kettle-changelog` (run as `kettle-changelog`)
514
602
  - Purpose: Generates a new CHANGELOG.md section for the current version read from `lib/**/version.rb`, moves notes from the Unreleased section, and updates comparison links.
515
603
  - Prerequisites:
516
- - `coverage/coverage.json` present (generate with: `K_SOUP_COV_FORMATTERS="json" bin/rspec`).
517
- - `bin/yard` available (Bundler-installed), to compute documentation coverage.
604
+ - `coverage/coverage.json` present (generate with: `K_SOUP_COV_FORMATTERS="json" bin/rspec`).
605
+ - `bin/rake yard` available, to compute documentation coverage.
518
606
  - Usage:
519
- - `kettle-changelog`
607
+ - `kettle-changelog`
520
608
  - Behavior:
521
- - Reads version from the unique `lib/**/version.rb` in the project.
522
- - Moves entries from the `[Unreleased]` section into a new `[#.#.#] - YYYY-MM-DD` section.
523
- - Prepends 4 lines with TAG, line coverage, branch coverage, and percent documented.
524
- - Converts any GitLab-style compare links at the bottom to GitHub style, adds new tag/compare links for the new release and a temporary tag reference `[X.Y.Zt]`.
609
+ - Reads version from the unique `lib/**/version.rb` in the project.
610
+ - Moves entries from the `[Unreleased]` section into a new `[#.#.#] - YYYY-MM-DD` section.
611
+ - Prepends 4 lines with TAG, line coverage, branch coverage, and percent documented.
612
+ - Converts any GitLab-style compare links at the bottom to GitHub style, adds new tag/compare links for the new release and a temporary tag reference `[X.Y.Zt]`.
525
613
 
526
614
  ### Pre-release checks
527
615
 
528
616
  - Script: `exe/kettle-pre-release` (run as `kettle-pre-release`)
529
617
  - Purpose: Run a suite of pre-release validations to catch avoidable mistakes (resumable by check number).
530
618
  - Usage:
531
- - `kettle-pre-release [--check-num N]`
532
- - Short option: `kettle-pre-release -cN`
619
+ - `kettle-pre-release [--check-num N]`
620
+ - Short option: `kettle-pre-release -cN`
533
621
  - Options:
534
- - `--check-num N` Start from check number N (default: 1)
622
+ - `--check-num N` Start from check number N (default: 1)
535
623
  - Checks:
536
- - 1) Validate that all image URLs referenced by Markdown files resolve (HTTP HEAD)
624
+ - 1) Validate that all image URLs referenced by Markdown files resolve (HTTP HEAD)
537
625
 
538
626
  ### Commit message helper (git hook)
539
627
 
540
628
  - Script: `exe/kettle-commit-msg` (run by git as `.git/hooks/commit-msg`)
541
629
  - Purpose: Append a standardized footer and optionally enforce branch naming rules when configured.
542
630
  - Usage:
543
- - Git invokes this with the path to the commit message file: `kettle-commit-msg .git/COMMIT_EDITMSG`
544
- - Install via `bundle exec rake kettle:dev:install` to copy hook templates into `.git-hooks` and wire them up.
631
+ - Git invokes this with the path to the commit message file: `kettle-commit-msg .git/COMMIT_EDITMSG`
632
+ - Install via `bundle exec rake kettle:dev:install` to copy hook templates into `.git-hooks` and wire them up.
545
633
  - Behavior:
546
- - When `GIT_HOOK_BRANCH_VALIDATE=jira`, validates the current branch matches the pattern: `^(hotfix|bug|feature|candy)/[0-9]{8,}-…`.
547
- - If it matches and the commit message lacks the numeric ID, appends `[<type>][<id>]`.
548
- - Always invokes `Kettle::Dev::GitCommitFooter.render` to potentially append a footer if allowed by the goalie.
549
- - Prefers project-local `.git-hooks` templates; falls back to `~/.git-hooks`.
634
+ - When `GIT_HOOK_BRANCH_VALIDATE=jira`, validates the current branch matches the pattern: `^(hotfix|bug|feature|candy)/[0-9]{8,}-…`.
635
+ - If it matches and the commit message lacks the numeric ID, appends `[<type>][<id>]`.
636
+ - Always invokes `Kettle::Dev::GitCommitFooter.render` to potentially append a footer if allowed by the goalie.
637
+ - Prefers project-local `.git-hooks` templates; falls back to `~/.git-hooks`.
550
638
  - Environment:
551
- - `GIT_HOOK_BRANCH_VALIDATE` Branch rule (e.g., `jira`) or `false` to disable.
552
- - `GIT_HOOK_FOOTER_APPEND` Enable footer auto-append when goalie allows (true/false).
553
- - `GIT_HOOK_FOOTER_SENTINEL` Required marker to avoid duplicate appends when enabled.
554
- - `GIT_HOOK_FOOTER_APPEND_DEBUG` Extra debug output in the footer template (true/false).
639
+ - `GIT_HOOK_BRANCH_VALIDATE` Branch rule (e.g., `jira`) or `false` to disable.
640
+ - `GIT_HOOK_FOOTER_APPEND` Enable footer auto-append when goalie allows (true/false).
641
+ - `GIT_HOOK_FOOTER_SENTINEL` Required marker to avoid duplicate appends when enabled.
642
+ - `GIT_HOOK_FOOTER_APPEND_DEBUG` Extra debug output in the footer template (true/false).
555
643
 
556
644
  ### Project bootstrap installer
557
645
 
558
646
  - Script: `exe/kettle-dev-setup` (run as `kettle-dev-setup`)
559
647
  - Purpose: Bootstrap a host gem repository to use kettle-dev’s tooling without manual steps.
560
648
  - Usage:
561
- - `kettle-dev-setup [options] [passthrough args]`
649
+ - `kettle-dev-setup [options] [passthrough args]`
562
650
  - Options (mapped through to `rake kettle:dev:install`):
563
- - `--allowed=VAL` Pass `allowed=VAL` to acknowledge prior direnv allow, etc.
564
- - `--force` Pass `force=true` to accept prompts non-interactively.
565
- - `--hook_templates=VAL` Pass `hook_templates=VAL` to control git hook templating.
566
- - `--only=VAL` Pass `only=VAL` to restrict install scope.
567
- - `--include=VAL` Pass `include=VAL` to include optional files by glob (see notes below).
568
- - `-h`, `--help` Show help.
651
+ - `--allowed=VAL` Pass `allowed=VAL` to acknowledge prior direnv allow, etc.
652
+ - `--force` Pass `force=true` to accept prompts non-interactively.
653
+ - `--hook_templates=VAL` Pass `hook_templates=VAL` to control git hook templating.
654
+ - `--only=VAL` Pass `only=VAL` to restrict install scope.
655
+ - `--include=VAL` Pass `include=VAL` to include optional files by glob (see notes below).
656
+ - `-h`, `--help` Show help.
569
657
  - Behavior:
570
- - Verifies a clean git working tree, presence of a Gemfile and a gemspec.
571
- - Syncs development dependencies from this gem’s example gemspec into the target gemspec (replacing or inserting `add_development_dependency` lines as needed).
572
- - Ensures `bin/setup` exists (copies from gem if missing) and replaces/creates the project’s `Rakefile` from `Rakefile.example`.
573
- - Runs `bin/setup`, then `bundle exec bundle binstubs --all`.
574
- - Stages and commits any bootstrap changes with message: `🎨 Template bootstrap by kettle-dev-setup v<version>`.
575
- - Executes `bin/rake kettle:dev:install` with the parsed passthrough args.
576
-
577
- ### Template Manifest and AST Strategies
578
-
579
- `kettle:dev:template` looks at `template_manifest.yml` to determine how each file should be updated. Each entry has a `path` (exact file or glob) and a `strategy`:
580
-
581
- | Strategy | Behavior |
582
- | --- | --- |
583
- | `skip` | Legacy behavior: template content is copied with token replacements and any bespoke merge logic already in place. |
584
- | `replace` | Template AST replaces the destination outside of `kettle-dev:freeze` sections. |
585
- | `append` | Only missing AST nodes (e.g., `gem` or `task` declarations) are appended; existing nodes remain untouched. |
586
- | `merge` | Destination nodes are updated in-place using the template AST (used for `Gemfile`, `*.gemspec`, and `Rakefile`). |
587
-
588
- All Ruby files receive this reminder (inserted after shebang/frozen-string-literal lines):
589
-
590
- ```
591
- # To force retention during kettle-dev templating:
592
- # kettle-dev:freeze
593
- # # ... your code
594
- # kettle-dev:unfreeze
595
- ```
596
-
597
- Wrap any code you never want rewritten between `kettle-dev:freeze` / `kettle-dev:unfreeze` comments. When an AST merge fails, the task emits an error asking you to file an issue at https://github.com/kettle-rb/kettle-dev/issues and then aborts—there is no regex fallback.
598
-
599
- ### Template Example
600
-
601
- Here is an example `template_manifest.yml`:
602
-
603
- ```yaml
604
- # For each file or glob, specify a strategy for how it should be managed.
605
- # See https://github.com/kettle-rb/kettle-dev/blob/main/docs/README.md#template-manifest-and-ast-strategies
606
- # for details on each strategy.
607
- files:
608
- - path: "Gemfile"
609
- strategy: "merge"
610
- - path: "*.gemspec"
611
- strategy: "merge"
612
- - path: "Rakefile"
613
- strategy: "merge"
614
- - path: "README.md"
615
- strategy: "replace"
616
- - path: ".env.local"
617
- strategy: "skip"
618
- ```
658
+ - Verifies a clean git working tree, presence of a Gemfile and a gemspec.
659
+ - Syncs development dependencies from this gem’s example gemspec into the target gemspec (replacing or inserting `add_development_dependency` lines as needed).
660
+ - Ensures `bin/setup` exists (copies from gem if missing) and replaces/creates the project’s `Rakefile` from `Rakefile.example`.
661
+ - Runs `bin/setup`, then `bundle exec bundle binstubs --all`.
662
+ - Stages and commits any bootstrap changes with message: `🎨 Template bootstrap by kettle-dev-setup v<version>`.
663
+ - Executes `bin/rake kettle:dev:install` with the parsed passthrough args.
619
664
 
620
665
  ### Open Collective README updater
621
666
 
@@ -630,15 +675,15 @@ files:
630
675
  - Backers (Individuals): `<!-- <TAG>:START --> … <!-- <TAG>:END -->` or `<!-- <TAG>-INDIVIDUALS:START --> … <!-- <TAG>-INDIVIDUALS:END -->`
631
676
  - Sponsors (Organizations): `<!-- <TAG>-ORGANIZATIONS:START --> … <!-- <TAG>-ORGANIZATIONS:END -->`
632
677
  - Handle resolution:
633
- 1. `OPENCOLLECTIVE_HANDLE` environment variable, if set
634
- 2. `opencollective.yml` in the project root (e.g., `collective: "kettle-rb"` in this repo)
678
+ 1. `OPENCOLLECTIVE_HANDLE` environment variable, if set
679
+ 2. `opencollective.yml` in the project root (e.g., `collective: "kettle-rb"` in this repo)
635
680
  - Usage:
636
681
  - `exe/kettle-readme-backers`
637
682
  - `OPENCOLLECTIVE_HANDLE=my-collective exe/kettle-readme-backers`
638
683
  - Behavior:
639
684
  - Writes to README.md only if content between the tags would change.
640
685
  - If neither the backers nor sponsors tags are present, prints a helpful warning and exits with status 2.
641
- - When there are no entries, inserts a friendly placeholder: "No backers yet. Be the first!" or "No sponsors yet. Be the first!".
686
+ - When there are no entries, inserts a friendly placeholder: "No backers yet. Be the first\!" or "No sponsors yet. Be the first\!".
642
687
  - When updates are written and the repository is a git work tree, the script stages README.md and commits with a message thanking new backers and subscribers, including mentions for any newly added backers and subscribers (GitHub @handles when their website/profile is a github.com URL; otherwise their name).
643
688
  - Customize the commit subject via env var: `KETTLE_README_BACKERS_COMMIT_SUBJECT="💸 Thanks 🙏 to our new backers 🎒 and subscribers 📜"`.
644
689
  - Or via .opencollective.yml: set `readme-backers-commit-subject: "💸 Thanks 🙏 to our new backers 🎒 and subscribers 📜"`.
@@ -646,68 +691,13 @@ files:
646
691
  - Note: When used with the provided `.git-hooks`, the subject should start with a gitmoji character (see [gitmoji][📌gitmoji]).
647
692
  - Tip:
648
693
  - Run this locally before committing to keep your README current, or schedule it in CI to refresh periodically.
649
- - It runs automatically on a once-a-week schedule by the .github/workflows/opencollective.yml workflow that is part of the kettle-dev template.
694
+ - It runs automatically on a once-a-week schedule by the .github/workflows/opencollective.yml workflow that is part of the kettle-jem template.
650
695
  - Authentication requirement:
651
696
  - When running in CI with the provided workflow, you must provide an organization-level Actions secret named `README_UPDATER_TOKEN`.
652
697
  - Create it under your GitHub organization settings: `https://github.com/organizations/<YOUR_ORG>/settings/secrets/actions`.
653
698
  - The updater will look for `REPO` or `GITHUB_REPOSITORY` (both usually set by GitHub Actions) to infer `<YOUR_ORG>` for guidance.
654
699
  - If `README_UPDATER_TOKEN` is missing, the tool prints a helpful error to STDERR and aborts, including a direct link to the expected org settings page.
655
700
 
656
- ## 🦷 FLOSS Funding
657
-
658
- While kettle-rb tools are free software and will always be, the project would benefit immensely from some funding.
659
- Raising a monthly budget of... "dollars" would make the project more sustainable.
660
-
661
- We welcome both individual and corporate sponsors! We also offer a
662
- wide array of funding channels to account for your preferences
663
- (although currently [Open Collective][🖇osc] is our preferred funding platform).
664
-
665
- **If you're working in a company that's making significant use of kettle-rb tools we'd
666
- appreciate it if you suggest to your company to become a kettle-rb sponsor.**
667
-
668
- You can support the development of kettle-rb tools via
669
- [GitHub Sponsors][🖇sponsor],
670
- [Liberapay][⛳liberapay],
671
- [PayPal][🖇paypal],
672
- [Open Collective][🖇osc]
673
- and [Tidelift][🏙️entsup-tidelift].
674
-
675
- | 📍 NOTE |
676
- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
677
- | If doing a sponsorship in the form of donation is problematic for your company <br/> from an accounting standpoint, we'd recommend the use of Tidelift, <br/> where you can get a support-like subscription instead. |
678
-
679
- ### Open Collective for Individuals
680
-
681
- Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/kettle-rb#backer)]
682
-
683
- NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
684
-
685
- <!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
686
- No backers yet. Be the first!
687
- <!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
688
-
689
- ### Open Collective for Organizations
690
-
691
- Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/kettle-rb#sponsor)]
692
-
693
- NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
694
-
695
- <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
696
- No sponsors yet. Be the first!
697
- <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
698
-
699
- ### Another way to support open-source
700
-
701
- I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats).
702
-
703
- If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`.
704
-
705
- I’m developing a new library, [floss_funding][🖇floss-funding-gem], designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.
706
-
707
- **[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
708
-
709
- [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS efforts using Patreon][🖇patreon-img]][🖇patreon]
710
-
711
701
  ## 🔐 Security
712
702
 
713
703
  See [SECURITY.md][🔐security].
@@ -715,31 +705,30 @@ See [SECURITY.md][🔐security].
715
705
  ## 🤝 Contributing
716
706
 
717
707
  If you need some ideas of where to help, you could work on adding more code coverage,
718
- or if it is already 💯 (see [below](#code-coverage)) check [reek](REEK), [issues][🤝gh-issues], or [PRs][🤝gh-pulls],
708
+ or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues] or [PRs][🤝gh-pulls],
719
709
  or use the gem and think about how it could be better.
720
710
 
721
711
  We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
722
712
 
723
713
  See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
724
714
 
725
- ### Roadmap
726
-
727
- - [ ] Template the RSpec test harness.
728
- - [ ] Enhance gitlab pipeline configuration.
729
- - [ ] Add focused, packaged, named, templating strategies, allowing, for example, only refreshing the Appraisals related template files.
730
-
731
715
  ### 🚀 Release Instructions
732
716
 
733
717
  See [CONTRIBUTING.md][🤝contributing].
734
718
 
735
719
  ### Code Coverage
736
720
 
721
+ <details markdown="1">
722
+ <summary>Coverage service badges</summary>
723
+
737
724
  [![Coverage Graph][🏀codecov-g]][🏀codecov]
738
725
 
739
726
  [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls]
740
727
 
741
728
  [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov]
742
729
 
730
+ </details>
731
+
743
732
  ### 🪇 Code of Conduct
744
733
 
745
734
  Everyone interacting with this project's codebases, issue trackers,
@@ -754,13 +743,13 @@ Made with [contributors-img][🖐contrib-rocks].
754
743
  Also see GitLab Contributors: [https://gitlab.com/kettle-rb/kettle-dev/-/graphs/main][🚎contributors-gl]
755
744
 
756
745
  <details>
757
- <summary>⭐️ Star History</summary>
746
+ <summary>⭐️ Star History</summary>
758
747
 
759
- <a href="https://star-history.com/#kettle-rb/kettle-dev&Date">
748
+ <a href="https://star-history.com/kettle-rb/kettle-dev&Date">
760
749
  <picture>
761
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kettle-rb/kettle-dev&type=Date&theme=dark" />
762
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kettle-rb/kettle-dev&type=Date" />
763
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kettle-rb/kettle-dev&type=Date" />
750
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kettle-rb/kettle-dev&type=Date&theme=dark" />
751
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kettle-rb/kettle-dev&type=Date" />
752
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kettle-rb/kettle-dev&type=Date" />
764
753
  </picture>
765
754
  </a>
766
755
 
@@ -768,31 +757,20 @@ Also see GitLab Contributors: [https://gitlab.com/kettle-rb/kettle-dev/-/graphs/
768
757
 
769
758
  ## 📌 Versioning
770
759
 
771
- This Library adheres to [![Semantic Versioning 2.0.0][📌semver-img]][📌semver].
772
- Violations of this scheme should be reported as bugs.
773
- Specifically, if a minor or patch version is released that breaks backward compatibility,
774
- a new version should be immediately released that restores compatibility.
775
- Breaking changes to the public API will only be introduced with new major versions.
776
-
777
- > dropping support for a platform is both obviously and objectively a breaking change <br/>
778
- >—Jordan Harband ([@ljharb](https://github.com/ljharb), maintainer of SemVer) [in SemVer issue 716][📌semver-breaking]
779
-
780
- I understand that policy doesn't work universally ("exceptions to every rule!"),
781
- but it is the policy here.
782
- As such, in many cases it is good to specify a dependency on this library using
783
- the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
760
+ This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
761
+ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
784
762
 
785
763
  For example:
786
764
 
787
765
  ```ruby
788
- spec.add_dependency("kettle-dev", "~> 1.0")
766
+ spec.add_dependency("kettle-dev", "~> 2.0")
789
767
  ```
790
768
 
791
769
  <details markdown="1">
792
770
  <summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
793
771
 
794
- SemVer should, IMO, but doesn't explicitly, say that dropping support for specific Platforms
795
- is a *breaking change* to an API, and for that reason the bike shedding is endless.
772
+ Dropping support for a platform can be a breaking change for affected users.
773
+ If a release changes supported platforms, it should be called out clearly in the changelog and versioned with that impact in mind.
796
774
 
797
775
  To get a better understanding of how SemVer is intended to work over a project's lifetime,
798
776
  read this article from the creator of SemVer:
@@ -805,23 +783,21 @@ See [CHANGELOG.md][📌changelog] for a list of releases.
805
783
 
806
784
  ## 📄 License
807
785
 
808
- The gem is available as open source under the terms of
809
- the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref].
810
- See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer].
786
+ The gem is available under the following license: [AGPL-3.0-only](AGPL-3.0-only.md).
787
+ See [LICENSE.md][📄license] for details.
788
+
789
+ If none of the available licenses suit your use case, please [contact us](mailto:floss@galtzo.com) to discuss a custom commercial license.
811
790
 
812
791
  ### © Copyright
813
792
 
814
- <ul>
815
- <li>
816
- Copyright (c) 2023, 2025 Peter H. Boling, of
817
- <a href="https://discord.gg/3qme4XHNKN">
818
- Galtzo.com
819
- <picture>
820
- <img src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px-blank.svg" alt="Galtzo.com Logo (Wordless) by Aboling0, CC BY-SA 4.0" width="24">
821
- </picture>
822
- </a>, and kettle-dev contributors.
823
- </li>
824
- </ul>
793
+ See [LICENSE.md][📄license] for the official copyright notice.
794
+
795
+ <details markdown="1">
796
+ <summary>Copyright holders</summary>
797
+
798
+ - Copyright (c) 2023, 2025-2026 Peter H. Boling
799
+
800
+ </details>
825
801
 
826
802
  ## 🤑 A request for help
827
803
 
@@ -864,7 +840,7 @@ Thanks for RTFM. ☺️
864
840
  [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
865
841
  [🖇polar]: https://polar.sh/pboling
866
842
  [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
867
- [🖇kofi]: https://ko-fi.com/O5O86SNP4
843
+ [🖇kofi]: https://ko-fi.com/pboling
868
844
  [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
869
845
  [🖇patreon]: https://patreon.com/galtzo
870
846
  [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
@@ -886,13 +862,13 @@ Thanks for RTFM. ☺️
886
862
  [⛳️gem-name]: https://bestgems.org/gems/kettle-dev
887
863
  [⛳️name-img]: https://img.shields.io/badge/name-kettle--dev-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
888
864
  [⛳️tag-img]: https://img.shields.io/github/tag/kettle-rb/kettle-dev.svg
889
- [⛳️tag]: http://github.com/kettle-rb/kettle-dev/releases
865
+ [⛳️tag]: https://github.com/kettle-rb/kettle-dev/releases
890
866
  [🚂maint-blog]: http://www.railsbling.com/tags/kettle-dev
891
867
  [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
892
868
  [🚂maint-contact]: http://www.railsbling.com/contact
893
869
  [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
894
870
  [💖🖇linkedin]: http://www.linkedin.com/in/peterboling
895
- [💖🖇linkedin-img]: https://img.shields.io/badge/PeterBoling-LinkedIn-0B66C2?style=flat&logo=newjapanprowrestling
871
+ [💖🖇linkedin-img]: https://img.shields.io/badge/LinkedIn-Profile-0B66C2?style=flat&logo=newjapanprowrestling
896
872
  [💖✌️wellfound]: https://wellfound.com/u/peter-boling
897
873
  [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound
898
874
  [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
@@ -921,7 +897,7 @@ Thanks for RTFM. ☺️
921
897
  [💁🏼‍♂️peterboling]: http://www.peterboling.com
922
898
  [🚂railsbling]: http://www.railsbling.com
923
899
  [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange
924
- [📜src-gl]: https://gitlab.com/kettle-rb/kettle-dev/
900
+ [📜src-gl]: https://gitlab.com/kettle-rb/kettle-dev
925
901
  [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue
926
902
  [📜src-cb]: https://codeberg.org/kettle-rb/kettle-dev
927
903
  [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green
@@ -930,12 +906,10 @@ Thanks for RTFM. ☺️
930
906
  [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
931
907
  [📜gl-wiki]: https://gitlab.com/kettle-rb/kettle-dev/-/wikis/home
932
908
  [📜gh-wiki]: https://github.com/kettle-rb/kettle-dev/wiki
933
- [📜gl-wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white
934
- [📜gh-wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
909
+ [📜gl-wiki-img]: https://img.shields.io/badge/wiki-gitlab-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white
910
+ [📜gh-wiki-img]: https://img.shields.io/badge/wiki-github-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
935
911
  [👽dl-rank]: https://bestgems.org/gems/kettle-dev
936
912
  [👽dl-ranki]: https://img.shields.io/gem/rd/kettle-dev.svg
937
- [👽oss-help]: https://www.codetriage.com/kettle-rb/kettle-dev
938
- [👽oss-helpi]: https://www.codetriage.com/kettle-rb/kettle-dev/badges/users.svg
939
913
  [👽version]: https://bestgems.org/gems/kettle-dev
940
914
  [👽versioni]: https://img.shields.io/gem/v/kettle-dev.svg
941
915
  [🏀qlty-mnt]: https://qlty.sh/gh/kettle-rb/projects/kettle-dev
@@ -948,22 +922,29 @@ Thanks for RTFM. ☺️
948
922
  [🏀coveralls-img]: https://coveralls.io/repos/github/kettle-rb/kettle-dev/badge.svg?branch=main
949
923
  [🖐codeQL]: https://github.com/kettle-rb/kettle-dev/security/code-scanning
950
924
  [🖐codeQL-img]: https://github.com/kettle-rb/kettle-dev/actions/workflows/codeql-analysis.yml/badge.svg
951
- [🚎1-an-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ancient.yml
952
- [🚎1-an-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ancient.yml/badge.svg
925
+ [🚎ruby-2.4-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-2.4.yml
926
+ [🚎ruby-2.5-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-2.5.yml
927
+ [🚎ruby-2.6-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-2.6.yml
928
+ [🚎ruby-2.7-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-2.7.yml
929
+ [🚎ruby-3.0-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-3.0.yml
930
+ [🚎ruby-3.1-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-3.1.yml
931
+ [🚎ruby-3.2-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-3.2.yml
932
+ [🚎ruby-3.3-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-3.3.yml
933
+ [🚎ruby-3.4-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/ruby-3.4.yml
934
+ [🚎jruby-9.2-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/jruby-9.2.yml
935
+ [🚎jruby-9.3-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/jruby-9.3.yml
936
+ [🚎jruby-9.4-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/jruby-9.4.yml
937
+ [🚎truby-22.3-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/truffleruby-22.3.yml
938
+ [🚎truby-23.0-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/truffleruby-23.0.yml
939
+ [🚎truby-23.1-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/truffleruby-23.1.yml
940
+ [🚎truby-24.2-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/truffleruby-24.2.yml
941
+ [🚎truby-25.0-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/truffleruby-25.0.yml
953
942
  [🚎2-cov-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/coverage.yml
954
943
  [🚎2-cov-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/coverage.yml/badge.svg
955
944
  [🚎3-hd-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/heads.yml
956
945
  [🚎3-hd-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/heads.yml/badge.svg
957
- [🚎4-lg-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/legacy.yml
958
- [🚎4-lg-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/legacy.yml/badge.svg
959
946
  [🚎5-st-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/style.yml
960
947
  [🚎5-st-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/style.yml/badge.svg
961
- [🚎6-s-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/supported.yml
962
- [🚎6-s-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/supported.yml/badge.svg
963
- [🚎7-us-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/unsupported.yml
964
- [🚎7-us-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/unsupported.yml/badge.svg
965
- [🚎8-ho-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/hoary.yml
966
- [🚎8-ho-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/hoary.yml/badge.svg
967
948
  [🚎9-t-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/truffle.yml
968
949
  [🚎9-t-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/truffle.yml/badge.svg
969
950
  [🚎10-j-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/jruby.yml
@@ -976,9 +957,6 @@ Thanks for RTFM. ☺️
976
957
  [🚎13-🔒️-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/locked_deps.yml/badge.svg
977
958
  [🚎14-🔓️-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/unlocked_deps.yml
978
959
  [🚎14-🔓️-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/unlocked_deps.yml/badge.svg
979
- [🚎15-🪪-wf]: https://github.com/kettle-rb/kettle-dev/actions/workflows/license-eye.yml
980
- [🚎15-🪪-wfi]: https://github.com/kettle-rb/kettle-dev/actions/workflows/license-eye.yml/badge.svg
981
- [💎ruby-2.3i]: https://img.shields.io/badge/Ruby-2.3-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
982
960
  [💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
983
961
  [💎ruby-2.5i]: https://img.shields.io/badge/Ruby-2.5-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
984
962
  [💎ruby-2.6i]: https://img.shields.io/badge/Ruby-2.6-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
@@ -987,16 +965,18 @@ Thanks for RTFM. ☺️
987
965
  [💎ruby-3.1i]: https://img.shields.io/badge/Ruby-3.1-CC342D?style=for-the-badge&logo=ruby&logoColor=white
988
966
  [💎ruby-3.2i]: https://img.shields.io/badge/Ruby-3.2-CC342D?style=for-the-badge&logo=ruby&logoColor=white
989
967
  [💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white
968
+ [💎ruby-3.4i]: https://img.shields.io/badge/Ruby-3.4-CC342D?style=for-the-badge&logo=ruby&logoColor=white
969
+ [💎ruby-4.0i]: https://img.shields.io/badge/Ruby-4.0-CC342D?style=for-the-badge&logo=ruby&logoColor=white
990
970
  [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green
991
971
  [💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue
992
- [💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=pink
993
- [💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=pink
972
+ [💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
973
+ [💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
994
974
  [💎truby-23.1i]: https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
975
+ [💎truby-24.2i]: https://img.shields.io/badge/Truffle_Ruby-24.2-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
976
+ [💎truby-25.0i]: https://img.shields.io/badge/Truffle_Ruby-25.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
995
977
  [💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green
996
- [💎truby-headi]: https://img.shields.io/badge/Truffle_Ruby-HEAD-34BCB1?style=for-the-badge&logo=ruby&logoColor=blue
997
- [💎jruby-9.1i]: https://img.shields.io/badge/JRuby-9.1_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red
998
- [💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red
999
- [💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red
978
+ [💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2-FBE742?style=for-the-badge&logo=ruby&logoColor=red
979
+ [💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3-FBE742?style=for-the-badge&logo=ruby&logoColor=red
1000
980
  [💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red
1001
981
  [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green
1002
982
  [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue
@@ -1007,34 +987,34 @@ Thanks for RTFM. ☺️
1007
987
  [🤝cb-issues]: https://codeberg.org/kettle-rb/kettle-dev/issues
1008
988
  [🤝cb-pulls]: https://codeberg.org/kettle-rb/kettle-dev/pulls
1009
989
  [🤝cb-donate]: https://donate.codeberg.org/
1010
- [🤝contributing]: CONTRIBUTING.md
1011
- [🏀codecov-g]: https://codecov.io/gh/kettle-rb/kettle-dev/graphs/tree.svg
990
+ [🤝contributing]: https://github.com/kettle-rb/kettle-dev/blob/main/CONTRIBUTING.md
991
+ [🏀codecov-g]: https://codecov.io/gh/kettle-rb/kettle-dev/graph/badge.svg
1012
992
  [🖐contrib-rocks]: https://contrib.rocks
1013
993
  [🖐contributors]: https://github.com/kettle-rb/kettle-dev/graphs/contributors
1014
994
  [🖐contributors-img]: https://contrib.rocks/image?repo=kettle-rb/kettle-dev
1015
995
  [🚎contributors-gl]: https://gitlab.com/kettle-rb/kettle-dev/-/graphs/main
1016
- [🪇conduct]: CODE_OF_CONDUCT.md
996
+ [🪇conduct]: https://github.com/kettle-rb/kettle-dev/blob/main/CODE_OF_CONDUCT.md
1017
997
  [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
1018
998
  [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
1019
999
  [📌semver]: https://semver.org/spec/v2.0.0.html
1020
1000
  [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat
1021
1001
  [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
1022
1002
  [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
1023
- [📌changelog]: CHANGELOG.md
1003
+ [📌changelog]: https://github.com/kettle-rb/kettle-dev/blob/main/CHANGELOG.md
1024
1004
  [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
1025
1005
  [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
1026
1006
  [📌gitmoji]: https://gitmoji.dev
1027
1007
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1028
1008
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1029
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-5.026-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1030
- [🔐security]: SECURITY.md
1009
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-3.068-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1010
+ [🔐security]: https://github.com/kettle-rb/kettle-dev/blob/main/SECURITY.md
1031
1011
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1032
1012
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
1033
- [📄license]: LICENSE.txt
1034
- [📄license-ref]: https://opensource.org/licenses/MIT
1035
- [📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg
1036
- [📄license-compat]: https://dev.to/galtzo/how-to-check-license-compatibility-41h0
1037
- [📄license-compat-img]: https://img.shields.io/badge/Apache_Compatible:_Category_A-%E2%9C%93-259D6C.svg?style=flat&logo=Apache
1013
+ [📄license]: LICENSE.md
1014
+ [📄license-ref]: AGPL-3.0-only.md
1015
+ [📄license-img]: https://img.shields.io/badge/License-AGPL--3.0--only-259D6C.svg
1016
+ [📄license-compat]: https://www.apache.org/legal/resolved.html#category-x
1017
+ [📄license-compat-img]: https://img.shields.io/badge/Apache_Incompatible:_Category_X-%E2%9C%97-C0392B.svg?style=flat&logo=Apache
1038
1018
  [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
1039
1019
  [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
1040
1020
  [🚎yard-current]: http://rubydoc.info/gems/kettle-dev
@@ -1046,3 +1026,14 @@ Thanks for RTFM. ☺️
1046
1026
  [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
1047
1027
  [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
1048
1028
  [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
1029
+
1030
+ <!-- kettle-jem:metadata:start -->
1031
+ | Field | Value |
1032
+ |---|---|
1033
+ | Package | kettle-dev |
1034
+ | Description | 🍲 Kettle::Dev is a meta tool from kettle-rb to streamline development and testing. Acts as a shim dependency, pulling in many other dependencies, to give you OOTB productivity with a RubyGem, or Ruby app project. Configures a complete set of Rake tasks, for all the libraries is brings in, so they arrive ready to go. Fund overlooked open source projects - bottom of stack, dev/test dependencies: floss-funding.dev |
1035
+ | Homepage | https://github.com/kettle-rb/kettle-dev |
1036
+ | Source | https://github.com/kettle-rb/kettle-dev/tree/v2.0.1 |
1037
+ | License | `AGPL-3.0-only` |
1038
+ | Funding | https://github.com/sponsors/pboling, https://issuehunt.io/u/pboling, https://ko-fi.com/pboling, https://liberapay.com/pboling/donate, https://opencollective.com/kettle-rb, https://patreon.com/galtzo, https://polar.sh/pboling, https://thanks.dev/u/gh/pboling, https://tidelift.com/funding/github/rubygems/kettle-dev, https://www.buymeacoffee.com/pboling |
1039
+ <!-- kettle-jem:metadata:end -->