kettle-family 1.0.1 → 1.0.2

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: ddbeefcf7d7d90e52b0fadb3f09358c14baaa3eade9b03685e36868bd608e810
4
- data.tar.gz: a75ce0508f27ba21ee30cf7a23fb95b97479ce1f6f03242a0fcc3210b2d2092f
3
+ metadata.gz: 19486d91816150dae28ac5f1e8b31ef3f43b0f4f7004337681f08819fb41b27d
4
+ data.tar.gz: e2bf61a97f739f211accb4fc5cbfe91acc4121077c5f620786d30d217b4cc803
5
5
  SHA512:
6
- metadata.gz: '02850c92673ac9c330561be7e9b7cba733683aa952312cdf17bab8a299e4dbcd002ee9f75c5f08cd68c4650dcfea57399e04713523890822a50ce6278bf0536a'
7
- data.tar.gz: a4b1e30e093fb889d26755250bc035243436a2e272288575991b9fcb83003288b4cb665363633711b20e4c7e1ce13103c7cd038d1b0e721dbd78a805af3ec4c9
6
+ metadata.gz: e8826e083336b3de83e313fc3207c60461e494fc8c1c4ad22b8148b861024ca78adcefa1b5c357d7ed90af79dddb3cda59dc4900434e862739d8d2f930e8e0c3
7
+ data.tar.gz: 1d735e6c84877eab971381d22226c96871e2fa0198bab1d9895bf771abdbbe2d5bf2c69a0d16bd04c0a3cdfdc830c7e7354f526313a5f0b8dbeec2a96df7d908
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -28,11 +28,48 @@ Please file a bug if you notice a violation of semantic versioning.
28
28
 
29
29
  ### Fixed
30
30
 
31
+ ### Security
32
+
33
+ ## [1.0.2] - 2026-07-21
34
+
35
+ - TAG: [v1.0.2][1.0.2t]
36
+ - COVERAGE: 95.51% -- 2637/2761 lines in 23 files
37
+ - BRANCH COVERAGE: 77.98% -- 928/1190 branches in 23 files
38
+ - 28.63% documented
39
+
40
+ ### Added
41
+
42
+ - `kettle-family template` now passes family-level `readme.corporate_sponsors`
43
+ config into member `kettle-jem` runs for template-managed README sponsor logos.
44
+ - `kettle-family state` is now an alias for `kettle-family release-state`.
45
+ - `kettle-family sync` now fetches the remote default branch, rebases the local
46
+ default branch onto it, then rebases the original checked-out branch onto the
47
+ updated local default branch.
48
+
49
+ ### Changed
50
+
51
+ - `kettle-family release-state` now reports the checked-out branch and displays
52
+ release distance as local/remote ahead and behind counts.
53
+ - kettle-jem-template-20260720-001 - Generated READMEs can now render
54
+ template-managed corporate sponsor logos from project or family config.
55
+ - kettle-jem-template-20260720-002 - Generated development Gemfiles now use the
56
+ released `tree_sitter_language_pack` gem 1.13.3 or newer by default.
57
+ - kettle-jem-template-20260720-003 - Generated StructuredMerge Git diff driver
58
+ config now uses the installed `smorg-rb` Ruby driver name.
59
+ - kettle-jem-template-20260720-004 - Generated multi-engine workflow files now
60
+ omit JRuby and TruffleRuby jobs when project config declares MRI-only engines.
61
+ - kettle-jem-template-20260720-005 - Generated README Support & Community rows
62
+ now include a RubyForum help badge.
63
+
64
+ ### Fixed
65
+
66
+ - Default member discovery now excludes benchmark fixture gemspecs so benchmark
67
+ projects are not treated as install/template/release family members.
68
+ - `kettle-family template` now keeps non-verbose `kettle-jem --events` progress
69
+ compact and omits raw NDJSON event streams from failed text reports.
31
70
  - Generated HEAD and runtime dependency HEAD CI workflows no longer include
32
71
  JRuby or TruffleRuby jobs for this MRI-only gem.
33
72
 
34
- ### Security
35
-
36
73
  ## [1.0.1] - 2026-07-20
37
74
 
38
75
  - TAG: [v1.0.1][1.0.1t]
