kettle-dev 1.1.4 → 1.1.5

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 (45) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.env.local.example +14 -1
  4. data/.envrc +2 -2
  5. data/.git-hooks/commit-msg +22 -16
  6. data/.git-hooks/prepare-commit-msg.example +19 -0
  7. data/.github/workflows/coverage.yml +2 -2
  8. data/.junie/guidelines.md +4 -0
  9. data/.opencollective.yml.example +3 -0
  10. data/CHANGELOG.md +31 -1
  11. data/CONTRIBUTING.md +29 -0
  12. data/FUNDING.md +2 -2
  13. data/README.md +148 -38
  14. data/README.md.example +7 -7
  15. data/Rakefile.example +1 -1
  16. data/exe/kettle-changelog +7 -2
  17. data/exe/kettle-commit-msg +20 -5
  18. data/exe/kettle-dev-setup +2 -1
  19. data/exe/kettle-dvcs +7 -2
  20. data/exe/kettle-pre-release +66 -0
  21. data/exe/kettle-readme-backers +7 -2
  22. data/exe/kettle-release +9 -2
  23. data/lib/kettle/dev/changelog_cli.rb +4 -5
  24. data/lib/kettle/dev/ci_helpers.rb +9 -5
  25. data/lib/kettle/dev/ci_monitor.rb +229 -8
  26. data/lib/kettle/dev/gem_spec_reader.rb +105 -39
  27. data/lib/kettle/dev/git_adapter.rb +6 -3
  28. data/lib/kettle/dev/git_commit_footer.rb +5 -2
  29. data/lib/kettle/dev/pre_release_cli.rb +248 -0
  30. data/lib/kettle/dev/readme_backers.rb +4 -2
  31. data/lib/kettle/dev/release_cli.rb +27 -17
  32. data/lib/kettle/dev/tasks/ci_task.rb +112 -22
  33. data/lib/kettle/dev/tasks/install_task.rb +23 -17
  34. data/lib/kettle/dev/tasks/template_task.rb +64 -23
  35. data/lib/kettle/dev/template_helpers.rb +44 -31
  36. data/lib/kettle/dev/version.rb +1 -1
  37. data/lib/kettle/dev.rb +5 -0
  38. data/sig/kettle/dev/ci_monitor.rbs +6 -0
  39. data/sig/kettle/dev/gem_spec_reader.rbs +8 -5
  40. data/sig/kettle/dev/pre_release_cli.rbs +20 -0
  41. data/sig/kettle/dev/template_helpers.rbs +2 -0
  42. data/sig/kettle/dev.rbs +1 -0
  43. data.tar.gz.sig +0 -0
  44. metadata +30 -4
  45. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e041df45a5e998c2dabf617686124f45b29aa26d93c1dcf21e0da99cffcac3b
4
- data.tar.gz: 183b02683f8a96d82ad6df04371b8776110a30eb768c395060f3d8dd2a5011b0
3
+ metadata.gz: f68d8b2e7fab5b4e07af0c56ef2b13754adcb43a91cb1bc521527153b11db756
4
+ data.tar.gz: 41a619d94690defc476bcf2666dd71acabeffce33c7c47eaa6b912b5983a9117
5
5
  SHA512:
6
- metadata.gz: 505620d1cef37c67523e6c8760172f215b650e3f972397170f4f0275a838c8b0a1d9ab1b36e5cc1dbeedfb8327672e02b94be7e2269cb3f446375a83abed040b
7
- data.tar.gz: 2de8a12668ed28128b11425f2097473ad60714a98985375c249053ca001b9e23e295c2e1afde917b2d8a13fab4270362cc5bffb4916637e56dd6b43687240425
6
+ metadata.gz: e5efa939db2b66d476069297dd8340b07f8a62763248e13ef81d4cd9ac34d1c7a8ebd1f11e481580ed608f33a181e32d673fcf552561ad9efd7765b266ff49f0
7
+ data.tar.gz: 0a9c66859f5fb518e197a29b367da2fe0fdfe0fa941b9de48627ac4464e2f9c497dcbf41882603f8b907664b880922adacf9aab08725a1eae48f3cbae26a8f6b
checksums.yaml.gz.sig CHANGED
Binary file
data/.env.local.example CHANGED
@@ -11,4 +11,17 @@ export AUTOGEN_FIXTURE_CLEANUP=false # autogenerated gem fixture cleanup after e
11
11
  export GIT_HOOK_FOOTER_APPEND=false
12
12
  export GIT_HOOK_FOOTER_APPEND_DEBUG=false
13
13
  export GIT_HOOK_FOOTER_SENTINEL="⚡️ A message from a fellow meat-based-AI ⚡️"
