kettle-dev 2.2.18 → 2.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f361805b0355ac14c6b5a3f5d2555feb722b8c640a2550f46d2a8f7ab0c80c6
4
- data.tar.gz: a39ee59b4404715e976240bca10e818f9b2b85e88575bac566ba02cd1116c4c9
3
+ metadata.gz: 309dfdff5a98f7d5d2f189a3b51a4d0f231d037b61ea37023918a70ec436d997
4
+ data.tar.gz: 9dff167d60de601c34738beb35c81df5e3c1a8874630ccaebf753507fa205a41
5
5
  SHA512:
6
- metadata.gz: af5802350e819dcf37618a8cc3eac5c1ee98ad1e8f14f3e724ac1083875746139565ee34ccd697d6dd5c8950d2bf17e58b4b98416014a190cde2e62bd316df09
7
- data.tar.gz: 7407dd36a674f8271b645e2bb97c3b84a15461cd14010e870f1036a53ebfb8ba00d959a341694c43ae1d8cf884d97d1a758815080f90fc4e65aebc46579668a2
6
+ metadata.gz: baf9a43aeac7238588295facc22c7a151c68abeed3b754872d539bc25571ea43e87eaac9ffb81ea4f5133206d1e9f1d0ef7d2fc609b666fa0bfad54df27069d0
7
+ data.tar.gz: 6f607059c8cd545bad791de6277f40f0b75d956fbc7654677cdcfb53345c2b658e98881e80f694992041e872e96b4e643d69f61a578ca305821fe449fe6c21ae
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,20 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [2.2.19] - 2026-06-26
34
+
35
+ - TAG: [v2.2.19][2.2.19t]
36
+ - COVERAGE: 91.75% -- 4082/4449 lines in 33 files
37
+ - BRANCH COVERAGE: 72.94% -- 1615/2214 branches in 33 files
38
+ - 61.84% documented
39
+
40
+ ### Changed
41
+
42
+ - `kettle-release` now runs `bin/rake appraisal:generate` by default when
43
+ `Appraisals` is present; use `--appraisal-update` or
44
+ `KETTLE_RELEASE_APPRAISAL_TASK=appraisal:update` for the slower lock-resolving
45
+ update path.
46
+
33
47
  ## [2.2.18] - 2026-06-24
34
48
 
35
49
  - TAG: [v2.2.18][2.2.18t]
@@ -2279,7 +2293,9 @@ Please file a bug if you notice a violation of semantic versioning.
2279
2293
  - Selecting will run the selected workflow via `act`
2280
2294
  - This may move to its own gem in the future.
2281
2295
 
