kettle-dev 1.1.12 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.rubocop_rspec.yml +30 -0
- data/Appraisals +1 -1
- data/CHANGELOG.md +12 -1
- data/README.md +1 -1
- data/README.md.example +1 -1
- data/Rakefile.example +1 -1
- data/lib/kettle/dev/changelog_cli.rb +5 -0
- data/lib/kettle/dev/ci_helpers.rb +11 -0
- data/lib/kettle/dev/ci_monitor.rb +8 -2
- data/lib/kettle/dev/commit_msg.rb +1 -0
- data/lib/kettle/dev/dvcs_cli.rb +10 -1
- data/lib/kettle/dev/git_adapter.rb +1 -0
- data/lib/kettle/dev/git_commit_footer.rb +1 -0
- data/lib/kettle/dev/input_adapter.rb +1 -0
- data/lib/kettle/dev/pre_release_cli.rb +2 -0
- data/lib/kettle/dev/readme_backers.rb +14 -0
- data/lib/kettle/dev/release_cli.rb +19 -0
- data/lib/kettle/dev/setup_cli.rb +9 -1
- data/lib/kettle/dev/tasks/install_task.rb +31 -18
- data/lib/kettle/dev/tasks/template_task.rb +9 -0
- data/lib/kettle/dev/template_helpers.rb +4 -0
- data/lib/kettle/dev/version.rb +1 -1
- data/lib/kettle/dev/versioning.rb +2 -0
- data.tar.gz.sig +0 -0
- metadata +6 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b2236329716c5ee01b5cf04dd99ee6b0595a7fa95a76c8ab959c04130aaada7
|
4
|
+
data.tar.gz: 9ea676b1fd79e9247c56bf3bb5c584870e572ed6ed462ba399227c3e03047ea5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2d83150965bedec8642543e4c818447203c0c4d5de60d41a41b2bf0672995a1e80c8501c463d448746e9d76622553df389a6fecf1a1313358c1c203c2ea29a0
|
7
|
+
data.tar.gz: ba80dea5b32c6ae569e63ef2f5134683d6867c0857ed988c2bfe243076b02728c9ca12a5ae874cd94459794af63163ef215753243256c7d6157d91251f19e8ca
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.rubocop_rspec.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
RSpec/MultipleExpectations:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
RSpec/NamedSubject:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
RSpec/ExampleLength:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
RSpec/VerifiedDoubles:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
RSpec/MessageSpies:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
RSpec/InstanceVariable:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
RSpec/NestedGroups:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
RSpec/ExpectInHook:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
RSpec/DescribeClass:
|
26
|
+
Exclude:
|
27
|
+
- 'spec/examples/*'
|
28
|
+
|
29
|
+
RSpec/MultipleMemoizedHelpers:
|
30
|
+
Enabled: false
|
data/Appraisals
CHANGED
@@ -143,7 +143,7 @@ end
|
|
143
143
|
# Only run linter on the latest version of Ruby (but, in support of oldest supported Ruby version)
|
144
144
|
appraise "style" do
|
145
145
|
eval_gemfile "modular/style.gemfile"
|
146
|
-
eval_gemfile "modular/x_std_libs
|
146
|
+
eval_gemfile "modular/x_std_libs.gemfile"
|
147
147
|
# Dependencies injected by the kettle-dev-setup script & kettle:dev:install rake task
|
148
148
|
# eval_gemfile "modular/injected.gemfile"
|
149
149
|
end
|
data/CHANGELOG.md
CHANGED
@@ -24,6 +24,15 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
24
24
|
### Fixed
|
25
25
|
### Security
|
26
26
|
|
27
|
+
## [1.1.13] - 2025-09-09
|
28
|
+
- TAG: [v1.1.13][1.1.13t]
|
29
|
+
- COVERAGE: 96.29% -- 3479/3613 lines in 25 files
|
30
|
+
- BRANCH COVERAGE: 80.96% -- 1424/1759 branches in 25 files
|
31
|
+
- 76.88% documented
|
32
|
+
### Fixed
|
33
|
+
- include .rubocop_rspec.yml during install / template task's file copy
|
34
|
+
- kettle-dev-setup now honors `--force` option
|
35
|
+
|
27
36
|
## [1.1.12] - 2025-09-09
|
28
37
|
- TAG: [v1.1.12][1.1.12t]
|
29
38
|
- COVERAGE: 94.84% -- 3422/3608 lines in 25 files
|
@@ -590,7 +599,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
590
599
|
- Selecting will run the selected workflow via `act`
|
591
600
|
- This may move to its own gem in the future.
|
592
601
|
|
593
|
-
[Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.
|
602
|
+
[Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.13...HEAD
|
603
|
+
[1.1.13]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.12...v1.1.13
|
604
|
+
[1.1.13t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.1.13
|
594
605
|
[1.1.12]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.11...v1.1.12
|
595
606
|
[1.1.12t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.1.12
|
596
607
|
[1.1.11]: https://github.com/kettle-rb/kettle-dev/compare/v1.1.10...v1.1.11
|
data/README.md
CHANGED
@@ -907,7 +907,7 @@ Thanks for RTFM. ☺️
|
|
907
907
|
[📌gitmoji]:https://gitmoji.dev
|
908
908
|
[📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
909
909
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
910
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.
|
910
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.613-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
911
911
|
[🔐security]: SECURITY.md
|
912
912
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
913
913
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/README.md.example
CHANGED
@@ -507,7 +507,7 @@ Thanks for RTFM. ☺️
|
|
507
507
|
[📌gitmoji]:https://gitmoji.dev
|
508
508
|
[📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
509
509
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
510
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.
|
510
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.613-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
511
511
|
[🔐security]: SECURITY.md
|
512
512
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
513
513
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/Rakefile.example
CHANGED
@@ -106,6 +106,7 @@ module Kettle
|
|
106
106
|
content = File.read(path)
|
107
107
|
m = content.match(/VERSION\s*=\s*(["'])([^"']+)\1/)
|
108
108
|
next unless m
|
109
|
+
|
109
110
|
m[2]
|
110
111
|
end.compact
|
111
112
|
abort("VERSION constant not found in #{@root}/lib/**/version.rb") if versions.none?
|
@@ -117,6 +118,7 @@ module Kettle
|
|
117
118
|
lines = content.lines
|
118
119
|
start_i = lines.index { |l| l.start_with?("## [Unreleased]") }
|
119
120
|
return [nil, nil, nil] unless start_i
|
121
|
+
|
120
122
|
# Find the next version heading after Unreleased
|
121
123
|
next_i = (start_i + 1)
|
122
124
|
while next_i < lines.length && !lines[next_i].start_with?("## [")
|
@@ -133,6 +135,7 @@ module Kettle
|
|
133
135
|
# after_text begins with the first released section following Unreleased
|
134
136
|
m = after_text.match(/^## \[(\d+\.\d+\.\d+)\]/)
|
135
137
|
return m[1] if m
|
138
|
+
|
136
139
|
nil
|
137
140
|
end
|
138
141
|
|
@@ -199,8 +202,10 @@ module Kettle
|
|
199
202
|
branches = h["branches"] || []
|
200
203
|
branches.each do |b|
|
201
204
|
next unless b.is_a?(Hash)
|
205
|
+
|
202
206
|
cov = b["coverage"]
|
203
207
|
next unless cov.is_a?(Numeric)
|
208
|
+
|
204
209
|
total_branches += 1
|
205
210
|
covered_branches += 1 if cov > 0
|
206
211
|
end
|
@@ -35,6 +35,7 @@ module Kettle
|
|
35
35
|
def repo_info
|
36
36
|
out, status = Open3.capture2("git", "config", "--get", "remote.origin.url")
|
37
37
|
return unless status.success?
|
38
|
+
|
38
39
|
url = out.strip
|
39
40
|
if url =~ %r{git@github.com:(.+?)/(.+?)(\.git)?$}
|
40
41
|
[Regexp.last_match(1), Regexp.last_match(2).sub(/\.git\z/, "")]
|
@@ -88,8 +89,10 @@ module Kettle
|
|
88
89
|
# @return [Hash{String=>String,Integer}, nil] minimal run info or nil on error/none
|
89
90
|
def latest_run(owner:, repo:, workflow_file:, branch: nil, token: default_token)
|
90
91
|
return unless owner && repo
|
92
|
+
|
91
93
|
b = branch || current_branch
|
92
94
|
return unless b
|
95
|
+
|
93
96
|
# Scope to the exact commit SHA when available to avoid picking up a previous run on the same branch.
|
94
97
|
sha_out, status = Open3.capture2("git", "rev-parse", "HEAD")
|
95
98
|
sha = status.success? ? sha_out.strip : nil
|
@@ -100,6 +103,7 @@ module Kettle
|
|
100
103
|
req["Authorization"] = "token #{token}" if token && !token.empty?
|
101
104
|
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
|
102
105
|
return unless res.is_a?(Net::HTTPSuccess)
|
106
|
+
|
103
107
|
data = JSON.parse(res.body)
|
104
108
|
runs = Array(data["workflow_runs"]) || []
|
105
109
|
# Try to match by head_sha first; fall back to first run (branch-scoped) if none matches yet.
|
@@ -109,6 +113,7 @@ module Kettle
|
|
109
113
|
runs.first
|
110
114
|
end
|
111
115
|
return unless run
|
116
|
+
|
112
117
|
{
|
113
118
|
"status" => run["status"],
|
114
119
|
"conclusion" => run["conclusion"],
|
@@ -154,6 +159,7 @@ module Kettle
|
|
154
159
|
def repo_info_gitlab
|
155
160
|
url = origin_url
|
156
161
|
return unless url
|
162
|
+
|
157
163
|
if url =~ %r{git@gitlab.com:(.+?)/(.+?)(\.git)?$}
|
158
164
|
[Regexp.last_match(1), Regexp.last_match(2).sub(/\.git\z/, "")]
|
159
165
|
elsif url =~ %r{https://gitlab.com/(.+?)/(.+?)(\.git)?$}
|
@@ -176,8 +182,10 @@ module Kettle
|
|
176
182
|
# @return [Hash{String=>String,Integer}, nil]
|
177
183
|
def gitlab_latest_pipeline(owner:, repo:, branch: nil, host: "gitlab.com", token: default_gitlab_token)
|
178
184
|
return unless owner && repo
|
185
|
+
|
179
186
|
b = branch || current_branch
|
180
187
|
return unless b
|
188
|
+
|
181
189
|
project = URI.encode_www_form_component("#{owner}/#{repo}")
|
182
190
|
uri = URI("https://#{host}/api/v4/projects/#{project}/pipelines?ref=#{URI.encode_www_form_component(b)}&per_page=1")
|
183
191
|
req = Net::HTTP::Get.new(uri)
|
@@ -185,10 +193,13 @@ module Kettle
|
|
185
193
|
req["PRIVATE-TOKEN"] = token if token && !token.empty?
|
186
194
|
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
|
187
195
|
return unless res.is_a?(Net::HTTPSuccess)
|
196
|
+
|
188
197
|
data = JSON.parse(res.body)
|
189
198
|
return unless data.is_a?(Array)
|
199
|
+
|
190
200
|
pipe = data.first
|
191
201
|
return unless pipe.is_a?(Hash)
|
202
|
+
|
192
203
|
# Attempt to enrich with failure_reason by querying the single pipeline endpoint
|
193
204
|
begin
|
194
205
|
if pipe["id"]
|
@@ -36,6 +36,7 @@ module Kettle
|
|
36
36
|
# Some APIs report only a final state string like "success"/"failed"
|
37
37
|
return "✅" if conclusion.to_s == "success" || status.to_s == "success"
|
38
38
|
return "🍅" if conclusion.to_s == "failure" || status.to_s == "failed"
|
39
|
+
|
39
40
|
"⏳️"
|
40
41
|
end
|
41
42
|
end
|
@@ -100,7 +101,7 @@ module Kettle
|
|
100
101
|
emoji = status_emoji(it[:status], it[:conclusion])
|
101
102
|
details = [it[:status], it[:conclusion]].compact.join("/")
|
102
103
|
wf = it[:workflow]
|
103
|
-
puts " - #{wf}: #{emoji} (#{details}) #{
|
104
|
+
puts " - #{wf}: #{emoji} (#{details}) #{"-> #{it[:url]}" if it[:url]}"
|
104
105
|
all_ok &&= (it[:conclusion] == "success")
|
105
106
|
end
|
106
107
|
end
|
@@ -113,7 +114,7 @@ module Kettle
|
|
113
114
|
end
|
114
115
|
emoji = status_emoji(gl[:status], status)
|
115
116
|
details = gl[:status].to_s
|
116
|
-
puts "GitLab Pipeline: #{emoji} (#{details}) #{
|
117
|
+
puts "GitLab Pipeline: #{emoji} (#{details}) #{"-> #{gl[:url]}" if gl[:url]}"
|
117
118
|
all_ok &&= (gl[:status] != "failed")
|
118
119
|
end
|
119
120
|
all_ok
|
@@ -209,6 +210,7 @@ module Kettle
|
|
209
210
|
end
|
210
211
|
end
|
211
212
|
break if results.size == total
|
213
|
+
|
212
214
|
idx = (idx + 1) % total
|
213
215
|
sleep(1)
|
214
216
|
end
|
@@ -313,6 +315,7 @@ module Kettle
|
|
313
315
|
end
|
314
316
|
end
|
315
317
|
break if passed.size == total
|
318
|
+
|
316
319
|
idx = (idx + 1) % total
|
317
320
|
sleep(1)
|
318
321
|
end
|
@@ -395,15 +398,18 @@ module Kettle
|
|
395
398
|
def preferred_github_remote
|
396
399
|
cands = github_remote_candidates
|
397
400
|
return if cands.empty?
|
401
|
+
|
398
402
|
explicit = cands.find { |n| n == "github" } || cands.find { |n| n == "gh" }
|
399
403
|
return explicit if explicit
|
400
404
|
return "origin" if cands.include?("origin")
|
405
|
+
|
401
406
|
cands.first
|
402
407
|
end
|
403
408
|
module_function :preferred_github_remote
|
404
409
|
|
405
410
|
def parse_github_owner_repo(url)
|
406
411
|
return [nil, nil] unless url
|
412
|
+
|
407
413
|
if url =~ %r{git@github.com:(.+?)/(.+?)(\.git)?$}
|
408
414
|
[Regexp.last_match(1), Regexp.last_match(2).sub(/\.git\z/, "")]
|
409
415
|
elsif url =~ %r{https://github.com/(.+?)/(.+?)(\.git)?$}
|
@@ -18,6 +18,7 @@ module Kettle
|
|
18
18
|
validate = ENV.fetch("GIT_HOOK_BRANCH_VALIDATE", "false")
|
19
19
|
branch_rule_type = (!validate.casecmp("false").zero? && validate) || nil
|
20
20
|
return unless branch_rule_type
|
21
|
+
|
21
22
|
branch_rule = BRANCH_RULES[branch_rule_type]
|
22
23
|
return unless branch_rule
|
23
24
|
|
data/lib/kettle/dev/dvcs_cli.rb
CHANGED
@@ -69,6 +69,7 @@ module Kettle
|
|
69
69
|
%i[github gitlab codeberg].each do |forge|
|
70
70
|
r = names[forge]
|
71
71
|
next unless r && r != names[:origin]
|
72
|
+
|
72
73
|
git.fetch(r)
|
73
74
|
end
|
74
75
|
show_status!(git, names, branch)
|
@@ -106,8 +107,10 @@ module Kettle
|
|
106
107
|
def detect_default_branch!(git)
|
107
108
|
_out, ok = git.capture(["rev-parse", "--verify", "origin/main"])
|
108
109
|
return "main" if ok
|
110
|
+
|
109
111
|
_out2, ok2 = git.capture(["rev-parse", "--verify", "origin/master"])
|
110
112
|
return "master" if ok2
|
113
|
+
|
111
114
|
# Default to main if neither verifies
|
112
115
|
"main"
|
113
116
|
end
|
@@ -125,6 +128,7 @@ module Kettle
|
|
125
128
|
next unless remote
|
126
129
|
next if remote == names[:origin]
|
127
130
|
next unless existing.include?(remote)
|
131
|
+
|
128
132
|
ref = "#{remote}/#{branch}"
|
129
133
|
out, ok = git.capture(["rev-list", "--left-right", "--count", "#{base}...#{ref}"])
|
130
134
|
if ok && !out.to_s.strip.empty?
|
@@ -232,6 +236,7 @@ module Kettle
|
|
232
236
|
if org && repo
|
233
237
|
return [org, repo]
|
234
238
|
end
|
239
|
+
|
235
240
|
# Try to infer from any existing remote url
|
236
241
|
urls = git.remotes_with_urls
|
237
242
|
sample = urls["origin"] || urls.values.first
|
@@ -252,7 +257,8 @@ module Kettle
|
|
252
257
|
|
253
258
|
def prompt(label, default: nil)
|
254
259
|
return default if @opts[:force]
|
255
|
-
|
260
|
+
|
261
|
+
print("#{label}#{" [#{default}]" if default}: ")
|
256
262
|
ans = $stdin.gets&.strip
|
257
263
|
ans = nil if ans == ""
|
258
264
|
ans || default || abort!("#{label} is required")
|
@@ -341,6 +347,7 @@ module Kettle
|
|
341
347
|
codeberg: names[:codeberg],
|
342
348
|
}.each do |forge, remote_name|
|
343
349
|
next unless remote_name
|
350
|
+
|
344
351
|
ok = git.fetch(remote_name)
|
345
352
|
results[forge] = !!ok
|
346
353
|
say("Fetched from #{forge} (remote: #{remote_name}) => #{ok ? "OK" : "FAILED"}")
|
@@ -352,6 +359,7 @@ module Kettle
|
|
352
359
|
def update_readme_federation_status!(org, repo, results)
|
353
360
|
readme_path = File.join(Dir.pwd, "README.md")
|
354
361
|
return unless File.exist?(readme_path)
|
362
|
+
|
355
363
|
content = File.read(readme_path)
|
356
364
|
# Determine if all succeeded
|
357
365
|
forges = [:github, :gitlab, :codeberg]
|
@@ -376,6 +384,7 @@ module Kettle
|
|
376
384
|
say("\nSome forges are not yet available. Use these import links to create mirrors:")
|
377
385
|
[:github, :gitlab, :codeberg].each do |forge|
|
378
386
|
next if results[forge]
|
387
|
+
|
379
388
|
say(" - #{forge.capitalize} import: #{FORGE_MIGRATION_TOOLS[forge]}")
|
380
389
|
end
|
381
390
|
end
|
@@ -71,6 +71,7 @@ module Kettle
|
|
71
71
|
when Net::HTTPRedirection
|
72
72
|
location = response["location"]
|
73
73
|
return false unless location
|
74
|
+
|
74
75
|
new_uri = parse_http_uri(location)
|
75
76
|
new_uri = uri + location if new_uri.relative?
|
76
77
|
head_ok?(new_uri.to_s, limit: limit - 1, timeout: timeout)
|
@@ -155,6 +156,7 @@ module Kettle
|
|
155
156
|
|
156
157
|
start = @check_num
|
157
158
|
raise ArgumentError, "check_num must be >= 1" if start < 1
|
159
|
+
|
158
160
|
begin_idx = start - 1
|
159
161
|
checks[begin_idx..-1].each_with_index do |check, i|
|
160
162
|
idx = begin_idx + i + 1
|
@@ -119,6 +119,7 @@ module Kettle
|
|
119
119
|
def readme_osc_tag
|
120
120
|
env = ENV["KETTLE_DEV_BACKER_README_OSC_TAG"].to_s
|
121
121
|
return env unless env.strip.empty?
|
122
|
+
|
122
123
|
if File.file?(OC_YML_PATH)
|
123
124
|
begin
|
124
125
|
yml = YAML.safe_load(File.read(OC_YML_PATH))
|
@@ -149,6 +150,7 @@ module Kettle
|
|
149
150
|
def resolve_handle
|
150
151
|
env = ENV["OPENCOLLECTIVE_HANDLE"]
|
151
152
|
return env unless env.nil? || env.strip.empty?
|
153
|
+
|
152
154
|
if File.file?(OC_YML_PATH)
|
153
155
|
yml = YAML.safe_load(File.read(OC_YML_PATH))
|
154
156
|
handle = yml.is_a?(Hash) ? yml["collective"] || yml[:collective] : nil
|
@@ -167,6 +169,7 @@ module Kettle
|
|
167
169
|
conn.request(req)
|
168
170
|
end
|
169
171
|
return [] unless response.is_a?(Net::HTTPSuccess)
|
172
|
+
|
170
173
|
parsed = JSON.parse(response.body)
|
171
174
|
Array(parsed).map do |h|
|
172
175
|
Backer.new(
|
@@ -186,6 +189,7 @@ module Kettle
|
|
186
189
|
|
187
190
|
def generate_markdown(members, empty_message:, default_name:)
|
188
191
|
return empty_message if members.nil? || members.empty?
|
192
|
+
|
189
193
|
members.map do |m|
|
190
194
|
image_url = m.image || DEFAULT_AVATAR
|
191
195
|
link = m.website || m.profile || "#"
|
@@ -196,14 +200,17 @@ module Kettle
|
|
196
200
|
|
197
201
|
def replace_between_tags(content, start_tag, end_tag, new_content)
|
198
202
|
return :not_found if start_tag == :not_found || end_tag == :not_found
|
203
|
+
|
199
204
|
start_index = content.index(start_tag)
|
200
205
|
end_index = content.index(end_tag)
|
201
206
|
return :not_found if start_index.nil? || end_index.nil? || end_index < start_index
|
207
|
+
|
202
208
|
before = content[0..start_index + start_tag.length - 1]
|
203
209
|
after = content[end_index..-1]
|
204
210
|
replacement = "#{start_tag}\n#{new_content}\n#{end_tag}"
|
205
211
|
current_block = content[start_index..end_index + end_tag.length - 1]
|
206
212
|
return :no_change if current_block == replacement
|
213
|
+
|
207
214
|
trailing = after[end_tag.length..-1] || ""
|
208
215
|
"#{before}\n#{new_content}\n#{end_tag}#{trailing}"
|
209
216
|
end
|
@@ -230,9 +237,11 @@ module Kettle
|
|
230
237
|
|
231
238
|
def extract_section_identities(content, start_tag, end_tag)
|
232
239
|
return Set.new unless start_tag && end_tag && start_tag != :not_found && end_tag != :not_found
|
240
|
+
|
233
241
|
start_index = content.index(start_tag)
|
234
242
|
end_index = content.index(end_tag)
|
235
243
|
return Set.new if start_index.nil? || end_index.nil? || end_index < start_index
|
244
|
+
|
236
245
|
block = content[(start_index + start_tag.length)...end_index]
|
237
246
|
identities = Set.new
|
238
247
|
block.to_s.scan(/\[!\[[^\]]*\]\([^\)]*\)\]\(([^\)]+)\)/) do |m|
|
@@ -269,6 +278,7 @@ module Kettle
|
|
269
278
|
def mention_for_member(m, default_name: "Member")
|
270
279
|
handle = github_handle_from_urls(m.profile, m.website)
|
271
280
|
return "@#{handle}" if handle
|
281
|
+
|
272
282
|
name = (m.name && !m.name.strip.empty?) ? m.name.strip : default_name
|
273
283
|
name
|
274
284
|
end
|
@@ -281,8 +291,10 @@ module Kettle
|
|
281
291
|
next
|
282
292
|
end
|
283
293
|
next unless uri&.host&.downcase&.end_with?("github.com")
|
294
|
+
|
284
295
|
path = (uri.path || "").sub(%r{^/}, "").sub(%r{/$}, "")
|
285
296
|
next if path.empty?
|
297
|
+
|
286
298
|
parts = path.split("/")
|
287
299
|
candidate = if parts[0].downcase == "sponsors" && parts[1]
|
288
300
|
parts[1]
|
@@ -308,12 +320,14 @@ module Kettle
|
|
308
320
|
if system("git", "diff", "--cached", "--quiet")
|
309
321
|
return
|
310
322
|
end
|
323
|
+
|
311
324
|
system("git", "commit", "-m", message)
|
312
325
|
end
|
313
326
|
|
314
327
|
def commit_subject
|
315
328
|
env = ENV["KETTLE_README_BACKERS_COMMIT_SUBJECT"].to_s
|
316
329
|
return env unless env.strip.empty?
|
330
|
+
|
317
331
|
if File.file?(OC_YML_PATH)
|
318
332
|
begin
|
319
333
|
yml = YAML.safe_load(File.read(OC_YML_PATH))
|
@@ -283,6 +283,7 @@ module Kettle
|
|
283
283
|
# Example match: "- COVERAGE: 97.70% -- 2125/2175 lines in 20 files"
|
284
284
|
m = section.lines.find { |l| l =~ /-\s*COVERAGE:\s*.+--\s*\d+\/(\d+)\s+lines/i }
|
285
285
|
return unless m
|
286
|
+
|
286
287
|
denom = m.match(/-\s*COVERAGE:\s*.+--\s*\d+\/(\d+)\s+lines/i)[1].to_i
|
287
288
|
kloc = denom.to_f / 1000.0
|
288
289
|
kloc_str = format("%.3f", kloc)
|
@@ -296,6 +297,7 @@ module Kettle
|
|
296
297
|
# Replaces only the numeric portion after "KLOC-" keeping other URL parts intact.
|
297
298
|
def update_badge_number_in_file(path, kloc_str)
|
298
299
|
return unless File.file?(path)
|
300
|
+
|
299
301
|
content = File.read(path)
|
300
302
|
# Match the specific reference line, capture groups around the number
|
301
303
|
# Example: [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.175-FFDD67.svg?style=...
|
@@ -310,6 +312,7 @@ module Kettle
|
|
310
312
|
def update_rakefile_example_header!(version)
|
311
313
|
path = File.join(@root, "Rakefile.example")
|
312
314
|
return unless File.file?(path)
|
315
|
+
|
313
316
|
content = File.read(path)
|
314
317
|
today = Time.now.strftime("%Y-%m-%d")
|
315
318
|
new_line = "# kettle-dev Rakefile v#{version} - #{today}"
|
@@ -394,6 +397,7 @@ module Kettle
|
|
394
397
|
def collapse_years(enum)
|
395
398
|
arr = enum.to_a.map(&:to_i).uniq.sort
|
396
399
|
return "" if arr.empty?
|
400
|
+
|
397
401
|
segments = []
|
398
402
|
start = arr.first
|
399
403
|
prev = start
|
@@ -422,10 +426,12 @@ module Kettle
|
|
422
426
|
unless line =~ /copyright/i
|
423
427
|
next line
|
424
428
|
end
|
429
|
+
|
425
430
|
m = line.match(/\A(?<pre>.*?copyright[^0-9]*)(?<years>(?:\b(?:19|20)\d{2}\b(?:\s*[\-–]\s*\b(?:19|20)\d{2}\b)?)(?:\s*,\s*\b(?:19|20)\d{2}\b(?:\s*[\-–]\s*\b(?:19|20)\d{2}\b)?)*)(?<post>.*)\z/i)
|
426
431
|
unless m
|
427
432
|
next line
|
428
433
|
end
|
434
|
+
|
429
435
|
new_line = "#{m[:pre]}#{canonical_all}#{m[:post]}"
|
430
436
|
changed ||= (new_line != line)
|
431
437
|
new_line
|
@@ -444,12 +450,14 @@ module Kettle
|
|
444
450
|
unless line =~ /copyright/i
|
445
451
|
next line
|
446
452
|
end
|
453
|
+
|
447
454
|
# Capture three parts: prefix up to first year, the year blob, and the rest
|
448
455
|
m = line.match(/\A(?<pre>.*?copyright[^0-9]*)(?<years>(?:\b(?:19|20)\d{2}\b(?:\s*[\-–]\s*\b(?:19|20)\d{2}\b)?)(?:\s*,\s*\b(?:19|20)\d{2}\b(?:\s*[\-–]\s*\b(?:19|20)\d{2}\b)?)*)(?<post>.*)\z/i)
|
449
456
|
unless m
|
450
457
|
# No parsable year sequence on this line; leave as-is
|
451
458
|
next line
|
452
459
|
end
|
460
|
+
|
453
461
|
years_blob = m[:years]
|
454
462
|
# Reuse extraction logic on just the years blob
|
455
463
|
years = []
|
@@ -731,15 +739,18 @@ module Kettle
|
|
731
739
|
def preferred_github_remote
|
732
740
|
cands = github_remote_candidates
|
733
741
|
return if cands.empty?
|
742
|
+
|
734
743
|
# Prefer explicitly named GitHub remotes first, then origin (only if it points to GitHub), else the first candidate
|
735
744
|
explicit = cands.find { |n| n == "github" } || cands.find { |n| n == "gh" }
|
736
745
|
return explicit if explicit
|
737
746
|
return "origin" if cands.include?("origin")
|
747
|
+
|
738
748
|
cands.first
|
739
749
|
end
|
740
750
|
|
741
751
|
def parse_github_owner_repo(url)
|
742
752
|
return [nil, nil] unless url
|
753
|
+
|
743
754
|
if url =~ %r{git@github.com:(.+?)/(.+?)(\.git)?$}
|
744
755
|
[Regexp.last_match(1), Regexp.last_match(2).sub(/\.git\z/, "")]
|
745
756
|
elsif url =~ %r{https://github.com/(.+?)/(.+?)(\.git)?$}
|
@@ -761,6 +772,7 @@ module Kettle
|
|
761
772
|
def ahead_behind_counts(local_ref, remote_ref)
|
762
773
|
out, ok = git_output(["rev-list", "--left-right", "--count", "#{local_ref}...#{remote_ref}"])
|
763
774
|
return [0, 0] unless ok && !out.empty?
|
775
|
+
|
764
776
|
parts = out.split
|
765
777
|
left = parts[0].to_i
|
766
778
|
right = parts[1].to_i
|
@@ -769,6 +781,7 @@ module Kettle
|
|
769
781
|
|
770
782
|
def trunk_behind_remote?(trunk, remote)
|
771
783
|
return false unless remote_branch_exists?(remote, trunk)
|
784
|
+
|
772
785
|
_ahead, behind = ahead_behind_counts(trunk, "#{remote}/#{trunk}")
|
773
786
|
behind.positive?
|
774
787
|
end
|
@@ -781,6 +794,7 @@ module Kettle
|
|
781
794
|
missing_from = []
|
782
795
|
remotes.each do |r|
|
783
796
|
next if r == "all"
|
797
|
+
|
784
798
|
if remote_branch_exists?(r, trunk)
|
785
799
|
_ahead, behind = ahead_behind_counts(trunk, "#{r}/#{trunk}")
|
786
800
|
missing_from << r if behind.positive?
|
@@ -853,6 +867,7 @@ module Kettle
|
|
853
867
|
|
854
868
|
def merge_feature_into_trunk_and_push!(trunk, feature)
|
855
869
|
return if feature.nil? || feature == trunk
|
870
|
+
|
856
871
|
puts "Merging #{feature} into #{trunk} (after CI success)..."
|
857
872
|
checkout!(trunk)
|
858
873
|
run_cmd!("git pull --rebase origin #{Shellwords.escape(trunk)}")
|
@@ -971,12 +986,14 @@ module Kettle
|
|
971
986
|
def extract_changelog_for_version(version)
|
972
987
|
path = File.join(@root, "CHANGELOG.md")
|
973
988
|
return [nil, nil, nil] unless File.file?(path)
|
989
|
+
|
974
990
|
content = File.read(path)
|
975
991
|
lines = content.lines
|
976
992
|
|
977
993
|
# Find section start
|
978
994
|
start_idx = lines.index { |l| l.start_with?("## [#{version}]") }
|
979
995
|
return [nil, nil, nil] unless start_idx
|
996
|
+
|
980
997
|
i = start_idx + 1
|
981
998
|
# Find next section heading or EOF
|
982
999
|
while i < lines.length && !lines[i].start_with?("## [")
|
@@ -999,12 +1016,14 @@ module Kettle
|
|
999
1016
|
def extract_release_notes_footer
|
1000
1017
|
path = File.join(@root, "FUNDING.md")
|
1001
1018
|
return unless File.file?(path)
|
1019
|
+
|
1002
1020
|
content = File.read(path)
|
1003
1021
|
start_tag = "<!-- RELEASE-NOTES-FOOTER-START -->"
|
1004
1022
|
end_tag = "<!-- RELEASE-NOTES-FOOTER-END -->"
|
1005
1023
|
s = content.index(start_tag)
|
1006
1024
|
e = content.index(end_tag)
|
1007
1025
|
return unless s && e && e > s
|
1026
|
+
|
1008
1027
|
# Extract between tags, excluding the tags themselves
|
1009
1028
|
block = content[(s + start_tag.length)...e]
|
1010
1029
|
# Normalize: trim trailing whitespace but keep internal formatting
|
data/lib/kettle/dev/setup_cli.rb
CHANGED
@@ -46,6 +46,7 @@ module Kettle
|
|
46
46
|
|
47
47
|
def debug(msg)
|
48
48
|
return if ENV.fetch("DEBUG", "false").casecmp("true").nonzero?
|
49
|
+
|
49
50
|
$stderr.puts("[kettle-dev-setup] DEBUG: #{msg}")
|
50
51
|
end
|
51
52
|
|
@@ -106,7 +107,11 @@ module Kettle
|
|
106
107
|
parser = OptionParser.new do |opts|
|
107
108
|
opts.banner = "Usage: kettle-dev-setup [options]"
|
108
109
|
opts.on("--allowed=VAL", "Pass through to kettle:dev:install") { |v| @passthrough << "allowed=#{v}" }
|
109
|
-
opts.on("--force", "Pass through to kettle:dev:install")
|
110
|
+
opts.on("--force", "Pass through to kettle:dev:install") do
|
111
|
+
# Ensure in-process helpers (TemplateHelpers.ask) also see force mode
|
112
|
+
ENV["force"] = "true"
|
113
|
+
@passthrough << "force=true"
|
114
|
+
end
|
110
115
|
opts.on("--hook_templates=VAL", "Pass through to kettle:dev:install") { |v| @passthrough << "hook_templates=#{v}" }
|
111
116
|
opts.on("--only=VAL", "Pass through to kettle:dev:install") { |v| @passthrough << "only=#{v}" }
|
112
117
|
opts.on("-h", "--help", "Show help") do
|
@@ -260,6 +265,7 @@ module Kettle
|
|
260
265
|
example.each_line do |ln|
|
261
266
|
s = ln.strip
|
262
267
|
next if s.empty?
|
268
|
+
|
263
269
|
if s.start_with?("source ")
|
264
270
|
ex_sources << ln.rstrip
|
265
271
|
elsif (m = s.match(/^git_source\(\s*:(\w+)\s*\)/))
|
@@ -302,6 +308,7 @@ module Kettle
|
|
302
308
|
# Add missing eval_gemfile paths (recreate the exact example line when possible)
|
303
309
|
ex_eval_paths.each do |path|
|
304
310
|
next if tg_eval_paths.include?(path)
|
311
|
+
|
305
312
|
additions << "eval_gemfile \"#{path}\""
|
306
313
|
end
|
307
314
|
|
@@ -398,6 +405,7 @@ module Kettle
|
|
398
405
|
here = File.expand_path(File.join(__dir__, "..", "..", "..")) # lib/kettle/dev/ -> project root
|
399
406
|
path = File.join(here, rel)
|
400
407
|
return path if File.exist?(path)
|
408
|
+
|
401
409
|
nil
|
402
410
|
end
|
403
411
|
end
|
@@ -174,14 +174,19 @@ module Kettle
|
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
177
|
-
# If no grapheme found in README H1, ask the user
|
177
|
+
# If no grapheme found in README H1, either use a default in force mode, or ask the user.
|
178
178
|
if chosen_grapheme.nil? || chosen_grapheme.empty?
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
179
|
+
if ENV.fetch("force", "").to_s =~ ENV_TRUE_RE
|
180
|
+
# Non-interactive install: default to pizza slice to match template style.
|
181
|
+
chosen_grapheme = "🍕"
|
182
|
+
else
|
183
|
+
puts "No grapheme found after README H1. Enter a grapheme (emoji/symbol) to use for README, summary, and description:"
|
184
|
+
print("Grapheme: ")
|
185
|
+
ans = Kettle::Dev::InputAdapter.gets&.strip.to_s
|
186
|
+
chosen_grapheme = ans[/\A\X/u].to_s
|
187
|
+
# If still empty, skip synchronization silently
|
188
|
+
chosen_grapheme = nil if chosen_grapheme.empty?
|
189
|
+
end
|
185
190
|
end
|
186
191
|
|
187
192
|
if chosen_grapheme
|
@@ -311,15 +316,18 @@ module Kettle
|
|
311
316
|
|
312
317
|
github_repo_from_url = lambda do |url|
|
313
318
|
return unless url
|
319
|
+
|
314
320
|
url = url.strip
|
315
321
|
m = url.match(%r{github\.com[/:]([^/\s:]+)/([^/\s]+?)(?:\.git)?/?\z}i)
|
316
322
|
return unless m
|
323
|
+
|
317
324
|
[m[1], m[2]]
|
318
325
|
end
|
319
326
|
|
320
327
|
github_homepage_literal = lambda do |val|
|
321
328
|
return false unless val
|
322
329
|
return false if val.include?('#{')
|
330
|
+
|
323
331
|
v = val.to_s.strip
|
324
332
|
if (v.start_with?("\"") && v.end_with?("\"")) || (v.start_with?("'") && v.end_with?("'"))
|
325
333
|
v = begin
|
@@ -329,6 +337,7 @@ module Kettle
|
|
329
337
|
end
|
330
338
|
end
|
331
339
|
return false unless v =~ %r{\Ahttps?://github\.com/}i
|
340
|
+
|
332
341
|
!!github_repo_from_url.call(v)
|
333
342
|
end
|
334
343
|
|
@@ -364,12 +373,13 @@ module Kettle
|
|
364
373
|
puts "Current spec.homepage appears #{interpolated ? "interpolated" : "invalid"}: #{assigned}"
|
365
374
|
puts "Suggested literal homepage: \"#{suggested}\""
|
366
375
|
print("Update #{File.basename(gemspec_path)} to use this homepage? [Y/n]: ")
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
376
|
+
do_update =
|
377
|
+
if ENV.fetch("force", "").to_s =~ ENV_TRUE_RE
|
378
|
+
true
|
379
|
+
else
|
380
|
+
ans = Kettle::Dev::InputAdapter.gets&.strip
|
381
|
+
ans.nil? || ans.empty? || ans =~ /\Ay(es)?\z/i
|
382
|
+
end
|
373
383
|
|
374
384
|
if do_update
|
375
385
|
new_line = homepage_line.sub(/=.*/, "= \"#{suggested}\"\n")
|
@@ -385,6 +395,7 @@ module Kettle
|
|
385
395
|
rescue StandardError => e
|
386
396
|
# Do not swallow intentional task aborts signaled via Kettle::Dev::Error
|
387
397
|
raise if e.is_a?(Kettle::Dev::Error)
|
398
|
+
|
388
399
|
puts "WARNING: An error occurred while checking gemspec homepage: #{e.class}: #{e.message}"
|
389
400
|
end
|
390
401
|
|
@@ -406,6 +417,7 @@ module Kettle
|
|
406
417
|
[:create, :replace, :dir_create, :dir_replace].each do |sym|
|
407
418
|
items = meaningful.select { |_, rec| rec[:action] == sym }.map { |path, _| path }
|
408
419
|
next if items.empty?
|
420
|
+
|
409
421
|
puts " #{action_labels[sym]}:"
|
410
422
|
items.sort.each do |abs|
|
411
423
|
rel = begin
|
@@ -472,10 +484,8 @@ module Kettle
|
|
472
484
|
|
473
485
|
if defined?(updated_envrc_by_install) && updated_envrc_by_install
|
474
486
|
allowed_truthy = ENV.fetch("allowed", "").to_s =~ ENV_TRUE_RE
|
475
|
-
|
476
|
-
|
477
|
-
reason = allowed_truthy ? "allowed=true" : "force=true"
|
478
|
-
puts "Proceeding after .envrc update because #{reason}."
|
487
|
+
if allowed_truthy
|
488
|
+
puts "Proceeding after .envrc update because allowed=true."
|
479
489
|
else
|
480
490
|
puts
|
481
491
|
puts "IMPORTANT: .envrc was updated during kettle:dev:install."
|
@@ -509,7 +519,10 @@ module Kettle
|
|
509
519
|
puts "Would you like to add '.env.local' to #{gitignore_path}?"
|
510
520
|
print("Add to .gitignore now [Y/n]: ")
|
511
521
|
answer = Kettle::Dev::InputAdapter.gets&.strip
|
512
|
-
|
522
|
+
# Respect an explicit negative answer even when force=true
|
523
|
+
add_it = if answer && answer =~ /\An(o)?\z/i
|
524
|
+
false
|
525
|
+
elsif ENV.fetch("force", "").to_s =~ ENV_TRUE_RE
|
513
526
|
true
|
514
527
|
else
|
515
528
|
answer.nil? || answer.empty? || answer =~ /\Ay(es)?\z/i
|
@@ -349,6 +349,7 @@ module Kettle
|
|
349
349
|
src = helpers.prefer_example(File.join(gem_checkout_root, rel))
|
350
350
|
dest = File.join(project_root, rel)
|
351
351
|
next unless File.exist?(src)
|
352
|
+
|
352
353
|
if File.basename(rel) == "README.md"
|
353
354
|
# Precompute destination README H1 prefix (emoji(s) or first grapheme) before any overwrite occurs
|
354
355
|
prev_readme = File.exist?(dest) ? File.read(dest) : nil
|
@@ -364,6 +365,7 @@ module Kettle
|
|
364
365
|
loop do
|
365
366
|
cluster = s[/\A\X/u]
|
366
367
|
break if cluster.nil? || cluster.empty?
|
368
|
+
|
367
369
|
if emoji_re =~ cluster
|
368
370
|
out << cluster
|
369
371
|
s = s[cluster.length..-1].to_s
|
@@ -403,6 +405,7 @@ module Kettle
|
|
403
405
|
# Parse Markdown headings while ignoring fenced code blocks (``` ... ```)
|
404
406
|
build_sections = lambda do |md|
|
405
407
|
return {lines: [], sections: [], line_count: 0} unless md
|
408
|
+
|
406
409
|
lines = md.split("\n", -1)
|
407
410
|
line_count = lines.length
|
408
411
|
|
@@ -416,6 +419,7 @@ module Kettle
|
|
416
419
|
next
|
417
420
|
end
|
418
421
|
next if in_code
|
422
|
+
|
419
423
|
if (m = ln.match(/^(#+)\s+.+/))
|
420
424
|
level = m[1].length
|
421
425
|
title = ln.sub(/^#+\s+/, "")
|
@@ -449,6 +453,7 @@ module Kettle
|
|
449
453
|
j = i + 1
|
450
454
|
while j < sections_arr.length
|
451
455
|
return sections_arr[j][:start] - 1 if sections_arr[j][:level] <= current[:level]
|
456
|
+
|
452
457
|
j += 1
|
453
458
|
end
|
454
459
|
total_lines - 1
|
@@ -464,6 +469,7 @@ module Kettle
|
|
464
469
|
base = s[:base]
|
465
470
|
# Only set once (first occurrence wins)
|
466
471
|
next if dest_lookup.key?(base)
|
472
|
+
|
467
473
|
be = branch_end_index.call(dest_parsed[:sections], idx, dest_parsed[:line_count])
|
468
474
|
body_lines = dest_parsed[:lines][(s[:start] + 1)..be] || []
|
469
475
|
dest_lookup[base] = {body_branch: body_lines.join("\n"), level: s[:level]}
|
@@ -485,6 +491,7 @@ module Kettle
|
|
485
491
|
# Iterate in reverse to keep indices valid
|
486
492
|
src_parsed[:sections].reverse_each.with_index do |sec, rev_i|
|
487
493
|
next unless targets.include?(sec[:base])
|
494
|
+
|
488
495
|
# Determine branch range in src for this section
|
489
496
|
# rev_i is reverse index; compute forward index
|
490
497
|
i = src_parsed[:sections].length - 1 - rev_i
|
@@ -652,6 +659,7 @@ module Kettle
|
|
652
659
|
rescue StandardError => e
|
653
660
|
# Do not swallow intentional task aborts
|
654
661
|
raise if e.is_a?(Kettle::Dev::Error)
|
662
|
+
|
655
663
|
puts "WARNING: Could not determine env file changes: #{e.class}: #{e.message}"
|
656
664
|
end
|
657
665
|
|
@@ -753,6 +761,7 @@ module Kettle
|
|
753
761
|
hook_pairs = [[hook_ruby_src, "commit-msg", 0o755], [hook_sh_src, "prepare-commit-msg", 0o755]]
|
754
762
|
hook_pairs.each do |src, base, mode|
|
755
763
|
next unless File.file?(src)
|
764
|
+
|
756
765
|
hook_dests.each do |dstdir|
|
757
766
|
begin
|
758
767
|
FileUtils.mkdir_p(dstdir)
|
@@ -42,9 +42,13 @@ module Kettle
|
|
42
42
|
print("#{prompt} #{default ? "[Y/n]" : "[y/N]"}: ")
|
43
43
|
ans = Kettle::Dev::InputAdapter.gets&.strip
|
44
44
|
ans = "" if ans.nil?
|
45
|
+
# Normalize explicit no first
|
46
|
+
return false if ans =~ /\An(o)?\z/i
|
45
47
|
if default
|
48
|
+
# Empty -> default true; explicit yes -> true; anything else -> false
|
46
49
|
ans.empty? || ans =~ /\Ay(es)?\z/i
|
47
50
|
else
|
51
|
+
# Empty -> default false; explicit yes -> true; others (including garbage) -> false
|
48
52
|
ans =~ /\Ay(es)?\z/i
|
49
53
|
end
|
50
54
|
end
|
data/lib/kettle/dev/version.rb
CHANGED
@@ -16,6 +16,7 @@ module Kettle
|
|
16
16
|
content = File.read(path)
|
17
17
|
m = content.match(/VERSION\s*=\s*(["'])([^"']+)\1/)
|
18
18
|
next unless m
|
19
|
+
|
19
20
|
m[2]
|
20
21
|
end.compact
|
21
22
|
abort!("VERSION constant not found in #{root}/lib/**/version.rb") if versions.none?
|
@@ -39,6 +40,7 @@ module Kettle
|
|
39
40
|
|
40
41
|
if cmaj > pmaj
|
41
42
|
return :epic if cmaj && cmaj > 1000
|
43
|
+
|
42
44
|
:major
|
43
45
|
elsif cmin > pmin
|
44
46
|
:minor
|
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: 1.1.
|
4
|
+
version: 1.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter H. Boling
|
@@ -257,6 +257,7 @@ files:
|
|
257
257
|
- ".qlty/qlty.toml"
|
258
258
|
- ".rspec"
|
259
259
|
- ".rubocop.yml"
|
260
|
+
- ".rubocop_rspec.yml"
|
260
261
|
- ".simplecov"
|
261
262
|
- ".simplecov.example"
|
262
263
|
- ".tool-versions"
|
@@ -385,10 +386,10 @@ licenses:
|
|
385
386
|
- MIT
|
386
387
|
metadata:
|
387
388
|
homepage_uri: https://kettle-dev.galtzo.com/
|
388
|
-
source_code_uri: https://github.com/kettle-rb/kettle-dev/tree/v1.1.
|
389
|
-
changelog_uri: https://github.com/kettle-rb/kettle-dev/blob/v1.1.
|
389
|
+
source_code_uri: https://github.com/kettle-rb/kettle-dev/tree/v1.1.13
|
390
|
+
changelog_uri: https://github.com/kettle-rb/kettle-dev/blob/v1.1.13/CHANGELOG.md
|
390
391
|
bug_tracker_uri: https://github.com/kettle-rb/kettle-dev/issues
|
391
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/1.1.
|
392
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/1.1.13
|
392
393
|
funding_uri: https://github.com/sponsors/pboling
|
393
394
|
wiki_uri: https://github.com/kettle-rb/kettle-dev/wiki
|
394
395
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
@@ -417,7 +418,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
417
418
|
- !ruby/object:Gem::Version
|
418
419
|
version: '0'
|
419
420
|
requirements: []
|
420
|
-
rubygems_version: 3.7.
|
421
|
+
rubygems_version: 3.7.2
|
421
422
|
specification_version: 4
|
422
423
|
summary: "\U0001F372 A kettle-rb meta tool to streamline development and testing"
|
423
424
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|