14
- export GITHUB_TOKEN=<your GH PAT, for the GHA console bin/rake ci:act - DO NOT EVER COMMIT IT>
14
+
15
+ # Tokens used by ci:act and CI helpers for reading workflow/pipeline status via APIs
16
+ # GitHub (either GITHUB_TOKEN or GH_TOKEN will be used; fine-grained recommended)
17
+ # - Scope/permissions: For fine-grained tokens, grant repository access (Read) and Actions: Read
18
+ # - For classic tokens, public repos need no scopes; private repos typically require repo
19
+ export GITHUB_TOKEN=<your GH token for GHA status; NEVER COMMIT>
20
+ # Alternatively:
21
+ # export GH_TOKEN=<your GH token>
22
+
23
+ # GitLab (either GITLAB_TOKEN or GL_TOKEN will be used)
24
+ # - Scope: read_api is sufficient to read pipelines
25
+ export GITLAB_TOKEN=<your GitLab token for pipeline status; NEVER COMMIT>
26
+ # Alternatively:
27
+ # export GL_TOKEN=<your GitLab token>
data/.envrc CHANGED
@@ -21,8 +21,8 @@ export K_SOUP_COV_DO=true # Means you want code coverage
21
21
  export K_SOUP_COV_COMMAND_NAME="Test Coverage"
22
22
  # Available formats are html, xml, rcov, lcov, json, tty
23
23
  export K_SOUP_COV_FORMATTERS="html,xml,rcov,lcov,json,tty"
24
- export K_SOUP_COV_MIN_BRANCH=78 # Means you want to enforce X% branch coverage
25
- export K_SOUP_COV_MIN_LINE=97 # Means you want to enforce X% line coverage
24
+ export K_SOUP_COV_MIN_BRANCH=81 # Means you want to enforce X% branch coverage
25
+ export K_SOUP_COV_MIN_LINE=96 # Means you want to enforce X% line coverage
26
26
  export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met
27
27
  export K_SOUP_COV_MULTI_FORMATTERS=true
28
28
  export K_SOUP_COV_OPEN_BIN= # Means don't try to open coverage results in browser
@@ -1,21 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
2
  # vim: set syntax=ruby
3
3
 
4
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
5
-
6
- require "rubygems"
7
- require "bundler/setup"
8
-
9
- # External gems
10
- require "gitmoji/regex"
4
+ # Do not rely on Bundler; allow running outside a Bundler context
5
+ begin
6
+ require "rubygems"
7
+ rescue LoadError
8
+ # continue
9
+ end
11
10
 
12
- full_text = File.read(ARGV[0])
13
- # Is the first character a GitMoji?
14
- gitmoji_index = full_text =~ Gitmoji::Regex::REGEX
15
- if gitmoji_index == 0
16
- exit 0
17
- else
18
- denied = <<EOM
11
+ begin
12
+ # External gems
13
+ require "gitmoji/regex"
14
+
15
+ full_text = File.read(ARGV[0])
16
+ # Is the first character a GitMoji?
17
+ gitmoji_index = full_text =~ Gitmoji::Regex::REGEX
18
+ if gitmoji_index == 0
19
+ exit 0
20
+ else
21
+ denied = <<EOM
19
22
  Oh snap, think again...
20
23
 
21
24
  ______ _______ ___ _______ _______ _______ _______ ______ __
@@ -36,6 +39,9 @@ Must match: #{Gitmoji::Regex::REGEX.to_s}
36
39
  Example: git commit -m "✨ My excellent new feature"
37
40
 
38
41
  EOM
39
- puts denied
40
- exit 1
42
+ puts denied
43
+ exit 1
44
+ end
45
+ rescue LoadError => e
46
+ warn("gitmoji-regex gem not found: #{e.class}: #{e.message}.\n\tInstall the 'gitmoji-regex' gem to enable this check.\n\tSkipping gitmoji check.")
41
47
  end
@@ -0,0 +1,19 @@
1
+ #!/bin/sh
2
+
3
+ # Fail on error and unset variables
4
+ set -eu
5
+
6
+ # Determine project root as the parent directory of this hook script
7
+ PROJECT_ROOT="$(CDPATH= cd -- "$(dirname -- "$0")"/.. && pwd)"
8
+
9
+ # Run the Ruby hook within the direnv context (if available),
10
+ # so ENV from .envrc/.env.local at project root is loaded.
11
+ # One of the things .envrc needs to do is add $PROJECT_ROOT/bin/ to the path.
12
+ # You should have this line at the top of .envrc
13
+ # PATH_add bin
14
+ # NOTE: If this project ships exe scripts it should also add that.
15
+ if command -v direnv >/dev/null 2>&1; then
16
+ exec direnv exec "$PROJECT_ROOT" "kettle-commit-msg" "$@"
17
+ else
18
+ raise "direnv not found. Local development of this project ($PROJECT_ROOT) with tools from the kettle-dev gem may not work properly. Please run 'brew install direnv'."
19
+ fi
@@ -7,7 +7,7 @@ permissions:
7
7
 
8
8
  env:
9
9
  # Lower than local, which is at 100/100, because rubocop-lts isn't installed in the coverage workflow