2282
- [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.18...HEAD
2296
+ [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.19...HEAD
2297
+ [2.2.19]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.18...v2.2.19
2298
+ [2.2.19t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.2.19
2283
2299
  [2.2.18]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.17...v2.2.18
2284
2300
  [2.2.18t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.2.18
2285
2301
  [2.2.17]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.16...v2.2.17
data/CONTRIBUTING.md CHANGED
@@ -131,9 +131,12 @@ toolchain, and it may be higher than the gemspec runtime floor.
131
131
  They are created and updated with the commands:
132
132
 
133
133
  ```console
134
- bin/rake appraisal:update
134
+ bin/rake appraisal:generate
135
135
  ```
136
136
 
137
+ Use `bin/rake appraisal:update` when you intentionally need to resolve fresh
138
+ appraisal locks.
139
+
137
140
  If you need to reset all gemfiles/*.gemfile.lock files:
138
141
 
139
142
  ```console
data/README.md CHANGED
@@ -874,7 +874,7 @@ Thanks for RTFM. ☺️
874
874
  [📌gitmoji]: https://gitmoji.dev
875
875
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
876
876
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
877
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-4.446-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
877
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-4.449-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
878
878
  [🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
879
879
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
880
880
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
data/exe/kettle-changelog CHANGED
@@ -52,59 +52,57 @@ rescue LoadError => e
52
52
  exit(1)
53
53
  end
54
54
 
55
- begin
56
- if ARGV.include?("-h") || ARGV.include?("--help")
57
- puts <<~USAGE
58
- Usage: kettle-changelog [--version VERSION] [--update-prep] [--pending-release] [--release-state] [--add-unreleased-entry --section SECTION --entry TEXT] [--json] [--no-strict] [--no-coverage-threshold]
59
-
60
- Detects the current version from lib/**/version.rb, the latest live release, and
61
- the most recent CHANGELOG.md release section, then prompts to confirm the selected plan:
62
- create a new release section, update the prepared release section in place, or reformat only.
63
-
64
- Release plans add coverage and documentation stats, move entries from [Unreleased],
65
- and update bottom link references to GitHub style.
66
-
67
- Options:
68
- --version VERSION Use this version instead of detecting VERSION from lib/**/version.rb
69
- --update-prep Force updating the most recent prepared release section in place
70
- --pending-release Query whether the changelog has release work pending; exits 0 for yes, 1 for no
71
- --release-state,
72
- --release-status Print changelog release state, including latest published release and pending sources
73
- --add-unreleased-entry Add one entry to an existing section under ## [Unreleased]
74
- --section SECTION Unreleased section to receive the entry (Added, Changed, Deprecated, Removed, Fixed, Security)
75
- --entry TEXT Changelog entry text; "- " is added when omitted
76
- --json Print query output as JSON
77
- --no-strict Allow missing coverage and yard data (warnings only, no errors)
78
- --no-coverage-threshold Generate coverage without hard-failing below configured thresholds
79
-
80
- Environment:
81
- K_CHANGELOG_STRICT=false Disable strict mode (equivalent to --no-strict flag)
82
- K_CHANGELOG_COVERAGE_HARD=false Disable coverage threshold hard-failure
83
- K_CHANGELOG_VERSION_FILE=path Read VERSION from this file instead of lib/**/version.rb
84
-
85
- Data generation:
86
- Strict mode is the default. Release plans remove stale coverage output,
87
- run bundle exec kettle-test with JSON coverage enabled, read the resulting
88
- coverage/coverage.json, and collect documentation stats from bin/rake yard
89
- or bin/yard.
90
-
91
- Strict mode fails if specs fail, coverage JSON is not produced, coverage
92
- is below the configured project thresholds, or documentation stats cannot
93
- be collected.
94
-
95
- Non-strict mode does not generate missing coverage or documentation data;
96
- it warns and leaves unavailable stats blank.
97
-
98
- Runtime requirements:
99
- - bundle exec kettle-test available for strict coverage generation
100
- - bin/rake yard or bin/yard available for strict documentation stats
101
-
102
- Use --no-strict or K_CHANGELOG_STRICT=false to allow missing data.
103
- Use --no-coverage-threshold or K_CHANGELOG_COVERAGE_HARD=false to run fresh
104
- coverage without hard-failing below configured thresholds.
105
- USAGE
106
- exit(0)
107
- end
55
+ if ARGV.include?("-h") || ARGV.include?("--help")
56
+ puts <<~USAGE
57
+ Usage: kettle-changelog [--version VERSION] [--update-prep] [--pending-release] [--release-state] [--add-unreleased-entry --section SECTION --entry TEXT] [--json] [--no-strict] [--no-coverage-threshold]
58
+
59
+ Detects the current version from lib/**/version.rb, the latest live release, and
60
+ the most recent CHANGELOG.md release section, then prompts to confirm the selected plan:
61
+ create a new release section, update the prepared release section in place, or reformat only.
62
+
63
+ Release plans add coverage and documentation stats, move entries from [Unreleased],
64
+ and update bottom link references to GitHub style.
65
+
66
+ Options:
67
+ --version VERSION Use this version instead of detecting VERSION from lib/**/version.rb
68
+ --update-prep Force updating the most recent prepared release section in place
69
+ --pending-release Query whether the changelog has release work pending; exits 0 for yes, 1 for no
70
+ --release-state,
71
+ --release-status Print changelog release state, including latest published release and pending sources
72
+ --add-unreleased-entry Add one entry to an existing section under ## [Unreleased]
73
+ --section SECTION Unreleased section to receive the entry (Added, Changed, Deprecated, Removed, Fixed, Security)
74
+ --entry TEXT Changelog entry text; "- " is added when omitted
75
+ --json Print query output as JSON
76
+ --no-strict Allow missing coverage and yard data (warnings only, no errors)
77
+ --no-coverage-threshold Generate coverage without hard-failing below configured thresholds
78
+
79
+ Environment:
80
+ K_CHANGELOG_STRICT=false Disable strict mode (equivalent to --no-strict flag)
81
+ K_CHANGELOG_COVERAGE_HARD=false Disable coverage threshold hard-failure
82
+ K_CHANGELOG_VERSION_FILE=path Read VERSION from this file instead of lib/**/version.rb
83
+
84
+ Data generation:
85
+ Strict mode is the default. Release plans remove stale coverage output,
86
+ run bundle exec kettle-test with JSON coverage enabled, read the resulting
87
+ coverage/coverage.json, and collect documentation stats from bin/rake yard
88
+ or bin/yard.
89
+
90
+ Strict mode fails if specs fail, coverage JSON is not produced, coverage
91
+ is below the configured project thresholds, or documentation stats cannot
92
+ be collected.
93
+
94
+ Non-strict mode does not generate missing coverage or documentation data;
95
+ it warns and leaves unavailable stats blank.
96
+
97
+ Runtime requirements:
98
+ - bundle exec kettle-test available for strict coverage generation
99
+ - bin/rake yard or bin/yard available for strict documentation stats
100
+
101
+ Use --no-strict or K_CHANGELOG_STRICT=false to allow missing data.
102
+ Use --no-coverage-threshold or K_CHANGELOG_COVERAGE_HARD=false to run fresh
103
+ coverage without hard-failing below configured thresholds.
104
+ USAGE
105
+ exit(0)
108
106
  end
109
107
 
110
108
  begin
data/exe/kettle-release CHANGED
@@ -43,7 +43,7 @@ end
43
43
  # Do not guard with __FILE__ == $PROGRAM_NAME because binstubs use Kernel.load.
44
44
  if ARGV.include?("-h") || ARGV.include?("--help")
45
45
  puts <<~USAGE
46
- Usage: kettle-release [--version VERSION] [--local-ci] [start_step=<0-19>]
46
+ Usage: kettle-release [--version VERSION] [--local-ci] [--appraisal-update] [start_step=<0-19>]
47
47
 
48
48
  Automates the release flow for a Ruby gem in the host project.
49
49
 
@@ -58,7 +58,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
58
58
  2. Detect version; RubyGems sanity check; confirm CHANGELOG/version; sync copyright years; update badges/headers
59
59
  3. Run bin/setup
60
60
  4. Run bin/rake (default task)
61
- 5. Run bin/rake appraisal:update if Appraisals present
61
+ 5. Run bin/rake appraisal:generate if Appraisals present
62
62
  6. Ensure git user configured; commit release prep
63
63
  7. Optional local CI with `act` (controlled by K_RELEASE_LOCAL_CI)
64
64
  8. Ensure trunk in sync across remotes; rebase feature as needed
@@ -77,6 +77,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
77
77
  Options:
78
78
  start_step=<number> # Begin at the numbered step above (e.g., 10 to resume at CI monitoring)
79
79
  --version VERSION # Use this version instead of detecting VERSION from lib/**/version.rb
80
+ --appraisal-update # Use slower appraisal:update instead of default appraisal:generate
80
81
  --local-ci # Sensitive release mode: run act locally, publish before any git push,
81
82
  # create the git tag locally, then push commits and tags after publish
82
83
 
@@ -85,6 +86,8 @@ if ARGV.include?("-h") || ARGV.include?("--help")
85
86
  GEM_CERT_USER=<user> # Select certs/<user>.pem for signing
86
87
  K_RELEASE_LOCAL_CI=ask|1|0 # Use 'act' locally before push; 'ask' prompts, '1' forces, default off
87
88
  K_RELEASE_LOCAL_CI_WORKFLOW # Name of workflow (without .yml) for local CI; defaults to locked_deps or first
89
+ KETTLE_RELEASE_APPRAISAL_TASK=appraisal:update
90
+ # Use slower appraisal:update instead of default appraisal:generate
88
91
  GITHUB_TOKEN / GH_TOKEN # Optional; enables GitHub release creation and API queries
89
92
  GITLAB_TOKEN / GL_TOKEN # Optional; enables GitLab API queries when applicable
90
93
  DEBUG=true # Print backtraces on errors
@@ -119,12 +122,13 @@ def extract_version_arg!(argv)
119
122
  end
120
123
 
121
124
  local_ci = ARGV.include?("--local-ci")
125
+ appraisal_task = ARGV.delete("--appraisal-update") ? "appraisal:update" : nil
122
126
  start_step_arg = ARGV.find { |a| a.start_with?("start_step=") }
123
127
  start_step = start_step_arg ? start_step_arg.split("=", 2)[1].to_i : 0
124
128
  version_override = extract_version_arg!(ARGV)
125
129
 
126
130
  begin
127
- Kettle::Dev::ReleaseCLI.new(start_step: start_step, local_ci: local_ci, version: version_override).run
131
+ Kettle::Dev::ReleaseCLI.new(start_step: start_step, local_ci: local_ci, version: version_override, appraisal_task: appraisal_task).run
128
132
  rescue LoadError => e
129
133
  warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
130
134
  warn(Array(e.backtrace).join("\n")) if ENV["DEBUG"]
@@ -297,13 +297,13 @@ module Kettle
297
297
  end
298
298
  # Small initial delay to allow GitHub to register the newly pushed commit and enqueue workflows.
299
299
  # Configurable via K_RELEASE_CI_INITIAL_SLEEP (seconds); defaults to 3s.
300
- begin
301
- initial_sleep = begin
302
- Integer(ENV["K_RELEASE_CI_INITIAL_SLEEP"])
303
- rescue
304
- nil
305
- end
300
+
301
+ initial_sleep = begin
302
+ Integer(ENV["K_RELEASE_CI_INITIAL_SLEEP"])
303
+ rescue
304
+ nil
306
305
  end
306
+
307
307
  sleep((initial_sleep && initial_sleep >= 0) ? initial_sleep : 3)
308
308
  start_timeout = github_start_timeout
309
309
  poll_interval = github_poll_interval
@@ -6,7 +6,6 @@ require "net/http"
6
6
  require "open3"
7
7
  require "optparse"
8
8
  require "pathname"
9
- require "set"
10
9
  require "time"
11
10
  require "uri"
12
11
 
@@ -265,11 +264,9 @@ module Kettle
265
264
  @options[:progress] = bool
266
265
  end
267
266
  opt.on("--skip-pattern PATTERN", "Skip workflow paths matching pattern (repeatable)") do |pattern|
268
- begin
269
- @options[:reject_patterns] << Regexp.new(pattern)
270
- rescue RegexpError => e
271
- Kettle::Dev::ExitAdapter.abort("Invalid --skip-pattern #{pattern.inspect}: #{e.message}")
272
- end
267
+ @options[:reject_patterns] << Regexp.new(pattern)
268
+ rescue RegexpError => e
269
+ Kettle::Dev::ExitAdapter.abort("Invalid --skip-pattern #{pattern.inspect}: #{e.message}")
273
270
  end
274
271
  opt.on("--[no-]validate", "Validate YAML after editing") do |bool|
275
272
  @options[:validate] = bool
@@ -285,27 +282,25 @@ module Kettle
285
282
  def load_workflows(paths, state)
286
283
  file_progress = progress_bar(title: "Files", total: paths.length)
287
284
  paths.each_with_object([]) do |path, workflows|
288
- begin
289
- state[:files_scanned] += 1
290
- text = begin
291
- File.read(path)
292
- rescue Errno::EACCES => e
293
- record_failure(state, path: path, error: "read_error: #{e.message}")
294
- next
295
- end
296
-
297
- parsed = begin
298
- Psych.parse_stream(text)
299
- rescue Psych::Exception => e
300
- record_failure(state, path: path, error: "yaml_parse_error: #{e.message}")
301
- next
302
- end
285
+ state[:files_scanned] += 1
286
+ text = begin
287
+ File.read(path)
288
+ rescue Errno::EACCES => e
289
+ record_failure(state, path: path, error: "read_error: #{e.message}")
290
+ next
291
+ end
303
292
 
304
- uses_nodes = extract_uses_nodes(parsed, text)
305
- workflows << {path: path, text: text, uses_nodes: uses_nodes} unless uses_nodes.empty?
306
- ensure
307
- file_progress&.increment
293
+ parsed = begin
294
+ Psych.parse_stream(text)
295
+ rescue Psych::Exception => e
296
+ record_failure(state, path: path, error: "yaml_parse_error: #{e.message}")
297
+ next
308
298
  end
299
+
300
+ uses_nodes = extract_uses_nodes(parsed, text)
301
+ workflows << {path: path, text: text, uses_nodes: uses_nodes} unless uses_nodes.empty?
302
+ ensure
303
+ file_progress&.increment
309
304
  end
310
305
  end
311
306
 
@@ -53,26 +53,24 @@ module Kettle
53
53
  # Create a new adapter rooted at the current working directory.
54
54
  # @return [void]
55
55
  def initialize
56
- begin
57
- # Allow users/CI to opt out of using the 'git' gem even when available.
58
- # Set KETTLE_DEV_DISABLE_GIT_GEM to a truthy value ("1", "true", "yes") to force CLI backend.
59
- env_val = ENV["KETTLE_DEV_DISABLE_GIT_GEM"]
60
- # Ruby 2.3 compatibility: String#match? was added in 2.4; use Regexp#=== / =~ instead
61
- disable_gem = env_val && !!(/\A(1|true|yes)\z/i =~ env_val)
62
- if disable_gem
63
- @backend = :cli
64
- else
65
- Kernel.require "git"
66
- @backend = :gem
67
- @git = ::Git.open(Dir.pwd)
68
- end
69
- rescue LoadError => e
70
- Kettle::Dev.debug_error(e, __method__, backtrace: false)
71
- # Optional dependency: fall back to CLI
56
+ # Allow users/CI to opt out of using the 'git' gem even when available.
57
+ # Set KETTLE_DEV_DISABLE_GIT_GEM to a truthy value ("1", "true", "yes") to force CLI backend.
58
+ env_val = ENV["KETTLE_DEV_DISABLE_GIT_GEM"]
59
+ # Ruby 2.3 compatibility: String#match? was added in 2.4; use Regexp#=== / =~ instead
60
+ disable_gem = env_val && !!(/\A(1|true|yes)\z/i =~ env_val)
61
+ if disable_gem
72
62
  @backend = :cli
73
- rescue => e
74
- raise Kettle::Dev::Error, "Failed to open git repository: #{e.message}"
63
+ else
64
+ Kernel.require "git"
65
+ @backend = :gem
66
+ @git = ::Git.open(Dir.pwd)
75
67
  end
68
+ rescue LoadError => e
69
+ Kettle::Dev.debug_error(e, __method__, backtrace: false)
70
+ # Optional dependency: fall back to CLI
71
+ @backend = :cli
72
+ rescue => e
73
+ raise Kettle::Dev::Error, "Failed to open git repository: #{e.message}"
76
74
  end
77
75
 
78
76
  # Push a branch to a remote.
@@ -200,12 +198,10 @@ module Kettle
200
198
  def remotes_with_urls
201
199
  if @backend == :gem
202
200
  @git.remotes.each_with_object({}) do |r, h|
203
- begin
204
- h[r.name] = r.url
205
- rescue => e
206
- Kettle::Dev.debug_error(e, __method__)
207
- # ignore
208
- end
201
+ h[r.name] = r.url
202
+ rescue => e
203
+ Kettle::Dev.debug_error(e, __method__)
204
+ # ignore
209
205
  end
210
206
  else
211
207
  out, status = Open3.capture2("git", "remote", "-v")
@@ -5,7 +5,7 @@ module Kettle
5
5
  class GitCommitFooter
6
6
  # Regex to extract `name = "value"` assignments from a gemspec.
7
7
  # @return [Regexp]
8
- NAME_ASSIGNMENT_REGEX = /\bname\s*=\s*(["'])([^"']+)\1/.freeze
8
+ NAME_ASSIGNMENT_REGEX = /\bname\s*=\s*(["'])([^"']+)\1/
9
9
 
10
10
  # Whether footer appending is enabled (via GIT_HOOK_FOOTER_APPEND=true)
11
11
  # @return [Boolean]
@@ -44,14 +44,14 @@ module Kettle
44
44
 
45
45
  ypath = yaml_path(root)
46
46
  if strict
47
- yml = YAML.safe_load(File.read(ypath))
47
+ yml = YAML.safe_load_file(ypath)
48
48
  if yml.is_a?(Hash)
49
49
  handle = yml["collective"] || yml[:collective] || yml["org"] || yml[:org]
50
50
  return handle.to_s unless handle.nil? || handle.to_s.strip.empty? || handle.to_s.match?(/\{KJ\|[^}]+}/)
51
51
  end
52
52
  elsif File.file?(ypath)
53
53
  begin
54
- yml = YAML.safe_load(File.read(ypath))
54
+ yml = YAML.safe_load_file(ypath)
55
55
  if yml.is_a?(Hash)
56
56
  handle = yml["collective"] || yml[:collective] || yml["org"] || yml[:org]
57
57
  return handle.to_s unless handle.nil? || handle.to_s.strip.empty? || handle.to_s.match?(/\{KJ\|[^}]+}/)
@@ -253,12 +253,10 @@ module Kettle
253
253
  Array(glob_pattern)
254
254
  end
255
255
  urls = files.flat_map do |f|
256
- begin
257
- extract_image_urls_from_text(File.read(f))
258
- rescue => e
259
- warn("[kettle-pre-release] Could not read #{Kettle::Dev.display_path(f)}: #{e.class}: #{e.message}")
260
- []
261
- end
256
+ extract_image_urls_from_text(File.read(f))
257
+ rescue => e
258
+ warn("[kettle-pre-release] Could not read #{Kettle::Dev.display_path(f)}: #{e.class}: #{e.message}")
259
+ []
262
260
  end
263
261
  urls.uniq
264
262
  end
@@ -33,20 +33,18 @@ begin
33
33
  end
34
34
 
35
35
  run_appraisal_task = lambda do |task_name, primary_steps = nil|
36
- begin
37
- if primary_steps
38
- begin
39
- primary_steps.call
40
- rescue RuntimeError => e
41
- warn("[kettle-dev][#{task_name}] #{e.message}; falling back to appraisal:generate")
42
- run_generate_steps.call
43
- end
44
- else
36
+ if primary_steps
37
+ begin
38
+ primary_steps.call
39
+ rescue RuntimeError => e
40
+ warn("[kettle-dev][#{task_name}] #{e.message}; falling back to appraisal:generate")
45
41
  run_generate_steps.call
46
42
  end
47
- rescue RuntimeError => e
48
- abort(e.message)
43
+ else
44
+ run_generate_steps.call
49
45
  end
46
+ rescue RuntimeError => e
47
+ abort(e.message)
50
48
  end
51
49
 
52
50
  desc("Install Appraisal gemfiles (initial setup for projects that didn't previously use Appraisal)")
@@ -159,13 +157,11 @@ begin
159
157
  else
160
158
  failures = []
161
159
  locks.each do |f|
162
- begin
163
- File.delete(f)
164
- rescue Errno::ENOENT
165
- # Ignore if already gone
166
- rescue => e
167
- failures << [f, e]
168
- end
160
+ File.delete(f)
161
+ rescue Errno::ENOENT
162
+ # Ignore if already gone
163
+ rescue => e
164
+ failures << [f, e]
169
165
  end
170
166
 
171
167
  unless failures.empty?
@@ -5,7 +5,6 @@ require "yaml"
5
5
  require "json"
6
6
  require "uri"
7
7
  require "net/http"
8
- require "set"
9
8
 
10
9
  module Kettle
11
10
  module Dev
@@ -244,7 +243,7 @@ module Kettle
244
243
 
245
244
  if File.file?(OC_YML_PATH)
246
245
  begin
247
- yml = YAML.safe_load(File.read(OC_YML_PATH))
246
+ yml = YAML.safe_load_file(OC_YML_PATH)
248
247
  if yml.is_a?(Hash)
249
248
  from_yml = yml["readme-osc-tag"] || yml[:"readme-osc-tag"]
250
249
  from_yml = from_yml.to_s if from_yml
@@ -660,7 +659,7 @@ module Kettle
660
659
 
661
660
  if File.file?(OC_YML_PATH)
662
661
  begin
663
- yml = YAML.safe_load(File.read(OC_YML_PATH))
662
+ yml = YAML.safe_load_file(OC_YML_PATH)
664
663
  if yml.is_a?(Hash)
665
664
  from_yml = yml["readme-backers-commit-subject"] || yml[:"readme-backers-commit-subject"]
666
665
  from_yml = from_yml.to_s if from_yml
@@ -72,13 +72,14 @@ module Kettle
72
72
 
73
73
  public
74
74
 
75
- def initialize(start_step: 0, local_ci: false, version: nil)
75
+ def initialize(start_step: 0, local_ci: false, version: nil, appraisal_task: nil)
76
76
  @root = Kettle::Dev::CIHelpers.project_root
77
77
  @git = Kettle::Dev::GitAdapter.new
78
78
  @start_step = (start_step || 0).to_i
79
79
  @start_step = 0 if @start_step < 0
80
80
  @local_ci = !!local_ci
81
81
  @version_override = Kettle::Dev::Versioning.normalize_explicit_version(version)
82
+ @appraisal_task = normalize_appraisal_task(appraisal_task || ENV["KETTLE_RELEASE_APPRAISAL_TASK"])
82
83
  end
83
84
 
84
85
  def run
@@ -190,14 +191,14 @@ module Kettle
190
191
  # 4. bin/rake
191
192
  run_cmd!("bin/rake") if @start_step <= 4
192
193
 
193
- # 5. appraisal:update (optional) + canonical docs build
194
+ # 5. appraisal:generate (optional) + canonical docs build
194
195
  if @start_step <= 5
195
196
  appraisals_path = File.join(@root, "Appraisals")
196
197
  if File.file?(appraisals_path)
197
- puts "Appraisals detected at #{Kettle::Dev.display_path(appraisals_path)}. Running: bin/rake appraisal:update"
198
- run_cmd!("bin/rake appraisal:update")
198
+ puts "Appraisals detected at #{Kettle::Dev.display_path(appraisals_path)}. Running: bin/rake #{@appraisal_task}"
199
+ run_cmd!("bin/rake #{@appraisal_task}")
199
200
  else
200
- puts "No Appraisals file found; skipping appraisal:update"
201
+ puts "No Appraisals file found; skipping #{@appraisal_task}"
201
202
  end
202
203
 
203
204
  puts "Generating docs site via canonical task: bin/rake yard"
@@ -320,6 +321,15 @@ module Kettle
320
321
  end
321
322
  end
322
323
 
324
+ def normalize_appraisal_task(value)
325
+ task = value.to_s.strip
326
+ return "appraisal:generate" if task.empty?
327
+ return "appraisal:generate" if task == "generate" || task == "appraisal:generate"
328
+ return "appraisal:update" if task == "update" || task == "appraisal:update"
329
+
330
+ abort("Unsupported appraisal task #{value.inspect}; use appraisal:generate or appraisal:update.")
331
+ end
332
+
323
333
  private
324
334
 
325
335
  def local_ci?
@@ -405,7 +415,6 @@ module Kettle
405
415
  # This helps ensure docs are kept in sync when bumping the years.
406
416
  # Aborts with a helpful message when they differ.
407
417
  def validate_copyright_years!
408
- require "set"
409
418
  readme = File.join(@root, "README.md")
410
419
  license = File.join(@root, "LICENSE.txt")
411
420
  unless File.file?(readme) && File.file?(license)
@@ -446,7 +455,6 @@ module Kettle
446
455
  # then parses four-digit years and year ranges like "2012-2015" (hyphen or en dash).
447
456
  # Returns Set[Integer].
448
457
  def extract_years_from_file(path)
449
- require "set"
450
458
  years = Set.new
451
459
  content = File.read(path)
452
460
  # Only consider lines that look like copyright notices to reduce false positives
@@ -91,48 +91,46 @@ module Kettle
91
91
 
92
92
  # Print GitLab pipeline status (if configured) for the current branch.
93
93
  print_gitlab_status = proc do
94
- begin
95
- branch = Kettle::Dev::CIHelpers.current_branch
96
- # Detect any GitLab remote (not just origin), mirroring CIMonitor behavior
97
- gl_remotes = Kettle::Dev::CIMonitor.gitlab_remote_candidates
98
- if gl_remotes.nil? || gl_remotes.empty? || branch.nil?
99
- puts "Latest GL (#{branch || "n/a"}) pipeline: n/a"
100
- next
101
- end
94
+ branch = Kettle::Dev::CIHelpers.current_branch
95
+ # Detect any GitLab remote (not just origin), mirroring CIMonitor behavior
96
+ gl_remotes = Kettle::Dev::CIMonitor.gitlab_remote_candidates
97
+ if gl_remotes.nil? || gl_remotes.empty? || branch.nil?
98
+ puts "Latest GL (#{branch || "n/a"}) pipeline: n/a"
99
+ next
100
+ end
102
101
 
103
- # Parse owner/repo from the first GitLab remote URL
104
- gl_url = Kettle::Dev::CIMonitor.remote_url(gl_remotes.first)
105
- owner = repo = nil
106
- if gl_url =~ %r{git@gitlab.com:(.+?)/(.+?)(\.git)?$}
107
- owner = Regexp.last_match(1)
108
- repo = Regexp.last_match(2).sub(/\.git\z/, "")
109
- elsif gl_url =~ %r{https://gitlab.com/(.+?)/(.+?)(\.git)?$}
110
- owner = Regexp.last_match(1)
111
- repo = Regexp.last_match(2).sub(/\.git\z/, "")
112
- end
102
+ # Parse owner/repo from the first GitLab remote URL
103
+ gl_url = Kettle::Dev::CIMonitor.remote_url(gl_remotes.first)
104
+ owner = repo = nil
105
+ if gl_url =~ %r{git@gitlab.com:(.+?)/(.+?)(\.git)?$}
106
+ owner = Regexp.last_match(1)
107
+ repo = Regexp.last_match(2).sub(/\.git\z/, "")
108
+ elsif gl_url =~ %r{https://gitlab.com/(.+?)/(.+?)(\.git)?$}
109
+ owner = Regexp.last_match(1)
110
+ repo = Regexp.last_match(2).sub(/\.git\z/, "")
111
+ end
113
112
 
114
- unless owner && repo
115
- puts "Latest GL (#{branch}) pipeline: n/a"
116
- next
117
- end
113
+ unless owner && repo
114
+ puts "Latest GL (#{branch}) pipeline: n/a"
115
+ next
116
+ end
118
117
 
119
- pipe = Kettle::Dev::CIHelpers.gitlab_latest_pipeline(owner: owner, repo: repo, branch: branch)
120
- if pipe
121
- st = pipe["status"].to_s
122
- status = if st == "success"
123
- "success"
124
- else
125
- ((st == "failed") ? "failure" : nil)
126
- end
127
- emoji = Kettle::Dev::CIMonitor.status_emoji(st, status)
128
- details = [st, pipe["failure_reason"]].compact.join("/")
129
- puts "Latest GL (#{branch}) pipeline: #{emoji} (#{details})"
118
+ pipe = Kettle::Dev::CIHelpers.gitlab_latest_pipeline(owner: owner, repo: repo, branch: branch)
119
+ if pipe
120
+ st = pipe["status"].to_s
121
+ status = if st == "success"
122
+ "success"
130
123
  else
131
- puts "Latest GL (#{branch}) pipeline: none"
124
+ ((st == "failed") ? "failure" : nil)
132
125
  end
133
- rescue => e
134
- puts "GL status: error #{e.class}: #{e.message}"
126
+ emoji = Kettle::Dev::CIMonitor.status_emoji(st, status)
127
+ details = [st, pipe["failure_reason"]].compact.join("/")
128
+ puts "Latest GL (#{branch}) pipeline: #{emoji} (#{details})"
129
+ else
130
+ puts "Latest GL (#{branch}) pipeline: none"
135
131
  end
132
+ rescue => e
133
+ puts "GL status: error #{e.class}: #{e.message}"
136
134
  end
137
135
 
138
136
  run_act_for = proc do |file_path|
@@ -264,12 +262,10 @@ module Kettle
264
262
  selected = nil
265
263
  input_thread = nil
266
264
  read_input = proc do
267
- begin
268
- selected = Kettle::Dev::InputAdapter.gets&.strip
269
- rescue StandardError, SystemExit, Interrupt => error
270
- puts "Error reading input: #{error.class}: #{error.message}" if Kettle::Dev::DEBUGGING
271
- selected = :input_error
272
- end
265
+ selected = Kettle::Dev::InputAdapter.gets&.strip
266
+ rescue StandardError, SystemExit, Interrupt => error
267
+ puts "Error reading input: #{error.class}: #{error.message}" if Kettle::Dev::DEBUGGING
268
+ selected = :input_error
273
269
  end
274
270
  if tty
275
271
  input_thread = Thread.new(&read_input) # rubocop:disable ThreadSafety/NewThread
@@ -283,54 +279,52 @@ module Kettle
283
279
 
284
280
  options.each do |code, file|
285
281
  workers << Thread.new(code, file, owner, repo, branch, token, start_at) do |c, f, ow, rp, br, tk, st_at| # rubocop:disable ThreadSafety/NewThread
286
- begin
287
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
288
- delay = 0.12 - (now - st_at)
289
- sleep(delay) if delay && delay > 0
290
-
291
- if ow.nil? || rp.nil? || br.nil?
292
- status_q << [c, f, "n/a"]
293
- Thread.exit
294
- end
295
- uri = URI("https://api.github.com/repos/#{ow}/#{rp}/actions/workflows/#{f}/runs?branch=#{URI.encode_www_form_component(br)}&per_page=1")
296
- poll_interval = Integer(ENV["CI_ACT_POLL_INTERVAL"] || 5)
297
- loop do
298
- begin
299
- req = Net::HTTP::Get.new(uri)
300
- req["User-Agent"] = "ci:act rake task"
301
- req["Authorization"] = "token #{tk}" if tk && !tk.empty?
302
- res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
303
- if res.is_a?(Net::HTTPSuccess)
304
- data = JSON.parse(res.body)
305
- run = data["workflow_runs"]&.first
306
- if run
307
- st = run["status"]
308
- con = run["conclusion"]
309
- emoji = Kettle::Dev::CIMonitor.status_emoji(st, con)
310
- details = [st, con].compact.join("/")
311
- status_q << [c, f, "#{emoji} (#{details})"]
312
- break if st == "completed"
313
- else
314
- status_q << [c, f, "none"]
315
- break
316
- end
282
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
283
+ delay = 0.12 - (now - st_at)
284
+ sleep(delay) if delay && delay > 0
285
+
286
+ if ow.nil? || rp.nil? || br.nil?
287
+ status_q << [c, f, "n/a"]
288
+ Thread.exit
289
+ end
290
+ uri = URI("https://api.github.com/repos/#{ow}/#{rp}/actions/workflows/#{f}/runs?branch=#{URI.encode_www_form_component(br)}&per_page=1")
291
+ poll_interval = Integer(ENV["CI_ACT_POLL_INTERVAL"] || 5)
292
+ loop do
293
+ begin
294
+ req = Net::HTTP::Get.new(uri)
295
+ req["User-Agent"] = "ci:act rake task"
296
+ req["Authorization"] = "token #{tk}" if tk && !tk.empty?
297
+ res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
298
+ if res.is_a?(Net::HTTPSuccess)
299
+ data = JSON.parse(res.body)
300
+ run = data["workflow_runs"]&.first
301
+ if run
302
+ st = run["status"]
303
+ con = run["conclusion"]
304
+ emoji = Kettle::Dev::CIMonitor.status_emoji(st, con)
305
+ details = [st, con].compact.join("/")
306
+ status_q << [c, f, "#{emoji} (#{details})"]
307
+ break if st == "completed"
317
308
  else
318
- status_q << [c, f, "fail #{res.code}"]
309
+ status_q << [c, f, "none"]
310
+ break
319
311
  end
320
- rescue Exception => e # rubocop:disable Lint/RescueException
321
- Kettle::Dev.debug_error(e, __method__)
322
- # Catch all exceptions to prevent crashing the process from a worker thread
323
- status_q << [c, f, "err"]
312
+ else
313
+ status_q << [c, f, "fail #{res.code}"]
324
314
  end
325
- sleep(poll_interval)
315
+ rescue Exception => e # rubocop:disable Lint/RescueException
316
+ Kettle::Dev.debug_error(e, __method__)
317
+ # Catch all exceptions to prevent crashing the process from a worker thread
318
+ status_q << [c, f, "err"]
326
319
  end
327
- rescue Exception => e # rubocop:disable Lint/RescueException
328
- Kettle::Dev.debug_error(e, __method__)
329
- # simplecov:disable
330
- # Catch all exceptions in the worker thread boundary, including SystemExit
331
- status_q << [c, f, "err"]
332
- # simplecov:enable
320
+ sleep(poll_interval)
333
321
  end
322
+ rescue Exception => e # rubocop:disable Lint/RescueException
323
+ Kettle::Dev.debug_error(e, __method__)
324
+ # simplecov:disable
325
+ # Catch all exceptions in the worker thread boundary, including SystemExit
326
+ status_q << [c, f, "err"]
327
+ # simplecov:enable
334
328
  end
335
329
  end
336
330
 
@@ -3,7 +3,7 @@
3
3
  module Kettle
4
4
  module Dev
5
5
  module Version
6
- VERSION = "2.2.18"
6
+ VERSION = "2.2.19"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
data/lib/kettle/dev.rb CHANGED
@@ -177,38 +177,34 @@ module Kettle
177
177
  # Set up rubocop-lts, which cascades to rubocop-rubyX_X => rubocop_gradual)
178
178
  # @return [void]
179
179
  def linting_tasks
180
- begin
181
- # Lazy loaded because it won't be installed for Ruby < 2.7
182
- require "rubocop/lts"
183
-
184
- Rubocop::Lts.install_tasks
185
- if Kettle::Dev::IS_CI
186
- Kettle::Dev.register_default("rubocop_gradual:check")
187
- else
188
- Kettle::Dev.register_default("rubocop_gradual:autocorrect")
189
- end
190
- rescue LoadError
191
- # OK, no styles for you.
180
+ # Lazy loaded because it won't be installed for Ruby < 2.7
181
+ require "rubocop/lts"
182
+
183
+ Rubocop::Lts.install_tasks
184
+ if Kettle::Dev::IS_CI
185
+ Kettle::Dev.register_default("rubocop_gradual:check")
186
+ else
187
+ Kettle::Dev.register_default("rubocop_gradual:autocorrect")
192
188
  end
189
+ rescue LoadError
190
+ # OK, no styles for you.
193
191
  end
194
192
 
195
193
  ### TEST COVERAGE TASKS
196
194
  # Set up kettle-soup-cover
197
195
  # @return [void]
198
196
  def coverage_tasks
199
- begin
200
- # Lazy loaded because it won't be installed for Ruby < 2.7
201
- require "kettle-soup-cover"
202
-
203
- Kettle::Soup::Cover.install_tasks
204
- # NOTE: Coverage on CI is configured independent of this task.
205
- # This task is for local development, as it opens results in browser
206
- # simplecov:disable
207
- Kettle::Dev.register_default("coverage") unless Kettle::Dev::IS_CI
208
- # simplecov:enable
209
- rescue LoadError
210
- # OK, no soup for you.
211
- end
197
+ # Lazy loaded because it won't be installed for Ruby < 2.7
198
+ require "kettle-soup-cover"
199
+
200
+ Kettle::Soup::Cover.install_tasks
201
+ # NOTE: Coverage on CI is configured independent of this task.
202
+ # This task is for local development, as it opens results in browser
203
+ # simplecov:disable
204
+ Kettle::Dev.register_default("coverage") unless Kettle::Dev::IS_CI
205
+ # simplecov:enable
206
+ rescue LoadError
207
+ # OK, no soup for you.
212
208
  end
213
209
  end
214
210
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kettle-dev
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.18
4
+ version: 2.2.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -339,10 +339,10 @@ licenses:
339
339
  - AGPL-3.0-only
340
340
  metadata:
341
341
  homepage_uri: https://kettle-dev.galtzo.com
342
- source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.2.18
343
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.2.18/CHANGELOG.md
342
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.2.19
343
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.2.19/CHANGELOG.md
344
344
  bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
345
- documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.2.18
345
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.2.19
346
346
  funding_uri: https://github.com/sponsors/pboling
347
347
  wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
348
348
  news_uri: https://www.railsbling.com/tags/kettle-dev
metadata.gz.sig CHANGED
Binary file