kettle-dev 1.0.23 → 1.0.24
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/.github/workflows/style.yml +3 -3
- data/.github/workflows/truffle.yml +3 -3
- data/CHANGELOG.md +72 -47
- data/README.md +9 -12
- data/README.md.example +10 -6
- data/Rakefile.example +1 -1
- data/exe/kettle-changelog +23 -351
- data/exe/kettle-commit-msg +26 -5
- data/exe/kettle-readme-backers +25 -4
- data/exe/kettle-release +14 -5
- data/kettle-dev.gemspec.example +2 -2
- data/lib/kettle/dev/changelog_cli.rb +352 -0
- data/lib/kettle/dev/ci_monitor.rb +0 -5
- data/lib/kettle/dev/git_commit_footer.rb +0 -2
- data/lib/kettle/dev/readme_backers.rb +0 -1
- data/lib/kettle/dev/release_cli.rb +10 -11
- data/lib/kettle/dev/tasks/ci_task.rb +14 -27
- data/lib/kettle/dev/tasks/install_task.rb +0 -3
- data/lib/kettle/dev/tasks/template_task.rb +0 -3
- data/lib/kettle/dev/template_helpers.rb +9 -2
- data/lib/kettle/dev/version.rb +1 -1
- data/lib/kettle/dev.rb +8 -3
- data.tar.gz.sig +0 -0
- metadata +5 -4
- metadata.gz.sig +0 -0
data/exe/kettle-changelog
CHANGED
@@ -24,361 +24,24 @@ $stdout.sync = true
|
|
24
24
|
# Depending library or project must be using bundler
|
25
25
|
require "bundler/setup"
|
26
26
|
|
27
|
-
|
28
|
-
require "time"
|
29
|
-
require "open3"
|
30
|
-
require "shellwords"
|
27
|
+
script_basename = File.basename(__FILE__)
|
31
28
|
|
32
29
|
begin
|
30
|
+
# Standard library
|
31
|
+
require "json"
|
32
|
+
require "time"
|
33
|
+
require "open3"
|
34
|
+
require "shellwords"
|
35
|
+
|
36
|
+
# This library
|
33
37
|
require "kettle/dev"
|
38
|
+
puts "== #{script_basename} v#{Kettle::Dev::Version::VERSION} =="
|
34
39
|
rescue LoadError => e
|
35
|
-
warn("
|
36
|
-
warn("Hint: Ensure the host project
|
40
|
+
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
41
|
+
warn("Hint: Ensure the host project has kettle-dev as a dependency and run bundle install.")
|
37
42
|
exit(1)
|
38
43
|
end
|
39
44
|
|
40
|
-
require "kettle/dev/versioning"
|
41
|
-
|
42
|
-
puts "== kettle-changelog v#{Kettle::Dev::Version::VERSION} =="
|
43
|
-
|
44
|
-
module Kettle
|
45
|
-
module Dev
|
46
|
-
class ChangelogCLI
|
47
|
-
def initialize
|
48
|
-
@root = Kettle::Dev::CIHelpers.project_root
|
49
|
-
@changelog_path = File.join(@root, "CHANGELOG.md")
|
50
|
-
@coverage_path = File.join(@root, "coverage", "coverage.json")
|
51
|
-
end
|
52
|
-
|
53
|
-
def run
|
54
|
-
version = Kettle::Dev::Versioning.detect_version(@root)
|
55
|
-
today = Time.now.strftime("%Y-%m-%d")
|
56
|
-
owner, repo = Kettle::Dev::CIHelpers.repo_info
|
57
|
-
unless owner && repo
|
58
|
-
warn("Could not determine GitHub owner/repo from origin remote.")
|
59
|
-
warn("Make sure 'origin' points to github.com. Alternatively, set origin or update links manually afterward.")
|
60
|
-
end
|
61
|
-
|
62
|
-
line_cov_line, branch_cov_line = coverage_lines
|
63
|
-
yard_line = yard_percent_documented
|
64
|
-
|
65
|
-
changelog = File.read(@changelog_path)
|
66
|
-
|
67
|
-
# If the detected version already exists in the changelog, abort to avoid duplicates
|
68
|
-
if changelog =~ /^## \[#{Regexp.escape(version)}\]/
|
69
|
-
abort("CHANGELOG.md already has a section for version #{version}. Bump version.rb or remove the duplicate.")
|
70
|
-
end
|
71
|
-
|
72
|
-
unreleased_block, before, after = extract_unreleased(changelog)
|
73
|
-
if unreleased_block.nil?
|
74
|
-
abort("Could not find '## [Unreleased]' section in CHANGELOG.md")
|
75
|
-
end
|
76
|
-
|
77
|
-
if unreleased_block.strip.empty?
|
78
|
-
warn("No entries found under Unreleased. Creating an empty version section anyway.")
|
79
|
-
end
|
80
|
-
|
81
|
-
prev_version = detect_previous_version(after)
|
82
|
-
|
83
|
-
new_section = +""
|
84
|
-
new_section << "## [#{version}] - #{today}\n"
|
85
|
-
new_section << "- TAG: [v#{version}][#{version}t]\n"
|
86
|
-
new_section << "- #{line_cov_line}\n" if line_cov_line
|
87
|
-
new_section << "- #{branch_cov_line}\n" if branch_cov_line
|
88
|
-
new_section << "- #{yard_line}\n" if yard_line
|
89
|
-
new_section << filter_unreleased_sections(unreleased_block)
|
90
|
-
# Ensure exactly one blank line separates this new section from the next section
|
91
|
-
new_section.rstrip!
|
92
|
-
new_section << "\n\n"
|
93
|
-
|
94
|
-
# Reset the Unreleased section to empty category headings
|
95
|
-
unreleased_reset = <<~MD
|
96
|
-
## [Unreleased]
|
97
|
-
### Added
|
98
|
-
### Changed
|
99
|
-
### Deprecated
|
100
|
-
### Removed
|
101
|
-
### Fixed
|
102
|
-
### Security
|
103
|
-
MD
|
104
|
-
|
105
|
-
updated = before + unreleased_reset + "\n" + new_section + after
|
106
|
-
|
107
|
-
updated = update_link_refs(updated, owner, repo, prev_version, version)
|
108
|
-
|
109
|
-
# Ensure exactly one trailing newline at EOF
|
110
|
-
updated = updated.rstrip + "\n"
|
111
|
-
|
112
|
-
File.write(@changelog_path, updated)
|
113
|
-
puts "CHANGELOG.md updated with v#{version} section."
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
def abort(msg)
|
119
|
-
Kettle::Dev::ExitAdapter.abort(msg)
|
120
|
-
rescue NameError
|
121
|
-
Kernel.abort(msg)
|
122
|
-
end
|
123
|
-
|
124
|
-
def detect_version
|
125
|
-
candidates = Dir[File.join(@root, "lib", "**", "version.rb")]
|
126
|
-
abort("Could not find version.rb under lib/**.") if candidates.empty?
|
127
|
-
versions = candidates.map do |path|
|
128
|
-
content = File.read(path)
|
129
|
-
m = content.match(/VERSION\s*=\s*(["'])([^"']+)\1/)
|
130
|
-
next unless m
|
131
|
-
m[2]
|
132
|
-
end.compact
|
133
|
-
abort("VERSION constant not found in #{@root}/lib/**/version.rb") if versions.none?
|
134
|
-
abort("Multiple VERSION constants found to be out of sync (#{versions.inspect}) in #{@root}/lib/**/version.rb") unless versions.uniq.length == 1
|
135
|
-
versions.first
|
136
|
-
end
|
137
|
-
|
138
|
-
def extract_unreleased(content)
|
139
|
-
lines = content.lines
|
140
|
-
start_i = lines.index { |l| l.start_with?("## [Unreleased]") }
|
141
|
-
return [nil, nil, nil] unless start_i
|
142
|
-
# Find the next version heading after Unreleased
|
143
|
-
next_i = (start_i + 1)
|
144
|
-
while next_i < lines.length && !lines[next_i].start_with?("## [")
|
145
|
-
next_i += 1
|
146
|
-
end
|
147
|
-
# Now next_i points to the next section heading or EOF
|
148
|
-
before = lines[0..(start_i - 1)].join
|
149
|
-
unreleased_block = lines[(start_i + 1)..(next_i - 1)].join
|
150
|
-
after = lines[next_i..-1]&.join || ""
|
151
|
-
[unreleased_block, before, after]
|
152
|
-
end
|
153
|
-
|
154
|
-
def detect_previous_version(after_text)
|
155
|
-
# after_text begins with the first released section following Unreleased
|
156
|
-
m = after_text.match(/^## \[(\d+\.\d+\.\d+)\]/)
|
157
|
-
return m[1] if m
|
158
|
-
nil
|
159
|
-
end
|
160
|
-
|
161
|
-
# From the Unreleased block, keep only sections that have content.
|
162
|
-
# We detect sections as lines starting with '### '. A section has content if there is at least
|
163
|
-
# one non-empty, non-heading line under it before the next '###' or '##'. Typically these are list items.
|
164
|
-
# Returns a string that includes only the non-empty sections with their content.
|
165
|
-
def filter_unreleased_sections(unreleased_block)
|
166
|
-
lines = unreleased_block.lines
|
167
|
-
out = []
|
168
|
-
i = 0
|
169
|
-
while i < lines.length
|
170
|
-
line = lines[i]
|
171
|
-
if line.start_with?("### ")
|
172
|
-
header = line
|
173
|
-
i += 1
|
174
|
-
chunk = []
|
175
|
-
while i < lines.length && !lines[i].start_with?("### ") && !lines[i].start_with?("## ")
|
176
|
-
chunk << lines[i]
|
177
|
-
i += 1
|
178
|
-
end
|
179
|
-
# Determine if chunk has any content (non-blank)
|
180
|
-
content_present = chunk.any? { |l| l.strip != "" }
|
181
|
-
if content_present
|
182
|
-
# Trim trailing blank lines
|
183
|
-
while chunk.any? && chunk.last.strip == ""
|
184
|
-
chunk.pop
|
185
|
-
end
|
186
|
-
out << header
|
187
|
-
out.concat(chunk)
|
188
|
-
out << "\n" unless out.last&.end_with?("\n")
|
189
|
-
end
|
190
|
-
next
|
191
|
-
else
|
192
|
-
# Lines outside sections are ignored for released sections
|
193
|
-
i += 1
|
194
|
-
end
|
195
|
-
end
|
196
|
-
out.join
|
197
|
-
end
|
198
|
-
|
199
|
-
def coverage_lines
|
200
|
-
unless File.file?(@coverage_path)
|
201
|
-
warn("Coverage JSON not found at #{@coverage_path}.")
|
202
|
-
warn("Run: K_SOUP_COV_FORMATTERS=\"json\" bin/rspec")
|
203
|
-
return [nil, nil]
|
204
|
-
end
|
205
|
-
data = JSON.parse(File.read(@coverage_path))
|
206
|
-
files = data["coverage"] || {}
|
207
|
-
file_count = 0
|
208
|
-
total_lines = 0
|
209
|
-
covered_lines = 0
|
210
|
-
total_branches = 0
|
211
|
-
covered_branches = 0
|
212
|
-
files.each_value do |h|
|
213
|
-
lines = h["lines"] || []
|
214
|
-
line_relevant = lines.count { |x| x.is_a?(Integer) }
|
215
|
-
line_covered = lines.count { |x| x.is_a?(Integer) && x > 0 }
|
216
|
-
if line_relevant > 0
|
217
|
-
file_count += 1
|
218
|
-
total_lines += line_relevant
|
219
|
-
covered_lines += line_covered
|
220
|
-
end
|
221
|
-
branches = h["branches"] || []
|
222
|
-
branches.each do |b|
|
223
|
-
next unless b.is_a?(Hash)
|
224
|
-
cov = b["coverage"]
|
225
|
-
next unless cov.is_a?(Numeric)
|
226
|
-
total_branches += 1
|
227
|
-
covered_branches += 1 if cov > 0
|
228
|
-
end
|
229
|
-
end
|
230
|
-
line_pct = (total_lines > 0) ? ((covered_lines.to_f / total_lines) * 100.0) : 0.0
|
231
|
-
branch_pct = (total_branches > 0) ? ((covered_branches.to_f / total_branches) * 100.0) : 0.0
|
232
|
-
line_str = format("COVERAGE: %.2f%% -- %d/%d lines in %d files", line_pct, covered_lines, total_lines, file_count)
|
233
|
-
branch_str = format("BRANCH COVERAGE: %.2f%% -- %d/%d branches in %d files", branch_pct, covered_branches, total_branches, file_count)
|
234
|
-
[line_str, branch_str]
|
235
|
-
rescue StandardError => e
|
236
|
-
warn("Failed to parse coverage: #{e.class}: #{e.message}")
|
237
|
-
[nil, nil]
|
238
|
-
end
|
239
|
-
|
240
|
-
def yard_percent_documented
|
241
|
-
cmd = File.join(@root, "bin", "yard")
|
242
|
-
unless File.executable?(cmd)
|
243
|
-
warn("bin/yard not found or not executable; ensure yard is installed via bundler")
|
244
|
-
return
|
245
|
-
end
|
246
|
-
out, _ = Open3.capture2(cmd)
|
247
|
-
# Look for a line containing e.g., "95.35% documented"
|
248
|
-
line = out.lines.find { |l| l =~ /\d+(?:\.\d+)?%\s+documented/ }
|
249
|
-
if line
|
250
|
-
line = line.strip
|
251
|
-
# Return exactly as requested: e.g. "95.35% documented"
|
252
|
-
line
|
253
|
-
else
|
254
|
-
warn("Could not find documented percentage in bin/yard output.")
|
255
|
-
nil
|
256
|
-
end
|
257
|
-
rescue StandardError => e
|
258
|
-
warn("Failed to run bin/yard: #{e.class}: #{e.message}")
|
259
|
-
nil
|
260
|
-
end
|
261
|
-
|
262
|
-
def update_link_refs(content, owner, repo, prev_version, new_version)
|
263
|
-
# Convert any GitLab links to GitHub
|
264
|
-
content = content.gsub(%r{https://gitlab\.com/([^/]+)/([^/]+)/-/compare/([^\.]+)\.\.\.([^\s]+)}) do
|
265
|
-
o = owner || Regexp.last_match(1)
|
266
|
-
r = repo || Regexp.last_match(2)
|
267
|
-
from = Regexp.last_match(3)
|
268
|
-
to = Regexp.last_match(4)
|
269
|
-
"https://github.com/#{o}/#{r}/compare/#{from}...#{to}"
|
270
|
-
end
|
271
|
-
content = content.gsub(%r{https://gitlab\.com/([^/]+)/([^/]+)/-/tags/(v[^\s\]]+)}) do
|
272
|
-
o = owner || Regexp.last_match(1)
|
273
|
-
r = repo || Regexp.last_match(2)
|
274
|
-
tag = Regexp.last_match(3)
|
275
|
-
"https://github.com/#{o}/#{r}/releases/tag/#{tag}"
|
276
|
-
end
|
277
|
-
|
278
|
-
# Append or update the bottom reference links
|
279
|
-
lines = content.lines
|
280
|
-
|
281
|
-
# Find the index of the Unreleased heading; only manipulate refs after this point
|
282
|
-
unreleased_idx = lines.index { |l| l.start_with?("## [Unreleased]") } || -1
|
283
|
-
|
284
|
-
# Find the first link-ref line (e.g., "[Unreleased]: http...") AFTER Unreleased
|
285
|
-
first_ref = nil
|
286
|
-
lines.each_with_index do |l, i|
|
287
|
-
if l =~ /^\[[^\]]+\]:\s+http/ && i > unreleased_idx
|
288
|
-
first_ref = i
|
289
|
-
break
|
290
|
-
end
|
291
|
-
end
|
292
|
-
unless first_ref
|
293
|
-
# Append at end if no ref block after Unreleased
|
294
|
-
first_ref = lines.length
|
295
|
-
lines << "\n"
|
296
|
-
end
|
297
|
-
|
298
|
-
# Ensure Unreleased points to GitHub compare from new tag to HEAD
|
299
|
-
if owner && repo
|
300
|
-
unreleased_ref = "[Unreleased]: https://github.com/#{owner}/#{repo}/compare/v#{new_version}...HEAD\n"
|
301
|
-
# Update an existing Unreleased ref only if it appears after Unreleased heading; otherwise append
|
302
|
-
idx = nil
|
303
|
-
lines.each_with_index do |l, i|
|
304
|
-
if l.start_with?("[Unreleased]:") && i >= first_ref
|
305
|
-
idx = i
|
306
|
-
break
|
307
|
-
end
|
308
|
-
end
|
309
|
-
if idx
|
310
|
-
lines[idx] = unreleased_ref
|
311
|
-
else
|
312
|
-
lines << unreleased_ref
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
if owner && repo
|
317
|
-
# Add compare link for the new version
|
318
|
-
from = prev_version ? "v#{prev_version}" : detect_initial_compare_base(lines)
|
319
|
-
new_compare = "[#{new_version}]: https://github.com/#{owner}/#{repo}/compare/#{from}...v#{new_version}\n"
|
320
|
-
unless lines.any? { |l| l.start_with?("[#{new_version}]:") }
|
321
|
-
lines << new_compare
|
322
|
-
end
|
323
|
-
# Add tag link for the new version
|
324
|
-
new_tag = "[#{new_version}t]: https://github.com/#{owner}/#{repo}/releases/tag/v#{new_version}\n"
|
325
|
-
unless lines.any? { |l| l.start_with?("[#{new_version}t]:") }
|
326
|
-
lines << new_tag
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
# Rebuild and sort the reference block so newest is at the bottom, preserving everything above first_ref
|
331
|
-
ref_lines = lines[first_ref..-1].select { |l| l =~ /^\[[^\]]+\]:\s+http/ }
|
332
|
-
# Deduplicate by key (text inside the square brackets)
|
333
|
-
by_key = {}
|
334
|
-
ref_lines.each do |l|
|
335
|
-
if l =~ /^\[([^\]]+)\]:\s+/
|
336
|
-
by_key[$1] = l
|
337
|
-
end
|
338
|
-
end
|
339
|
-
unreleased_line = by_key.delete("Unreleased")
|
340
|
-
# Separate version compare and tag links
|
341
|
-
compares = {}
|
342
|
-
tags = {}
|
343
|
-
by_key.each do |k, v|
|
344
|
-
if k =~ /^(\d+\.\d+\.\d+)$/
|
345
|
-
compares[$1] = v
|
346
|
-
elsif k =~ /^(\d+\.\d+\.\d+)t$/
|
347
|
-
tags[$1] = v
|
348
|
-
end
|
349
|
-
end
|
350
|
-
# Sort versions ascending so newest at bottom
|
351
|
-
sorted_versions = compares.keys.map { |s| Gem::Version.new(s) }.sort.map(&:to_s)
|
352
|
-
# In case some versions only have tags or only compares, include them as well
|
353
|
-
(tags.keys - compares.keys).each { |s| sorted_versions |= [s] }
|
354
|
-
sorted_versions = sorted_versions.map { |s| Gem::Version.new(s) }.sort.map(&:to_s)
|
355
|
-
|
356
|
-
new_ref_block = []
|
357
|
-
new_ref_block << unreleased_line if unreleased_line
|
358
|
-
sorted_versions.each do |v|
|
359
|
-
new_ref_block << compares[v] if compares[v]
|
360
|
-
new_ref_block << tags[v] if tags[v]
|
361
|
-
end
|
362
|
-
# Replace the old block
|
363
|
-
rebuilt = lines[0...first_ref] + new_ref_block + ["\n"]
|
364
|
-
rebuilt.join
|
365
|
-
end
|
366
|
-
|
367
|
-
def detect_initial_compare_base(lines)
|
368
|
-
# Fallback when prev_version is unknown: try to find the first compare base used historically
|
369
|
-
# e.g., for 1.0.0 it may be a commit SHA instead of a tag
|
370
|
-
ref = lines.find { |l| l =~ /^\[1\.0\.0\]:\s+https:\/\/github\.com\// }
|
371
|
-
if ref && (m = ref.match(%r{compare/([^\.]+)\.\.\.v\d+})).is_a?(MatchData)
|
372
|
-
m[1]
|
373
|
-
else
|
374
|
-
# Default to previous tag name if none found (unlikely to be correct, but better than empty)
|
375
|
-
"HEAD^"
|
376
|
-
end
|
377
|
-
end
|
378
|
-
end
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
45
|
begin
|
383
46
|
if ARGV.include?("-h") || ARGV.include?("--help")
|
384
47
|
puts <<~USAGE
|
@@ -394,11 +57,20 @@ begin
|
|
394
57
|
USAGE
|
395
58
|
exit(0)
|
396
59
|
end
|
60
|
+
end
|
61
|
+
|
62
|
+
begin
|
397
63
|
Kettle::Dev::ChangelogCLI.new.run
|
398
|
-
rescue
|
64
|
+
rescue LoadError => e
|
65
|
+
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
66
|
+
warn(e.backtrace.join("\n")) if ENV["DEBUG"]
|
67
|
+
exit(1)
|
68
|
+
rescue SystemExit => e
|
69
|
+
# Preserve exit status, but ensure at least a newline so shells don't show an empty line only.
|
70
|
+
warn("#{script_basename}: exited (status=#{e.status}, msg=#{e.message})") if e.status != 0
|
399
71
|
raise
|
400
72
|
rescue StandardError => e
|
401
|
-
warn("
|
402
|
-
warn(e.backtrace.join("\n"))
|
73
|
+
warn("#{script_basename}: unexpected error: #{e.class}: #{e.message}")
|
74
|
+
warn(e.backtrace.join("\n"))
|
403
75
|
exit(1)
|
404
76
|
end
|
data/exe/kettle-commit-msg
CHANGED
@@ -8,12 +8,19 @@ $stdout.sync = true
|
|
8
8
|
# Depending library or project must be using bundler
|
9
9
|
require "bundler/setup"
|
10
10
|
|
11
|
-
|
12
|
-
require "erb"
|
11
|
+
script_basename = File.basename(__FILE__)
|
13
12
|
|
14
|
-
|
13
|
+
begin
|
14
|
+
# Standard library
|
15
|
+
require "erb"
|
15
16
|
|
16
|
-
|
17
|
+
require "kettle/dev"
|
18
|
+
puts "== #{script_basename} v#{Kettle::Dev::Version::VERSION} =="
|
19
|
+
rescue LoadError => e
|
20
|
+
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
21
|
+
warn("Hint: Ensure the host project has kettle-dev as a dependency and run bundle install.")
|
22
|
+
exit(1)
|
23
|
+
end
|
17
24
|
|
18
25
|
# ENV variable control (set in .envrc, or .env.local)
|
19
26
|
# BRANCH_RULE_TYPE = jira, or another type of branch rule validation, or false to disable
|
@@ -52,4 +59,18 @@ else
|
|
52
59
|
# puts "No branch rule configured (set GIT_HOOK_BRANCH_VALIDATE=jira to enforce rules for jira style branch names)"
|
53
60
|
end
|
54
61
|
|
55
|
-
|
62
|
+
begin
|
63
|
+
Kettle::Dev::GitCommitFooter.render(*ARGV)
|
64
|
+
rescue LoadError => e
|
65
|
+
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
66
|
+
warn(e.backtrace.join("\n")) if ENV["DEBUG"]
|
67
|
+
exit(1)
|
68
|
+
rescue SystemExit => e
|
69
|
+
# Preserve exit status, but ensure at least a newline so shells don't show an empty line only.
|
70
|
+
warn("#{script_basename}: exited (status=#{e.status}, msg=#{e.message})") if e.status != 0
|
71
|
+
raise
|
72
|
+
rescue StandardError => e
|
73
|
+
warn("#{script_basename}: unexpected error: #{e.class}: #{e.message}")
|
74
|
+
warn(e.backtrace.join("\n"))
|
75
|
+
exit(1)
|
76
|
+
end
|
data/exe/kettle-readme-backers
CHANGED
@@ -5,11 +5,32 @@
|
|
5
5
|
|
6
6
|
# Immediate, unbuffered output
|
7
7
|
$stdout.sync = true
|
8
|
-
#
|
8
|
+
# Depending library or project must be using bundler
|
9
9
|
require "bundler/setup"
|
10
10
|
|
11
|
-
|
11
|
+
script_basename = File.basename(__FILE__)
|
12
12
|
|
13
|
-
|
13
|
+
begin
|
14
|
+
require "kettle/dev"
|
15
|
+
puts "== #{script_basename} v#{Kettle::Dev::Version::VERSION} =="
|
16
|
+
rescue LoadError => e
|
17
|
+
warn("kettle/dev: failed to load: #{e.message}")
|
18
|
+
warn("Hint: Ensure the host project has kettle-dev as a dependency and run bundle install.")
|
19
|
+
exit(1)
|
20
|
+
end
|
14
21
|
|
15
|
-
|
22
|
+
begin
|
23
|
+
Kettle::Dev::ReadmeBackers.new.run!
|
24
|
+
rescue LoadError => e
|
25
|
+
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
26
|
+
warn(e.backtrace.join("\n")) if ENV["DEBUG"]
|
27
|
+
exit(1)
|
28
|
+
rescue SystemExit => e
|
29
|
+
# Preserve exit status, but ensure at least a newline so shells don't show an empty line only.
|
30
|
+
warn("#{script_basename}: exited (status=#{e.status}, msg=#{e.message})") if e.status != 0
|
31
|
+
raise
|
32
|
+
rescue StandardError => e
|
33
|
+
warn("#{script_basename}: unexpected error: #{e.class}: #{e.message}")
|
34
|
+
warn(e.backtrace.join("\n"))
|
35
|
+
exit(1)
|
36
|
+
end
|
data/exe/kettle-release
CHANGED
@@ -19,7 +19,16 @@ $stdout.sync = true
|
|
19
19
|
# Depending library or project must be using bundler
|
20
20
|
require "bundler/setup"
|
21
21
|
|
22
|
-
|
22
|
+
script_basename = File.basename(__FILE__)
|
23
|
+
|
24
|
+
begin
|
25
|
+
require "kettle/dev"
|
26
|
+
puts "== #{script_basename} v#{Kettle::Dev::Version::VERSION} =="
|
27
|
+
rescue LoadError => e
|
28
|
+
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
29
|
+
warn("Hint: Ensure the host project has kettle-dev as a dependency and run bundle install.")
|
30
|
+
exit(1)
|
31
|
+
end
|
23
32
|
|
24
33
|
# Always execute when this file is loaded (e.g., via a Bundler binstub).
|
25
34
|
# Do not guard with __FILE__ == $PROGRAM_NAME because binstubs use Kernel.load.
|
@@ -48,22 +57,22 @@ if ARGV.include?("-h") || ARGV.include?("--help")
|
|
48
57
|
exit 0
|
49
58
|
end
|
50
59
|
|
51
|
-
puts "== kettle-release v#{Kettle::Dev::Version::VERSION} =="
|
52
60
|
# Parse start_step=<n> from ARGV
|
53
61
|
start_step_arg = ARGV.find { |a| a.start_with?("start_step=") }
|
54
62
|
start_step = start_step_arg ? start_step_arg.split("=", 2)[1].to_i : 1
|
63
|
+
|
55
64
|
begin
|
56
65
|
Kettle::Dev::ReleaseCLI.new(start_step: start_step).run
|
57
66
|
rescue LoadError => e
|
58
|
-
warn("
|
67
|
+
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
59
68
|
warn(e.backtrace.join("\n")) if ENV["DEBUG"]
|
60
69
|
exit(1)
|
61
70
|
rescue SystemExit => e
|
62
71
|
# Preserve exit status, but ensure at least a newline so shells don't show an empty line only.
|
63
|
-
warn("
|
72
|
+
warn("#{script_basename}: exited (status=#{e.status}, msg=#{e.message})") if e.status != 0
|
64
73
|
raise
|
65
74
|
rescue StandardError => e
|
66
|
-
warn("
|
75
|
+
warn("#{script_basename}: unexpected error: #{e.class}: #{e.message}")
|
67
76
|
warn(e.backtrace.join("\n"))
|
68
77
|
exit(1)
|
69
78
|
end
|
data/kettle-dev.gemspec.example
CHANGED
@@ -67,8 +67,8 @@ Gem::Specification.new do |spec|
|
|
67
67
|
# Signatures
|
68
68
|
"sig/**/*.rbs",
|
69
69
|
]
|
70
|
-
|
71
|
-
#
|
70
|
+
|
71
|
+
# Automatically included with gem package, no need to list again in files.
|
72
72
|
spec.extra_rdoc_files = Dir[
|
73
73
|
# Files (alphabetical)
|
74
74
|
"CHANGELOG.md",
|