10
- K_SOUP_COV_MIN_BRANCH: 73
10
+ K_SOUP_COV_MIN_BRANCH: 78
11
11
  K_SOUP_COV_MIN_LINE: 93
12
12
  K_SOUP_COV_MIN_HARD: true
13
13
  K_SOUP_COV_FORMATTERS: "xml,rcov,lcov,tty"
@@ -116,7 +116,7 @@ jobs:
116
116
  hide_complexity: true
117
117
  indicators: true
118
118
  output: both
119
- thresholds: '93 73'
119
+ thresholds: '93 78'
120
120
  continue-on-error: ${{ matrix.experimental != 'false' }}
121
121
 
122
122
  - name: Add Coverage PR Comment
data/.junie/guidelines.md CHANGED
@@ -133,3 +133,7 @@ Notes
133
133
  - Coverage reports: NEVER review the HTML report. Use JSON (preferred), XML, LCOV, or RCOV. For this project, always run tests with K_SOUP_COV_FORMATTERS set to "json".
134
134
  - Do NOT modify .envrc in tasks; when running tests locally or in scripts, manually prefix each run, e.g.: K_SOUP_COV_FORMATTERS="json" bin/rspec
135
135
  - For all the kettle-soup-cover options, see .envrc and find the K_SOUP_COV_* env vars.