@@ -786,7 +823,9 @@ Please file a bug if you notice a violation of semantic versioning.
786
823
  - Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
787
824
  - Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
788
825
 
789
- [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.0.1...HEAD
826
+ [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.0.2...HEAD
827
+ [1.0.2]: https://github.com/kettle-dev/kettle-family/compare/v1.0.1...v1.0.2
828
+ [1.0.2t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.0.2
790
829
  [1.0.1]: https://github.com/kettle-dev/kettle-family/compare/v1.0.0...v1.0.1
791
830
  [1.0.1t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.0.1
792
831
  [1.0.0]: https://github.com/kettle-dev/kettle-family/compare/v0.2.7...v1.0.0
data/README.md CHANGED
@@ -45,7 +45,7 @@ while RubyGems MFA prompts remain interactive.
45
45
  | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
46
46
  |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
47
47
  | Works with MRI Ruby 4 | [![Ruby current Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf]|
48
- | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
48
+ | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Get help from RubyForum][✉️ruby-forum-img]][✉️ruby-forum] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
49
49
  | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
50
50
  | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitLab Wiki][📜gl-wiki-img]][📜gl-wiki] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] |
51
51
  | Compliance | [![License: AGPL-3.0-only][📄license-img]][📄license] [![Apache license compatibility: Category X][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
@@ -560,6 +560,8 @@ Thanks for RTFM. ☺️
560
560
  [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
561
561
  [✉️ruby-friends-img]: https://img.shields.io/badge/daily.dev-%F0%9F%92%8E_Ruby_Friends-0A0A0A?style=for-the-badge&logo=dailydotdev&logoColor=white
562
562
  [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
563
+ [✉️ruby-forum-img]: https://img.shields.io/badge/RubyForum-Help-CC342D?style=for-the-badge&logo=ruby&logoColor=white
564
+ [✉️ruby-forum]: https://www.rubyforum.org/c/help/8
563
565
 
564
566
  [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
565
567
  [⛳️gem-namespace]: https://github.com/kettle-dev/kettle-family
@@ -667,7 +669,7 @@ Thanks for RTFM. ☺️
667
669
  [📌gitmoji]: https://gitmoji.dev
668
670
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
669
671
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
670
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.655-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
672
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.761-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
671
673
  [🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
672
674
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
673
675
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -10,8 +10,8 @@ module Kettle
10
10
  class CLI < CommandKit::Command
11
11
  include CommandKit::Commands
12
12
 
13
- COMMANDS = %w[discover plan report metadata check test lint docs template gha-sha-pins bup bupb bex install bump bump-version add-changelog release push pull up branch-lanes release-state].freeze
14
- WORKFLOW_COMMANDS = %w[check test lint docs template gha-sha-pins bup bupb bex release push pull up].freeze
13
+ COMMANDS = %w[discover plan report metadata check test lint docs template gha-sha-pins bup bupb bex install bump bump-version add-changelog release push pull sync up branch-lanes release-state state].freeze
14
+ WORKFLOW_COMMANDS = %w[check test lint docs template gha-sha-pins bup bupb bex release push pull sync up].freeze
15
15
 
16
16
  command_name "kettle-family"
17
17
  usage "[options] COMMAND [ARGS...]"
@@ -254,6 +254,16 @@ module Kettle
254
254
  end
255
255
  end
256
256
 
257
+ class State < ReleaseState
258
+ command_name "state"
259
+ description "Alias for release-state."
260
+
261
+ def run(*args)
262
+ unexpected_arguments!(args)
263
+ run_family("release-state")
264
+ end
265
+ end
266
+
257
267
  class WorkflowCommand < BaseCommand
258
268
  include ExecutionOptions
259
269
  include WorkflowOptions
@@ -475,6 +485,12 @@ module Kettle
475
485
  description "Plan or execute git pull --rebase per member."
476
486
  end
477
487
 
488
+ class Sync < WorkflowCommand
489
+ command_name "sync"
490
+ usage "[options]"
491
+ description "Plan or execute default-branch fetch/rebase and branch rebase per member."
492
+ end
493
+
478
494
  class Up < WorkflowCommand
479
495
  command_name "up"
480
496
  usage "[options]"
@@ -501,9 +517,11 @@ module Kettle
501
517
  command Release
502
518
  command Push
503
519
  command Pull
520
+ command Sync
504
521
  command Up
505
522
  command BranchLanes
506
523
  command ReleaseState
524
+ command State
507
525
 
508
526
  prepend ReturningMain
509
527
 
@@ -9,6 +9,8 @@ module Kettle
9
9
  DEFAULT_MEMBER_EXCLUDES = [
10
10
  "vendor/**",
11
11
  "**/vendor/**",
12
+ "benchmarks/**",
13
+ "**/benchmarks/**",
12
14
  "tmp/**",
13
15
  "**/tmp/**",
14
16
  "spec/**",
@@ -190,6 +192,13 @@ module Kettle
190
192
  fetch_path("template", "jobs")
191
193
  end
192
194
 
195
+ def readme_corporate_sponsors
196
+ raw = fetch_path("readme", "corporate_sponsors") ||
197
+ fetch_path("sponsorships", "corporate") ||
198
+ fetch_path("corporate_sponsors")
199
+ normalize_corporate_sponsors(raw)
200
+ end
201
+
193
202
  def normalize_lockfiles?
194
203
  fetch_path("template", "normalize_lockfiles") == true
195
204
  end
@@ -306,6 +315,28 @@ module Kettle
306
315
  .select { |path| File.directory?(path) }
307
316
  end
308
317
 
318
+ def normalize_corporate_sponsors(raw)
319
+ Array(raw).filter_map do |entry|
320
+ unless entry.is_a?(Hash)
321
+ raise ArgumentError, "corporate sponsor entries must be mappings with name, url, and img_src"
322
+ end
323
+
324
+ sponsor = stringify_keys(entry)
325
+ name = sponsor["name"].to_s.strip
326
+ url = sponsor["url"].to_s.strip
327
+ img_src = sponsor["img_src"].to_s.strip
328
+ if name.empty? || url.empty? || img_src.empty?
329
+ raise ArgumentError, "corporate sponsor entries require name, url, and img_src"
330
+ end
331
+
332
+ {
333
+ "name" => name,
334
+ "url" => url,
335
+ "img_src" => img_src
336
+ }
337
+ end
338
+ end
339
+
309
340
  def fetch_path(*keys)
310
341
  keys.reduce(data) do |memo, key|
311
342
  break nil unless memo.is_a?(Hash)
@@ -59,6 +59,7 @@ module Kettle
59
59
  success = status.success?
60
60
  state = success ? JSON.parse(stdout) : {}
61
61
  state = branch_filtered_state(member, state, branch) if success && branch
62
+ state = enrich_git_state(member.root, state) if success
62
63
  result(member: member, command: command, stdout: stdout, stderr: stderr, status: status.exitstatus, elapsed: elapsed, success: success, state: state, branch: branch)
63
64
  rescue JSON::ParserError => error
64
65
  result(member: member, command: command || release_state_command, stdout: stdout, stderr: stderr, status: 1, elapsed: elapsed || 0.0, success: false, state: {}, reason: "invalid release-state JSON: #{error.message}", branch: branch)
@@ -182,6 +183,73 @@ module Kettle
182
183
  status.success?
183
184
  end
184
185
 
186
+ def enrich_git_state(root, state)
187
+ return state unless git_work_tree?(root)
188
+
189
+ enriched = state.dup
190
+ current_branch = git_output(root, "branch", "--show-current")
191
+ enriched["current_branch"] = current_branch unless current_branch.to_s.empty?
192
+
193
+ version = state["latest_released"].to_s.empty? ? state["latest_changelog_version"] : state["latest_released"]
194
+ return enriched if version.to_s.empty?
195
+
196
+ local_default = default_branch(root)
197
+ if local_default
198
+ enriched["default_branch"] = local_default
199
+ if (counts = release_counts_for_ref(root, version, local_default))
200
+ enriched["behind"] = counts.fetch(:behind)
201
+ enriched["ahead"] = counts.fetch(:ahead)
202
+ end
203
+ end
204
+
205
+ remote_default = remote_default_branch(root, local_default)
206
+ if remote_default
207
+ enriched["remote_default_branch"] = remote_default
208
+ if (counts = release_counts_for_ref(root, version, remote_default))
209
+ enriched["remote_behind"] = counts.fetch(:behind)
210
+ enriched["remote_ahead"] = counts.fetch(:ahead)
211
+ end
212
+ end
213
+
214
+ enriched
215
+ end
216
+
217
+ def git_work_tree?(root)
218
+ _stdout, _stderr, status = Open3.capture3("git", "rev-parse", "--is-inside-work-tree", chdir: root)
219
+ status.success?
220
+ end
221
+
222
+ def default_branch(root)
223
+ remote_default = remote_default_branch(root)
224
+ branch = remote_default&.delete_prefix("origin/")
225
+ return branch if branch && git_ref_exists?(root, "refs/heads/#{branch}")
226
+
227
+ %w[main master].find { |name| git_ref_exists?(root, "refs/heads/#{name}") }
228
+ end
229
+
230
+ def remote_default_branch(root, local_default = nil)
231
+ symbolic = git_output(root, "symbolic-ref", "--quiet", "--short", "refs/remotes/origin/HEAD")
232
+ return symbolic if symbolic&.start_with?("origin/")
233
+
234
+ "origin/#{local_default}" if local_default && git_ref_exists?(root, "refs/remotes/origin/#{local_default}")
235
+ end
236
+
237
+ def release_counts_for_ref(root, version, ref)
238
+ tag = release_tag_for_version(root, version)
239
+ return nil unless tag && git_ref_exists?(root, ref)
240
+
241
+ stdout = git_output(root, "rev-list", "--left-right", "--count", "#{tag}...#{ref}")
242
+ parts = stdout.to_s.split
243
+ return nil unless parts.length == 2 && parts.all? { |part| part.match?(/\A\d+\z/) }
244
+
245
+ {behind: parts.fetch(0).to_i, ahead: parts.fetch(1).to_i}
246
+ end
247
+
248
+ def git_output(root, *args)
249
+ stdout, _stderr, status = Open3.capture3("git", *args, chdir: root)
250
+ status.success? ? stdout.strip : nil
251
+ end
252
+
185
253
  def family_changelog_state(root)
186
254
  changelog = File.expand_path(config.changelog_path, root)
187
255
  raise Error, "missing root changelog #{config.changelog_path}" unless File.file?(changelog)
@@ -192,7 +260,7 @@ module Kettle
192
260
  unreleased_entries = unreleased_entries?(content)
193
261
  prepared_release_pending = !version.to_s.empty? && latest_changelog_version == version
194
262
  ahead = commits_ahead_of_release(root, latest_changelog_version)
195
- {
263
+ enrich_git_state(root, {
196
264
  "gem_name" => config.family_name,
197
265
  "version" => version,
198
266
  "latest_released" => nil,
@@ -201,7 +269,7 @@ module Kettle
201
269
  "unreleased_entries" => unreleased_entries,
202
270
  "prepared_release_pending" => prepared_release_pending,
203
271
  "pending_release" => unreleased_entries || prepared_release_pending
204
- }
272
+ })
205
273
  end
206
274
 
207
275
  def root_changelog_version(root)
@@ -20,6 +20,7 @@ module Kettle
20
20
  push
21
21
  release
22
22
  release-state
23
+ sync
23
24
  template
24
25
  test
25
26
  up
@@ -103,7 +104,7 @@ module Kettle
103
104
  lines << "results:"
104
105
  visible_results.each do |result|
105
106
  lines << " #{result_state(result)} #{result.member_name} #{result.phase} #{result.reason || ""}".rstrip
106
- append_indented_output(lines, result.stdout) unless suppress_success_output?(result)
107
+ append_result_stdout(lines, result)
107
108
  append_indented_output(lines, result.stderr) if !result.ok? && !result.stderr.to_s.empty?
108
109
  lines << " resume: #{resume_hint_for(result)}" unless result.ok?
109
110
  end
@@ -158,10 +159,34 @@ module Kettle
158
159
  output.to_s.each_line(chomp: true) { |line| lines << " #{line}" }
159
160
  end
160
161
 
162
+ def append_result_stdout(lines, result)
163
+ return if suppress_success_output?(result)
164
+
165
+ if template_event_stdout?(result)
166
+ append_template_event_failure_summary(lines, result.stdout) unless result.ok?
167
+ else
168
+ append_indented_output(lines, result.stdout)
169
+ end
170
+ end
171
+
161
172
  def suppress_success_output?(result)
162
173
  result.stdout.to_s.empty? || (command == "template" && result.ok?)
163
174
  end
164
175
 
176
+ def template_event_stdout?(result)
177
+ command == "template" && result.phase == "template" && template_events(result.stdout).any?
178
+ end
179
+
180
+ def append_template_event_failure_summary(lines, output)
181
+ diagnostics = template_events(output).filter_map do |event|
182
+ next unless event["type"] == "diagnostic"
183
+
184
+ event["message"].to_s.empty? ? event["kind"].to_s : event["message"].to_s
185
+ end.uniq
186
+ diagnostics.each { |message| lines << " diagnostic: #{message}" unless message.empty? }
187
+ lines << " template event stream omitted from text report"
188
+ end
189
+
165
190
  def append_template_summary(lines)
166
191
  template_results = results.select { |result| result.phase == "template" }
167
192
  return if template_results.empty?
@@ -173,6 +198,9 @@ module Kettle
173
198
  end
174
199
 
175
200
  def template_changed_file_count(result)
201
+ event_count = template_changed_file_count_from_events(result.stdout)
202
+ return event_count if event_count
203
+
176
204
  payload = JSON.parse(result.stdout.to_s)
177
205
  Array(payload["changed_files"] || payload[:changed_files]).length if payload.is_a?(Hash)
178
206
  rescue JSON::ParserError
@@ -182,6 +210,22 @@ module Kettle
182
210
  0
183
211
  end
184
212
 
213
+ def template_changed_file_count_from_events(output)
214
+ summaries = template_events(output).select { |event| event["type"] == "summary" && event.key?("changed_count") }
215
+ return nil if summaries.empty?
216
+
217
+ summaries.sum { |event| event["changed_count"].to_i }
218
+ end
219
+
220
+ def template_events(output)
221
+ output.to_s.each_line.filter_map do |line|
222
+ payload = JSON.parse(line)
223
+ payload if payload.is_a?(Hash) && payload["event_version"]
224
+ rescue JSON::ParserError
225
+ nil
226
+ end
227
+ end
228
+
185
229
  def append_member_release_targets(lines)
186
230
  return if member_release_target_branches.empty?
187
231
 
@@ -313,10 +357,11 @@ module Kettle
313
357
  state = result.state || {}
314
358
  row = [
315
359
  state.fetch("gem_name", result.member_name).to_s,
360
+ state.fetch("current_branch", nil).to_s.empty? ? "unknown" : state.fetch("current_branch").to_s,
316
361
  state.fetch("version", "unknown").to_s,
317
362
  state.fetch("latest_released", nil).to_s.empty? ? "unknown" : state.fetch("latest_released").to_s,
318
363
  state.fetch("latest_changelog_version", nil).to_s.empty? ? "none" : state.fetch("latest_changelog_version").to_s,
319
- state.fetch("ahead", nil).nil? ? "unknown" : state.fetch("ahead").to_s,
364
+ release_state_ahead_behind(state),
320
365
  yes_no(state.fetch("unreleased_entries", nil)),
321
366
  yes_no(state.fetch("prepared_release_pending", nil)),
322
367
  yes_no(state.fetch("pending_release", nil))
@@ -327,12 +372,27 @@ module Kettle
327
372
  end
328
373
 
329
374
  def release_state_header
330
- header = [["gem", "version.rb", "latest released", "latest changelog", "ahead", "unreleased", "prepared", "pending"]]
375
+ header = [["gem", "checkout", "version.rb", "latest released", "latest changelog", "ahead / behind", "unreleased", "prepared", "pending"]]
331
376
  return header unless release_state_has_branches?
332
377
 
333
378
  [["branch", *header.first]]
334
379
  end
335
380
 
381
+ def release_state_ahead_behind(state)
382
+ local_ahead = state.fetch("ahead", nil)
383
+ local_behind = state.fetch("behind", nil)
384
+ return "unknown" if local_ahead.nil? && local_behind.nil?
385
+
386
+ "#{release_state_count(local_ahead, state.fetch("remote_ahead", nil))} / #{release_state_count(local_behind, state.fetch("remote_behind", nil))}"
387
+ end
388
+
389
+ def release_state_count(local_value, remote_value)
390
+ local_text = local_value.nil? ? "unknown" : local_value.to_s
391
+ return local_text if remote_value.nil? || remote_value == local_value
392
+
393
+ "#{local_text} (#{remote_value})"
394
+ end
395
+
336
396
  def release_state_has_branches?
337
397
  results.any? { |result| !result.branch.to_s.empty? }
338
398
  end
@@ -3,7 +3,7 @@
3
3
  module Kettle
4
4
  module Family
5
5
  module Version
6
- VERSION = "1.0.1"
6
+ VERSION = "1.0.2"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
@@ -16,6 +16,36 @@ module Kettle
16
16
  "lint" => "bundle exec rake rubocop_gradual",
17
17
  "docs" => "bundle exec rake yard",
18
18
  "gha-sha-pins" => "bundle exec kettle-gha-sha-pins",
19
+ "sync" => [
20
+ "sh",
21
+ "-lc",
22
+ <<~SH
23
+ set -e
24
+ current_branch=$(git branch --show-current)
25
+ if [ -z "$current_branch" ]; then
26
+ echo "kettle-family sync requires a named branch checkout" >&2
27
+ exit 1
28
+ fi
29
+ default_ref=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true)
30
+ default_branch=${default_ref#origin/}
31
+ if [ -z "$default_branch" ] || [ "$default_branch" = "$default_ref" ]; then
32
+ default_branch=$(git remote show origin | awk '/HEAD branch:/ { print $NF; exit }')
33
+ fi
34
+ if [ -z "$default_branch" ]; then
35
+ echo "could not determine origin default branch" >&2
36
+ exit 1
37
+ fi
38
+ git fetch origin "$default_branch"
39
+ if [ "$current_branch" != "$default_branch" ]; then
40
+ git switch "$default_branch"
41
+ fi
42
+ git rebase "origin/$default_branch"
43
+ if [ "$current_branch" != "$default_branch" ]; then
44
+ git switch "$current_branch"
45
+ git rebase "$default_branch"
46
+ fi
47
+ SH
48
+ ],
19
49
  "bupb" => %w[bundle update --bundler]
20
50
  }.freeze
21
51
  GIT_SYNC_COMMANDS = {
@@ -952,6 +982,10 @@ module Kettle
952
982
  if command == "template"
953
983
  env["KETTLE_JEM_TEMPLATE_PROFILE"] = config.template_profile if config.template_profile
954
984
  env["KJ_REPOSITORY_TOPOLOGY"] = config.template_repository_topology if config.template_repository_topology
985
+ corporate_sponsors = config.readme_corporate_sponsors
986
+ unless corporate_sponsors.empty?
987
+ env["KETTLE_JEM_CORPORATE_SPONSORS_JSON"] = JSON.generate(corporate_sponsors)
988
+ end
955
989
  end
956
990
  env.merge!(env_overrides)
957
991
  if command == "template" && verbose
@@ -994,6 +1028,7 @@ module Kettle
994
1028
 
995
1029
  def template_event_line_handler(member)
996
1030
  return nil unless progress_io
1031
+ return nil unless verbose || debug
997
1032
 
998
1033
  lambda do |line|
999
1034
  event = parse_template_event(line)
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kettle-family
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -303,10 +303,10 @@ licenses:
303
303
  - AGPL-3.0-only
304
304
  metadata:
305
305
  homepage_uri: https://kettle-family.galtzo.com
306
- source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.0.1
307
- changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.0.1/CHANGELOG.md
306
+ source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.0.2
307
+ changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.0.2/CHANGELOG.md
308
308
  bug_tracker_uri: https://github.com/kettle-dev/kettle-family/issues
309
- documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.0.1
309
+ documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.0.2
310
310
  funding_uri: https://github.com/sponsors/pboling
311
311
  wiki_uri: https://github.com/kettle-dev/kettle-family/wiki
312
312
  news_uri: https://www.railsbling.com/tags/kettle-family
metadata.gz.sig CHANGED
Binary file