136
+
137
+ Important documentation rules
138
+ - Do NOT edit files under docs/ manually; they are generated by `bundle exec rake yard` as part of the default rake task.
139
+ - Clarification: Executable scripts provided by this gem (exe/* and installed binstubs) work when the gem is installed as a system gem (gem install kettle-dev). However, the Rake tasks provided by this gem require kettle-dev to be declared as a development dependency in the host project's Gemfile and loaded in the project's Rakefile.
@@ -0,0 +1,3 @@
1
+ collective: "{OPENCOLLECTIVE|ORG_NAME}"
2
+ readme-backers-commit-subject: "💸 Thanks 🙏 to our new backers 🎒 and subscribers 📜"
3
+ readme-osc-tag: "OPENCOLLECTIVE"
data/CHANGELOG.md CHANGED
@@ -24,6 +24,34 @@ Please file a bug if you notice a violation of semantic versioning.
24
24
  ### Fixed
25
25
  ### Security
26
26
 
27
+ ## [1.1.5] - 2025-09-04
28
+ - TAG: [v1.1.5][1.1.5t]
29
+ - COVERAGE: 33.87% -- 1125/3322 lines in 22 files
30
+ - BRANCH COVERAGE: 22.04% -- 361/1638 branches in 22 files
31
+ - 76.83% documented
32
+ ### Added
33
+ - kettle-pre-release: run re-release checks on a library
34
+ - validate URLs of image assets in Markdown files
35
+ - honor ENV["FUNDING_FORGE"] set to "false" as intentional disabling of funding-related logic.
36
+ - Add CLI Option --only passthrough from kettle-dev-setup to Installation Task
37
+ - Comprehensive documentation of all exe/ scripts in README.md
38
+ - add gitlab pipeline result to ci:act
39
+ - highlight SHA discrepancies in ci:act task header info
40
+ - how to set up forge tokens for ci:act, and other tools, instructions for README.md
41
+ ### Changed
42
+ - expanded use of adapter patterns (Exit, Git, and Input)
43
+ - refactored and improved structure of code, more resilient
44
+ - kettle-release: do not abort immediately on CI failure; continue checking all workflows, summarize results, and prompt to (c)ontinue or (q)uit (reuses ci:act-style summary)
45
+ ### Removed
46
+ - defensive NameError handling in ChangelogCLI.abort method
47
+ ### Fixed
48
+ - replace token {OPENCOLLECTIVE|ORG_NAME} with funding org name
49
+ - prefer .example version of .git-hooks
50
+ - kettle-commit-msg now runs via rubygems (not bundler) so it will work via a system gem
51
+ - fixed logic for handling derivation of forge and funding URLs
52
+ - allow commits to succeed if dependencies are missing or broken
53
+ - RBS types documentation for GemSpecReader
54
+
27
55
  ## [1.1.4] - 2025-09-02
28
56
  - TAG: [v1.1.4][1.1.4t]
29
57
  - COVERAGE: 67.64% -- 554/819 lines in 9 files
@@ -468,7 +496,9 @@ Please file a bug if you notice a violation of semantic versioning.
468
496
  - Selecting will run the selected workflow via `act`
469
497
  - This may move to its own gem in the future.
470
498
 
471
- [Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.4...HEAD
499
+ [Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.5...HEAD
500
+ [1.1.5]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.4...v1.1.5
501
+ [1.1.5t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.1.5
472
502
  [1.1.4]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.3...v1.1.4
473
503
  [1.1.4t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.1.4
474
504
  [1.1.3]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.2...v1.1.3
data/CONTRIBUTING.md CHANGED
@@ -22,6 +22,35 @@ Follow these instructions:
22
22
  6. Make sure to add tests for it. This is important, so it doesn't break in a future release.
23
23
  7. Create new Pull Request.
24
24
 
25
+ ## Executables vs Rake tasks
26
+
27
+ Executables shipped by kettle-dev can be used with or without generating the binstubs.
28
+ They will work when kettle-dev is installed globally (i.e., `gem install kettle-dev`) and do not require that kettle-dev be in your bundle.
29
+
30
+ - kettle-changelog
31
+ - kettle-commit-msg
32
+ - kettle-dev-setup
33
+ - kettle-dvcs
34
+ - kettle-pre-release
35
+ - kettle-readme-backers
36
+ - kettle-release
37
+
38
+ However, the rake tasks provided by kettle-dev do require kettle-dev to be added as a development dependency and loaded in your Rakefile.
39
+ See the full list of rake tasks in head of Rakefile
40
+
41
+ **Gemfile**
42
+ ```ruby
43
+ group :development do
44
+ gem "kettle-dev", require: false
45
+ end
46
+ ```
47
+
48
+ **Rakefile**
49
+ ```ruby
50
+ # Rakefile
51
+ require "kettle/dev"
52
+ ```
53
+
25
54
  ## Environment Variables for Local Development
26
55
 
27
56
  Below are the primary environment variables recognized by stone_checksums (and its integrated tools). Unless otherwise noted, set boolean values to the string "true" to enable.
data/FUNDING.md CHANGED
@@ -18,11 +18,11 @@ Many paths lead to being a sponsor or a backer of this project. Are you on such
18
18
  [🖇sponsor]: https://github.com/sponsors/pboling
19
19
  [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
20
20
  [🖇polar]: https://polar.sh/pboling
21
- [🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat
21
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
22
22
  [🖇kofi]: https://ko-fi.com/O5O86SNP4
23
23
  [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
24
24
  [🖇patreon]: https://patreon.com/galtzo
25
- [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat
25
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
26
26
  [🖇buyme]: https://www.buymeacoffee.com/pboling
27
27
  [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
28
28
  [🖇paypal]: https://www.paypal.com/paypalme/peterboling
data/README.md CHANGED
@@ -123,7 +123,7 @@ What it does:
123
123
  - If any fail, the script prints import links to help you create a mirror on that forge.
124
124
 
125
125
  <details>
126
- <summary>Find this repo on other forges (Coming soon!)</summary>
126
+ <summary>Find this repo on other forges</summary>
127
127
 
128
128
  | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
129
129
  |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
@@ -210,6 +210,19 @@ NOTE: Be prepared to track down certs for signed gems and add them the same way
210
210
 
211
211
  ## ⚙️ Configuration
212
212
 
213
+ Note on executables vs Rake tasks
214
+ - 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.
215
+ - 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:
216
+ ```ruby
217
+ group :development do
218
+ gem "kettle-dev", require: false
219
+ end
220
+ ```
221
+ And your Rakefile loads the gem's tasks, e.g.:
222
+ ```ruby
223
+ require "kettle/dev"
224
+ ```
225
+
213
226
  ### RSpec
214
227
 
215
228
  This gem integrates tightly with [kettle-test](https://github.com/kettle-rb/kettle-test).
@@ -230,11 +243,16 @@ Then run the one-time project bootstrapper:
230
243
 
231
244
  ```console
232
245
  kettle-dev-setup
246
+ # Or to accept all defaults:
247
+ kettle-dev-setup --allowed=true --force
233
248
  ```
234
249
 
235
- After bootstrapping you may want to update the template.
250
+ You'll be able to compare the changes with your diff tool, and certainly revert some of them.
236
251
 
237
- Invoke the rake task directly:
252
+ For your protection:
253
+ - it won't run if git doesn't start out porcelain clean.
254
+
255
+ After bootstrapping, to update the template to the latest version from a new release of this gem, run:
238
256
 
239
257
  ```console
240
258
  bundle exec rake kettle:dev:install
@@ -310,6 +328,7 @@ Tip: When running a single spec file locally, you may want `K_SOUP_COV_MIN_HARD=
310
328
 
311
329
  GitHub API and CI helpers
312
330
  - GITHUB_TOKEN or GH_TOKEN: Token used by `ci:act` and release workflow checks to query GitHub Actions status at higher rate limits
331
+ - GITLAB_TOKEN or GL_TOKEN: Token used by `ci:act` and CI monitor to query GitLab pipeline status
313
332
 
314
333
  Releasing and signing
315
334
  - SKIP_GEM_SIGNING: If set, skip gem signing during build/release
@@ -344,6 +363,28 @@ GitHub Actions local runner helper
344
363
  - `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.
345
364
  - Non-interactive: `bundle exec rake ci:act[loc]` (short code), or `bundle exec rake ci:act[locked_deps.yml]` (filename).
346
365
 
366
+ Setup tokens for API status (GitHub and GitLab)
367
+ - 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.
368
+ - GitHub token (recommended: fine-grained):
369
+ - Where to create: https://github.com/settings/personal-access-tokens
370
+ - Fine-grained: “Tokens (fine-grained)” → Generate new token
371
+ - Classic (fallback): “Tokens (classic)” → Generate new token
372
+ - Minimum permissions:
373
+ - Fine-grained: Repository access: Read-only for the target repository (or your org); Permissions → Actions: Read
374
+ - Classic: For public repos, no scopes are strictly required but rate limits are very low; for private repos, include the repo scope
375
+ - Add to environment (.env.local via direnv):
376
+ - GITHUB_TOKEN=your_token_here (or GH_TOKEN=…)
377
+ - GitLab token:
378
+ - Where to create (gitlab.com): https://gitlab.com/-/user_settings/personal_access_tokens
379
+ - Minimum scope: read_api (sufficient to read pipelines)
380
+ - Add to environment (.env.local via direnv):
381
+ - GITLAB_TOKEN=your_token_here (or GL_TOKEN=…)
382
+ - Load environment:
383
+ - Save tokens in .env.local (never commit this file), then run: direnv allow
384
+ - Verify:
385
+ - Run: bundle exec rake ci:act
386
+ - 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.
387
+
347
388
  Project automation bootstrap
348
389
  - `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.
349
390
  - `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.
@@ -372,8 +413,10 @@ Project automation bootstrap
372
413
  - This behavior is automatic for any future `*.example` files added to the templates.
373
414
  - 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`.
374
415
 
375
- Releasing (maintainers)
376
- - `exe/kettle-release` — guided release helper that:
416
+ ### Releasing (maintainers)
417
+
418
+ - Script: `exe/kettle-release` (run as `kettle-release`)
419
+ - Purpose: guided release helper that:
377
420
  - Runs sanity checks (`bin/setup`, `bin/rake`), confirms version/changelog, optionally updates Appraisals, commits “🔖 Prepare release vX.Y.Z”.
378
421
  - Optionally runs your CI locally with `act` before any push:
379
422
  - Enable with env: `K_RELEASE_LOCAL_CI="true"` (run automatically) or `K_RELEASE_LOCAL_CI="ask"` (prompt [Y/n]).
@@ -381,35 +424,100 @@ Releasing (maintainers)
381
424
  - On failure, the release prep commit is soft-rolled-back (`git reset --soft HEAD^`) and the process aborts.
382
425
  - Ensures trunk sync and rebases feature as needed, pushes, monitors GitHub Actions with a progress bar, and merges feature to trunk on success.
383
426
  - 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).
384
-
385
- - start_step map (skip directly to a phase):
386
- - 1: Ensure Bundler >= 2.7.0 and begin full flow
387
- - 2: Version detection + sanity checks + prompt to confirm version.rb and CHANGELOG.md
388
- - 3: Run bin/setup
389
- - 4: Run bin/rake (default task)
390
- - 5: Run appraisal:update when Appraisals exists (skip otherwise)
391
- - 6: Verify git user.name/email and commit release prep "🔖 Prepare release vX.Y.Z"
392
- - 7: Optionally run local CI with nektos/act before pushing (see K_RELEASE_LOCAL_CI, K_RELEASE_LOCAL_CI_WORKFLOW)
393
- - 8: Ensure trunk is up-to-date and reconcile with GitHub remote if needed
394
- - 9: Push current branch to configured remotes (or default), force-pushing on retry when needed
395
- - 10: Monitor CI after push (GitHub Actions and/or GitLab pipelines); progress bar; aborts on failure
396
- - 11: Merge feature branch into trunk and push
397
- - 12: Checkout trunk and pull latest
398
- - 13: Signing checks and guidance (abort when signing enabled but cert missing); respect SKIP_GEM_SIGNING
399
- - 14: Build gem (honors SKIP_GEM_SIGNING via env prefix)
400
- - 15: Generate and validate gem checksums (bin/gem_checksums)
401
- - 16: Release via `bundle exec rake release` and validate checksums again
402
- - 17: Create GitHub release from CHANGELOG when GITHUB_TOKEN present
403
- - 18: Push git tags to remotes (to "all" remote only when present; otherwise to each remote)
404
-
405
- Examples:
427
+ - Options:
428
+ - start_step map (skip directly to a phase):
429
+ - 1: Ensure Bundler >= 2.7.0 and begin full flow
430
+ - 2: Version detection + sanity checks + prompt to confirm version.rb and CHANGELOG.md
431
+ - 3: Run bin/setup
432
+ - 4: Run bin/rake (default task)
433
+ - 5: Run appraisal:update when Appraisals exists (skip otherwise)
434
+ - 6: Verify git user.name/email and commit release prep "🔖 Prepare release vX.Y.Z"
435
+ - 7: Optionally run local CI with nektos/act before pushing (see K_RELEASE_LOCAL_CI, K_RELEASE_LOCAL_CI_WORKFLOW)
436
+ - 8: Ensure trunk is up-to-date and reconcile with GitHub remote if needed
437
+ - 9: Push current branch to configured remotes (or default), force-pushing on retry when needed
438
+ - 10: Monitor CI after push (GitHub Actions and/or GitLab pipelines); progress bar; aborts on failure
439
+ - 11: Merge feature branch into trunk and push
440
+ - 12: Checkout trunk and pull latest
441
+ - 13: Signing checks and guidance (abort when signing enabled but cert missing); respect SKIP_GEM_SIGNING
442
+ - 14: Build gem (honors SKIP_GEM_SIGNING via env prefix)
443
+ - 15: Generate and validate gem checksums (bin/gem_checksums)
444
+ - 16: Release via `bundle exec rake release` and validate checksums again
445
+ - 17: Create GitHub release from CHANGELOG when GITHUB_TOKEN present
446
+ - 18: Push git tags to remotes (to "all" remote only when present; otherwise to each remote)
447
+ - Examples:
406
448
  - After intermittent CI failure, restart from monitoring: `bundle exec kettle-release start_step=10`
449
+ - Tips:
450
+ - The commit message helper `exe/kettle-commit-msg` prefers project-local `.git-hooks` (then falls back to `~/.git-hooks`).
451
+ - The goalie file `commit-subjects-goalie.txt` controls when a footer is appended; customize `footer-template.erb.txt` as you like.
452
+
453
+ ### Changelog generator
407
454
 
408
- Tip: The commit message helper `exe/kettle-commit-msg` prefers project-local `.git-hooks` (then falls back to `~/.git-hooks`). The goalie file `commit-subjects-goalie.txt` controls when a footer is appended; customize `footer-template.erb.txt` as you like.
455
+ - Script: `exe/kettle-changelog` (run as `kettle-changelog`)
456
+ - 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.
457
+ - Prerequisites:
458
+ - `coverage/coverage.json` present (generate with: `K_SOUP_COV_FORMATTERS="json" bin/rspec`).
459
+ - `bin/yard` available (Bundler-installed), to compute documentation coverage.
460
+ - Usage:
461
+ - `kettle-changelog`
462
+ - Behavior:
463
+ - Reads version from the unique `lib/**/version.rb` in the project.
464
+ - Moves entries from the `[Unreleased]` section into a new `[#.#.#] - YYYY-MM-DD` section.
465
+ - Prepends 4 lines with TAG, line coverage, branch coverage, and percent documented.
466
+ - 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]`.
467
+
468
+ ### Pre-release checks
469
+
470
+ - Script: `exe/kettle-pre-release` (run as `kettle-pre-release`)
471
+ - Purpose: Run a suite of pre-release validations to catch avoidable mistakes (resumable by check number).
472
+ - Usage:
473
+ - `kettle-pre-release [--check-num N]`
474
+ - Short option: `kettle-pre-release -cN`
475
+ - Options:
476
+ - `--check-num N` Start from check number N (default: 1)
477
+ - Checks:
478
+ - 1) Validate that all image URLs referenced by Markdown files resolve (HTTP HEAD)
479
+
480
+ ### Commit message helper (git hook)
481
+
482
+ - Script: `exe/kettle-commit-msg` (run by git as `.git/hooks/commit-msg`)
483
+ - Purpose: Append a standardized footer and optionally enforce branch naming rules when configured.
484
+ - Usage:
485
+ - Git invokes this with the path to the commit message file: `kettle-commit-msg .git/COMMIT_EDITMSG`
486
+ - Install via `bundle exec rake kettle:dev:install` to copy hook templates into `.git-hooks` and wire them up.
487
+ - Behavior:
488
+ - When `GIT_HOOK_BRANCH_VALIDATE=jira`, validates the current branch matches the pattern: `^(hotfix|bug|feature|candy)/[0-9]{8,}-…`.
489
+ - If it matches and the commit message lacks the numeric ID, appends `[<type>][<id>]`.
490
+ - Always invokes `Kettle::Dev::GitCommitFooter.render` to potentially append a footer if allowed by the goalie.
491
+ - Prefers project-local `.git-hooks` templates; falls back to `~/.git-hooks`.
492
+ - Environment:
493
+ - `GIT_HOOK_BRANCH_VALIDATE` Branch rule (e.g., `jira`) or `false` to disable.
494
+ - `GIT_HOOK_FOOTER_APPEND` Enable footer auto-append when goalie allows (true/false).
495
+ - `GIT_HOOK_FOOTER_SENTINEL` Required marker to avoid duplicate appends when enabled.
496
+ - `GIT_HOOK_FOOTER_APPEND_DEBUG` Extra debug output in the footer template (true/false).
497
+
498
+ ### Project bootstrap installer
499
+
500
+ - Script: `exe/kettle-dev-setup` (run as `kettle-dev-setup`)
501
+ - Purpose: Bootstrap a host gem repository to use kettle-dev’s tooling without manual steps.
502
+ - Usage:
503
+ - `kettle-dev-setup [options] [passthrough args]`
504
+ - Options (mapped through to `rake kettle:dev:install`):
505
+ - `--allowed=VAL` Pass `allowed=VAL` to acknowledge prior direnv allow, etc.
506
+ - `--force` Pass `force=true` to accept prompts non-interactively.
507
+ - `--hook_templates=VAL` Pass `hook_templates=VAL` to control git hook templating.
508
+ - `--only=VAL` Pass `only=VAL` to restrict install scope.
509
+ - `-h`, `--help` Show help.
510
+ - Behavior:
511
+ - Verifies a clean git working tree, presence of a Gemfile and a gemspec.
512
+ - Syncs development dependencies from this gem’s example gemspec into the target gemspec (replacing or inserting `add_development_dependency` lines as needed).
513
+ - Ensures `bin/setup` exists (copies from gem if missing) and replaces/creates the project’s `Rakefile` from `Rakefile.example`.
514
+ - Runs `bin/setup`, then `bundle exec bundle binstubs --all`.
515
+ - Stages and commits any bootstrap changes with message: `🎨 Template bootstrap by kettle-dev-setup v<version>`.
516
+ - Executes `bin/rake kettle:dev:install` with the parsed passthrough args.
409
517
 
410
518
  ### Open Collective README updater
411
519
 
412
- - Script: `exe/kettle-readme-backers`
520
+ - Script: `exe/kettle-readme-backers` (run as `kettle-readme-backers`)
413
521
  - Purpose: Updates README sections for Open Collective backers (individuals) and sponsors (organizations) by fetching live data from your collective.
414
522
  - Tags updated in README.md (first match wins for backers):
415
523
  - The default tag prefix is `OPENCOLLECTIVE`, and it is configurable:
@@ -421,7 +529,7 @@ Tip: The commit message helper `exe/kettle-commit-msg` prefers project-local `.g
421
529
  - Sponsors (Organizations): `<!-- <TAG>-ORGANIZATIONS:START --> … <!-- <TAG>-ORGANIZATIONS:END -->`
422
530
  - Handle resolution:
423
531
  1. `OPENCOLLECTIVE_HANDLE` environment variable, if set
424
- 2. `opencollective.yml` in the project root (`collective: "kettle-rb"` by default in this repo)
532
+ 2. `opencollective.yml` in the project root (e.g., `collective: "kettle-rb"` in this repo)
425
533
  - Usage:
426
534
  - `exe/kettle-readme-backers`
427
535
  - `OPENCOLLECTIVE_HANDLE=my-collective exe/kettle-readme-backers`
@@ -434,7 +542,9 @@ Tip: The commit message helper `exe/kettle-commit-msg` prefers project-local `.g
434
542
  - Or via .opencollective.yml: set `readme-backers-commit-subject: "💸 Thanks 🙏 to our new backers 🎒 and subscribers 📜"`.
435
543
  - Precedence: ENV overrides .opencollective.yml; if neither is set, a sensible default is used.
436
544
  - Note: When used with the provided `.git-hooks`, the subject should start with a gitmoji character (see [gitmoji][📌gitmoji]).
437
- - Tip: Run this locally before committing to keep your README current, or schedule it in CI to refresh periodically.
545
+ - Tip:
546
+ - Run this locally before committing to keep your README current, or schedule it in CI to refresh periodically.
547
+ - It runs automatically on a once-a-week schedule by the .github/workflows/opencollective.yml workflow that is part of the kettle-dev template.
438
548
 
439
549
  ## 🦷 FLOSS Funding
440
550
 
@@ -640,11 +750,11 @@ Thanks for RTFM. ☺️
640
750
  [🖇sponsor]: https://github.com/sponsors/pboling
641
751
  [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
642
752
  [🖇polar]: https://polar.sh/pboling
643
- [🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat
753
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
644
754
  [🖇kofi]: https://ko-fi.com/O5O86SNP4
645
755
  [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
646
756
  [🖇patreon]: https://patreon.com/galtzo
647
- [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat
757
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
648
758
  [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff
649
759
  [🖇buyme]: https://www.buymeacoffee.com/pboling
650
760
  [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
@@ -657,7 +767,7 @@ Thanks for RTFM. ☺️
657
767
 
658
768
  [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
659
769
  [⛳️gem-namespace]: https://github.com/kettle-rb/kettle-dev
660
- [⛳️namespace-img]: https://img.shields.io/badge/namespace-Kettle%3A%3ADev-3C2D2D.svg?style=square&logo=ruby&logoColor=white
770
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-Kettle::Dev-3C2D2D.svg?style=square&logo=ruby&logoColor=white
661
771
  [⛳️gem-name]: https://rubygems.org/gems/kettle-dev
662
772
  [⛳️name-img]: https://img.shields.io/badge/name-kettle--dev-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
663
773
  [⛳️tag-img]: https://img.shields.io/github/tag/kettle-rb/kettle-dev.svg
@@ -673,7 +783,7 @@ Thanks for RTFM. ☺️
673
783
  [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
674
784
  [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
675
785
  [💖🐘ruby-mast]: https://ruby.social/@galtzo
676
- [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https%3A%2F%2Fruby.social&style=flat&logo=mastodon&label=Ruby%20%40galtzo
786
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
677
787
  [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
678
788
  [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
679
789
  [💖🌳linktree]: https://linktr.ee/galtzo
@@ -793,9 +903,9 @@ Thanks for RTFM. ☺️
793
903
  [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
794
904
  [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
795
905
  [📌gitmoji]:https://gitmoji.dev
796
- [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square
906
+ [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
797
907
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
798
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.819-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
908
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-3.322-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
799
909
  [🔐security]: SECURITY.md
800
910
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
801
911
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -809,7 +919,7 @@ Thanks for RTFM. ☺️
809
919
  [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
810
920
  [💎SHA_checksums]: https://gitlab.com/kettle-rb/kettle-dev/-/tree/main/checksums
811
921
  [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
812
- [💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
922
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
813
923
  [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
814
924
  [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
815
925
  [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
data/README.md.example CHANGED
@@ -345,11 +345,11 @@ Thanks for RTFM. ☺️
345
345
  [🖇sponsor]: https://github.com/sponsors/pboling
346
346
  [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
347
347
  [🖇polar]: https://polar.sh/pboling
348
- [🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat
348
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
349
349
  [🖇kofi]: https://ko-fi.com/O5O86SNP4
350
350
  [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
351
351
  [🖇patreon]: https://patreon.com/galtzo
352
- [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat
352
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
353
353
  [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff
354
354
  [🖇buyme]: https://www.buymeacoffee.com/pboling
355
355
  [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
@@ -362,7 +362,7 @@ Thanks for RTFM. ☺️
362
362
 
363
363
  [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
364
364
  [⛳️gem-namespace]: https://github.com/kettle-rb/kettle-dev
365
- [⛳️namespace-img]: https://img.shields.io/badge/namespace-Kettle%3A%3ADev-3C2D2D.svg?style=square&logo=ruby&logoColor=white
365
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-Kettle::Dev-3C2D2D.svg?style=square&logo=ruby&logoColor=white
366
366
  [⛳️gem-name]: https://rubygems.org/gems/kettle-dev
367
367
  [⛳️name-img]: https://img.shields.io/badge/name-kettle--dev-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
368
368
  [⛳️tag-img]: https://img.shields.io/github/tag/kettle-rb/kettle-dev.svg
@@ -378,7 +378,7 @@ Thanks for RTFM. ☺️
378
378
  [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
379
379
  [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
380
380
  [💖🐘ruby-mast]: https://ruby.social/@galtzo
381
- [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https%3A%2F%2Fruby.social&style=flat&logo=mastodon&label=Ruby%20%40galtzo
381
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
382
382
  [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
383
383
  [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
384
384
  [💖🌳linktree]: https://linktr.ee/galtzo
@@ -503,9 +503,9 @@ Thanks for RTFM. ☺️
503
503
  [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
504
504
  [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
505
505
  [📌gitmoji]:https://gitmoji.dev
506
- [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square
506
+ [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
507
507
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
508
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.819-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
508
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-3.322-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
509
509
  [🔐security]: SECURITY.md
510
510
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
511
511
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -519,7 +519,7 @@ Thanks for RTFM. ☺️
519
519
  [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
520
520
  [💎SHA_checksums]: https://gitlab.com/kettle-rb/kettle-dev/-/tree/main/checksums
521
521
  [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
522
- [💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
522
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
523
523
  [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
524
524
  [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
525
525
  [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
data/Rakefile.example CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # kettle-dev Rakefile v1.1.4 - 2025-09-02
3
+ # kettle-dev Rakefile v1.1.5 - 2025-09-05
4
4
  # Ruby 2.3 (Safe Navigation) or higher required
5
5
  #
6
6
  # MIT License (see License.txt)
data/exe/kettle-changelog CHANGED
@@ -21,8 +21,13 @@
21
21
 
22
22
  $stdout.sync = true
23
23
 
24
- # Depending library or project must be using bundler
25
- require "bundler/setup"
24
+ # Do not rely on Bundler; allow running in repos that do not depend on kettle-dev
25
+ # Ensure RubyGems is available for 'require' lookups
26
+ begin
27
+ require "rubygems"
28
+ rescue LoadError
29
+ # Older Rubies always have rubygems; continue anyway
30
+ end
26
31
 
27
32
  script_basename = File.basename(__FILE__)
28
33