kettle-family 1.2.94 → 1.2.96
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/CHANGELOG.md +33 -1
- data/README.md +18 -1
- data/lib/kettle/family/cli.rb +28 -10
- data/lib/kettle/family/discovery.rb +10 -3
- data/lib/kettle/family/release_state_check.rb +14 -11
- data/lib/kettle/family/release_state_event_tape.rb +12 -6
- data/lib/kettle/family/version.rb +1 -1
- data/lib/kettle/family/workflow.rb +138 -45
- data/lib/kettle/family/workflow_progress.rb +39 -38
- data.tar.gz.sig +0 -0
- metadata +20 -20
- 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: d2f776638603414ab6c27f457473dea3f6088bae63f58a45fcbc0f165fe0e026
|
|
4
|
+
data.tar.gz: b44e74efb8e840e929df24573b815df7b7a749f27e67f86f76561ab654b406ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 77f9c29784b453d8d270398c675ed52e18d8ba5f374fc8add80465bce88f59a679ab254080e3fe349685bff16134bb97541ef087d5c32116123c95e443b64685
|
|
7
|
+
data.tar.gz: 4e750df4e8f1f7f92ee8a653bac8ed02a95ee7ddfa5daa8f8eef92003b78e2c58c93b41498b0b93f8649626dcaf3a645f36fdedabf78928e35653131f14431c3
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,34 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [1.2.96] - 2026-09-08
|
|
34
|
+
|
|
35
|
+
- TAG: [v1.2.96][1.2.96t]
|
|
36
|
+
- COVERAGE: 93.49% -- 6235/6669 lines in 35 files
|
|
37
|
+
- BRANCH COVERAGE: 77.99% -- 2523/3235 branches in 35 files
|
|
38
|
+
- 32.75% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Render branch-worktree template events in distinct live progress rows.
|
|
43
|
+
|
|
44
|
+
- Run release-state branch targets concurrently and render distinct branch progress rows.
|
|
45
|
+
|
|
46
|
+
- Preserve configured release waves for ordinary sibling members when another member has release-target branches.
|
|
47
|
+
|
|
48
|
+
- Restore the version_gem runtime dependency and preserve worktree integration documentation during template updates.
|
|
49
|
+
|
|
50
|
+
## [1.2.95] - 2026-09-07
|
|
51
|
+
|
|
52
|
+
- TAG: [v1.2.95][1.2.95t]
|
|
53
|
+
- COVERAGE: 93.49% -- 6199/6631 lines in 35 files
|
|
54
|
+
- BRANCH COVERAGE: 78.03% -- 2515/3223 branches in 35 files
|
|
55
|
+
- 32.58% documented
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- Run release-target branch worktrees through the full template bootstrap workflow before member preparation.
|
|
60
|
+
|
|
33
61
|
## [1.2.94] - 2026-09-07
|
|
34
62
|
|
|
35
63
|
- TAG: [v1.2.94][1.2.94t]
|
|
@@ -2640,7 +2668,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
2640
2668
|
- Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
|
|
2641
2669
|
- Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
|
|
2642
2670
|
|
|
2643
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.2.
|
|
2671
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.2.96...HEAD
|
|
2672
|
+
[1.2.96]: https://github.com/kettle-dev/kettle-family/compare/v1.2.95...v1.2.96
|
|
2673
|
+
[1.2.96t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.2.96
|
|
2674
|
+
[1.2.95]: https://github.com/kettle-dev/kettle-family/compare/v1.2.94...v1.2.95
|
|
2675
|
+
[1.2.95t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.2.95
|
|
2644
2676
|
[1.2.94]: https://github.com/kettle-dev/kettle-family/compare/v1.2.93...v1.2.94
|
|
2645
2677
|
[1.2.94t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.2.94
|
|
2646
2678
|
[1.2.93]: https://github.com/kettle-dev/kettle-family/compare/v1.2.92...v1.2.93
|
data/README.md
CHANGED
|
@@ -902,6 +902,23 @@ the template dependency graph. It must not invoke release-lockfile reset logic:
|
|
|
902
902
|
release normalization intentionally disables local paths, while template
|
|
903
903
|
recovery needs configured sibling paths to resolve unreleased family versions.
|
|
904
904
|
|
|
905
|
+
### Branch Worktree Equivalence
|
|
906
|
+
|
|
907
|
+
A release-target branch worktree is a separate checkout of the same template
|
|
908
|
+
member, not a reduced template workflow. Before its member template body runs,
|
|
909
|
+
it executes the same debugger, Appraisal, and Nomono bootstrap boundary as an
|
|
910
|
+
ordinary member. It then executes the same lockfile preparation, dependency
|
|
911
|
+
preparation and recovery, `kettle-jem` invocation, lockfile normalization, and
|
|
912
|
+
template commit path with the same `template_local` environment.
|
|
913
|
+
|
|
914
|
+
Only checkout mechanics differ: Family creates and trusts the linked worktree,
|
|
915
|
+
rebases that target branch on its own upstream when one exists, attaches the
|
|
916
|
+
branch name to the results, and removes the worktree after completion. These
|
|
917
|
+
steps are necessary because each target has a distinct Git ref and an absolute
|
|
918
|
+
`mise` configuration path. They do not change the dependency graph or omit a
|
|
919
|
+
template phase. Regression specs assert that branch worktrees call the shared
|
|
920
|
+
bootstrap boundary and cannot start a member template body when it fails.
|
|
921
|
+
|
|
905
922
|
## 🔐 Security
|
|
906
923
|
|
|
907
924
|
See [SECURITY.md][🔐security].
|
|
@@ -1154,7 +1171,7 @@ Thanks for RTFM. ☺️
|
|
|
1154
1171
|
[📌gitmoji]: https://gitmoji.dev
|
|
1155
1172
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1156
1173
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1157
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.
|
|
1174
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.669-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1158
1175
|
[🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
|
|
1159
1176
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1160
1177
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/lib/kettle/family/cli.rb
CHANGED
|
@@ -709,7 +709,7 @@ module Kettle
|
|
|
709
709
|
display_selected_members = display_members_for(command: command, config: config, members: selected, selected_members: selected)
|
|
710
710
|
print_execution_intent(command: command, config: config, members: display_selected_members, options: options, start_at: start_at)
|
|
711
711
|
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
712
|
-
state_progress = release_state_progress(command: command, members: result_members, options: options)
|
|
712
|
+
state_progress = release_state_progress(command: command, config: config, members: result_members, options: options)
|
|
713
713
|
state_progress&.start
|
|
714
714
|
state_event_handler = release_state_event_handler(
|
|
715
715
|
event_tape: state_event_tape,
|
|
@@ -901,21 +901,36 @@ module Kettle
|
|
|
901
901
|
stdout
|
|
902
902
|
end
|
|
903
903
|
|
|
904
|
-
def release_state_progress(command:, members:, options:)
|
|
904
|
+
def release_state_progress(command:, config:, members:, options:)
|
|
905
905
|
return nil unless command == "release-state"
|
|
906
906
|
return nil if options[:events] || options[:json]
|
|
907
907
|
return nil unless stdout.respond_to?(:tty?) && stdout.tty?
|
|
908
908
|
|
|
909
|
+
targets = release_state_progress_targets(config: config, members: members)
|
|
910
|
+
|
|
909
911
|
WorkflowProgress.new(
|
|
910
912
|
io: stdout,
|
|
911
913
|
label: "release state",
|
|
912
|
-
total:
|
|
913
|
-
jobs: Concurrency.wave_jobs(requested: options[:jobs], item_count:
|
|
914
|
-
members:
|
|
915
|
-
heading: "release state #{
|
|
914
|
+
total: targets.length,
|
|
915
|
+
jobs: Concurrency.wave_jobs(requested: options[:jobs], item_count: targets.length),
|
|
916
|
+
members: targets.map { |target| target.fetch(:progress_member) },
|
|
917
|
+
heading: "release state #{targets.length} target#{"s" unless targets.length == 1}:"
|
|
916
918
|
)
|
|
917
919
|
end
|
|
918
920
|
|
|
921
|
+
def release_state_progress_targets(config:, members:)
|
|
922
|
+
members.flat_map do |member|
|
|
923
|
+
member_config = member_release_config(member: member, config: config)
|
|
924
|
+
branches = member_config&.release_target_branches.to_a
|
|
925
|
+
next [{member: member, key: member.name, label: member.name, progress_member: member}] if branches.empty?
|
|
926
|
+
|
|
927
|
+
branches.map do |branch|
|
|
928
|
+
label = "#{member.name}@#{branch}"
|
|
929
|
+
{member: member, key: label, label: label, progress_member: member.dup.tap { |copy| copy.name = label }}
|
|
930
|
+
end
|
|
931
|
+
end
|
|
932
|
+
end
|
|
933
|
+
|
|
919
934
|
def release_state_event_handler(event_tape:, progress:, members:)
|
|
920
935
|
return nil unless event_tape || progress
|
|
921
936
|
|
|
@@ -927,18 +942,21 @@ module Kettle
|
|
|
927
942
|
member = members_by_name[event["member"]]
|
|
928
943
|
next unless member
|
|
929
944
|
|
|
945
|
+
branch = event["branch"].to_s
|
|
946
|
+
progress_key = branch.empty? ? member.name : "#{member.name}@#{branch}"
|
|
947
|
+
|
|
930
948
|
action = event["action"].to_s
|
|
931
949
|
status = event["status"].to_s
|
|
932
950
|
case action
|
|
933
951
|
when "member_start"
|
|
934
|
-
progress.start_member(member, total: 5, status: "release_state")
|
|
952
|
+
progress.start_member(member, total: 5, status: "release_state", key: progress_key, label: progress_key)
|
|
935
953
|
when "member_complete"
|
|
936
|
-
progress.finish_member(member, success: status == "ok", status: status)
|
|
954
|
+
progress.finish_member(member, success: status == "ok", status: status, key: progress_key, label: progress_key)
|
|
937
955
|
when "changelog_command", "computed_booleans", "git_state", "github_release", "transfer_changelog"
|
|
938
956
|
if status == "running"
|
|
939
|
-
progress.update(member, status: action)
|
|
957
|
+
progress.update(member, status: action, key: progress_key, label: progress_key)
|
|
940
958
|
elsif status == "ok" || status == "failed"
|
|
941
|
-
progress.advance(member, status: action, success: status == "ok")
|
|
959
|
+
progress.advance(member, status: action, success: status == "ok", key: progress_key, label: progress_key)
|
|
942
960
|
end
|
|
943
961
|
end
|
|
944
962
|
end
|
|
@@ -5,6 +5,11 @@ require "open3"
|
|
|
5
5
|
module Kettle
|
|
6
6
|
module Family
|
|
7
7
|
class Discovery
|
|
8
|
+
# Dir.chdir changes process-global state. Legacy gemspecs require this
|
|
9
|
+
# evaluation context, so serialize only that boundary; discovery callers
|
|
10
|
+
# may still resolve separate members and worktrees concurrently.
|
|
11
|
+
GEMSPEC_EVALUATION_MUTEX = Mutex.new
|
|
12
|
+
|
|
8
13
|
def initialize(config:, release_dependency_member_names: nil)
|
|
9
14
|
@config = config
|
|
10
15
|
@release_dependency_member_names = release_dependency_member_names&.map(&:to_s)
|
|
@@ -174,9 +179,11 @@ module Kettle
|
|
|
174
179
|
# evaluates gemspecs relative to the current process directory.
|
|
175
180
|
# Gem::Specification.load caches by path, which is wrong for branch-stack
|
|
176
181
|
# workflows that checkout different contents at the same path.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
182
|
+
spec = GEMSPEC_EVALUATION_MUTEX.synchronize do
|
|
183
|
+
# rubocop:disable ThreadSafety/DirChdir
|
|
184
|
+
Dir.chdir(File.dirname(path)) { eval_gemspec(path) }
|
|
185
|
+
# rubocop:enable ThreadSafety/DirChdir
|
|
186
|
+
end
|
|
180
187
|
raise Error, "could not load gemspec #{path}" unless spec
|
|
181
188
|
|
|
182
189
|
spec
|
|
@@ -56,20 +56,23 @@ module Kettle
|
|
|
56
56
|
def branch_results(event_handler: nil)
|
|
57
57
|
root = git_root
|
|
58
58
|
selected_names = members.map(&:name)
|
|
59
|
-
release_target_branches
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
results = parallel_map(branch_members) { |member| check_shared_changelog_member_or_local(member, branch: branch, event_handler: event_handler) }
|
|
64
|
-
memo.concat(normalize_shared_version_bump(results))
|
|
65
|
-
next
|
|
66
|
-
end
|
|
59
|
+
parallel_map(release_target_branches) do |branch|
|
|
60
|
+
branch_results_for(branch: branch, root: root, selected_names: selected_names, event_handler: event_handler)
|
|
61
|
+
end.flatten
|
|
62
|
+
end
|
|
67
63
|
|
|
68
|
-
|
|
64
|
+
def branch_results_for(branch:, root:, selected_names:, event_handler:)
|
|
65
|
+
with_branch_worktree(root: root, branch: branch) do |worktree_root|
|
|
66
|
+
branch_members = discover_branch_members(worktree_root: worktree_root, selected_names: selected_names)
|
|
67
|
+
if shared_changelog?
|
|
68
|
+
results = parallel_map(branch_members) { |member| check_shared_changelog_member_or_local(member, branch: branch, event_handler: event_handler) }
|
|
69
|
+
next normalize_shared_version_bump(results)
|
|
69
70
|
end
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
|
|
72
|
+
parallel_map(branch_members) { |member| check_member(member, branch: branch, event_handler: event_handler) }
|
|
72
73
|
end
|
|
74
|
+
rescue Error => error
|
|
75
|
+
[error_result(branch: branch, error: error)]
|
|
73
76
|
end
|
|
74
77
|
|
|
75
78
|
def check_member(member, branch: nil, event_handler: nil)
|
|
@@ -27,12 +27,12 @@ module Kettle
|
|
|
27
27
|
"timestamp" => @wall_clock.call,
|
|
28
28
|
"elapsed_seconds" => @clock.call - @started_at
|
|
29
29
|
)
|
|
30
|
-
|
|
30
|
+
target = target_key(payload)
|
|
31
31
|
@mutex.synchronize do
|
|
32
|
-
@sequence_by_member[
|
|
33
|
-
payload["sequence"] = @sequence_by_member.fetch(
|
|
32
|
+
@sequence_by_member[target] += 1
|
|
33
|
+
payload["sequence"] = @sequence_by_member.fetch(target)
|
|
34
34
|
line = JSON.generate(payload)
|
|
35
|
-
File.open(path_for(
|
|
35
|
+
File.open(path_for(target), "a") { |file| file.puts(line) }
|
|
36
36
|
@stream&.puts(line)
|
|
37
37
|
@stream.flush if @stream&.respond_to?(:flush)
|
|
38
38
|
end
|
|
@@ -43,8 +43,14 @@ module Kettle
|
|
|
43
43
|
|
|
44
44
|
private
|
|
45
45
|
|
|
46
|
-
def
|
|
47
|
-
|
|
46
|
+
def target_key(payload)
|
|
47
|
+
member = payload.fetch("member", "family").to_s
|
|
48
|
+
branch = payload["branch"].to_s
|
|
49
|
+
branch.empty? ? member : "#{member}@#{branch}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def path_for(target)
|
|
53
|
+
filename = target.gsub(/[^A-Za-z0-9_.-]+/, "_")
|
|
48
54
|
File.join(@directory, "#{filename}.ndjson")
|
|
49
55
|
end
|
|
50
56
|
end
|
|
@@ -5,7 +5,7 @@ module Kettle
|
|
|
5
5
|
# Version namespace for this gem.
|
|
6
6
|
module Version
|
|
7
7
|
# Current gem version.
|
|
8
|
-
VERSION = "1.2.
|
|
8
|
+
VERSION = "1.2.96"
|
|
9
9
|
end
|
|
10
10
|
# Current gem version exposed at the traditional constant location.
|
|
11
11
|
VERSION = Version::VERSION # Traditional Constant Location
|
|
@@ -932,14 +932,8 @@ module Kettle
|
|
|
932
932
|
end
|
|
933
933
|
|
|
934
934
|
def template_member_workflow_results(workflow_members)
|
|
935
|
-
|
|
936
|
-
return
|
|
937
|
-
|
|
938
|
-
appraisal_results = template_appraisal_bootstrap_results(workflow_members)
|
|
939
|
-
return debugger_results + appraisal_results unless appraisal_results.all?(&:ok?)
|
|
940
|
-
|
|
941
|
-
bootstrap_results = template_bootstrap_dependency_results(workflow_members)
|
|
942
|
-
return debugger_results + appraisal_results + bootstrap_results unless bootstrap_results.all?(&:ok?)
|
|
935
|
+
bootstrap_results = template_member_bootstrap_results(workflow_members)
|
|
936
|
+
return bootstrap_results unless bootstrap_results.all?(&:ok?)
|
|
943
937
|
|
|
944
938
|
template_progress = start_template_progress(workflow_members)
|
|
945
939
|
results = template_dependency_waves(workflow_members).each_with_object([]) do |wave, memo|
|
|
@@ -948,7 +942,22 @@ module Kettle
|
|
|
948
942
|
break memo unless wave_results.all?(&:ok?)
|
|
949
943
|
end
|
|
950
944
|
emit_template_progress_summary(results, progress: template_progress)
|
|
951
|
-
|
|
945
|
+
bootstrap_results + results
|
|
946
|
+
end
|
|
947
|
+
|
|
948
|
+
# This is the common preparation boundary for every template member,
|
|
949
|
+
# regardless of whether it runs in its primary checkout, a monorepo
|
|
950
|
+
# worktree, or a release-target branch worktree. Keep branch mechanics
|
|
951
|
+
# outside this method so they cannot silently omit a bootstrap phase.
|
|
952
|
+
def template_member_bootstrap_results(workflow_members)
|
|
953
|
+
debugger_results = template_debugger_bootstrap_results(workflow_members)
|
|
954
|
+
return debugger_results unless debugger_results.all?(&:ok?)
|
|
955
|
+
|
|
956
|
+
appraisal_results = template_appraisal_bootstrap_results(workflow_members)
|
|
957
|
+
return debugger_results + appraisal_results unless appraisal_results.all?(&:ok?)
|
|
958
|
+
|
|
959
|
+
bootstrap_results = template_bootstrap_dependency_results(workflow_members)
|
|
960
|
+
debugger_results + appraisal_results + bootstrap_results
|
|
952
961
|
end
|
|
953
962
|
|
|
954
963
|
def template_debugger_bootstrap_results(workflow_members)
|
|
@@ -1402,13 +1411,20 @@ module Kettle
|
|
|
1402
1411
|
)
|
|
1403
1412
|
end
|
|
1404
1413
|
|
|
1405
|
-
def template_results_for_member(member, progress: nil, commit_changes: true, wave_jobs: 1)
|
|
1406
|
-
|
|
1414
|
+
def template_results_for_member(member, progress: nil, progress_key: nil, progress_label: nil, commit_changes: true, wave_jobs: 1)
|
|
1415
|
+
progress_key ||= member.name
|
|
1416
|
+
progress_label ||= member.name
|
|
1417
|
+
progress&.start_member(
|
|
1418
|
+
member,
|
|
1419
|
+
total: template_phase_total(member),
|
|
1420
|
+
status: template_initial_status(member),
|
|
1421
|
+
**template_progress_identity_options(member, progress_key, progress_label)
|
|
1422
|
+
)
|
|
1407
1423
|
runner = CommandRunner.new(execute: execute, accept: accept)
|
|
1408
1424
|
[].tap do |memo|
|
|
1409
1425
|
if config.normalize_lockfiles?
|
|
1410
1426
|
normalize_lockfiles(member: member, runner: runner, memo: memo, phase: "prepare_lockfiles", commit_changes: commit_changes)
|
|
1411
|
-
emit_member_result_progress(member, memo.last, progress: progress)
|
|
1427
|
+
emit_member_result_progress(member, memo.last, progress: progress, progress_key: progress_key, progress_label: progress_label)
|
|
1412
1428
|
return memo unless memo.last.ok?
|
|
1413
1429
|
end
|
|
1414
1430
|
|
|
@@ -1419,7 +1435,7 @@ module Kettle
|
|
|
1419
1435
|
commit_changes: commit_changes,
|
|
1420
1436
|
wave_jobs: wave_jobs
|
|
1421
1437
|
)
|
|
1422
|
-
emit_member_result_progress(member, memo.last, progress: progress) if memo.last&.phase == "prepare_template_dependencies"
|
|
1438
|
+
emit_member_result_progress(member, memo.last, progress: progress, progress_key: progress_key, progress_label: progress_label) if memo.last&.phase == "prepare_template_dependencies"
|
|
1423
1439
|
return memo if prepared == false
|
|
1424
1440
|
|
|
1425
1441
|
memo << runner.call(
|
|
@@ -1427,22 +1443,23 @@ module Kettle
|
|
|
1427
1443
|
phase: command,
|
|
1428
1444
|
command: workflow_command(member),
|
|
1429
1445
|
env: template_command_env(wave_jobs: wave_jobs),
|
|
1430
|
-
stdout_line_handler: template_event_line_handler(member, progress: progress)
|
|
1446
|
+
stdout_line_handler: template_event_line_handler(member, progress: progress, progress_key: progress_key, progress_label: progress_label)
|
|
1431
1447
|
)
|
|
1432
|
-
emit_member_result_progress(member, memo.last, progress: progress)
|
|
1448
|
+
emit_member_result_progress(member, memo.last, progress: progress, progress_key: progress_key, progress_label: progress_label)
|
|
1433
1449
|
return memo unless memo.last.ok?
|
|
1434
1450
|
|
|
1435
1451
|
normalize_lockfiles(member: member, runner: runner, memo: memo, phase: "normalize_lockfiles", commit_changes: commit_changes)
|
|
1436
|
-
emit_member_result_progress(member, memo.last, progress: progress)
|
|
1452
|
+
emit_member_result_progress(member, memo.last, progress: progress, progress_key: progress_key, progress_label: progress_label)
|
|
1437
1453
|
commit_template_changes(member: member, runner: runner, memo: memo) if commit_changes
|
|
1438
|
-
emit_member_result_progress(member, memo.last, progress: progress) if memo.last&.phase == "commit_template"
|
|
1454
|
+
emit_member_result_progress(member, memo.last, progress: progress, progress_key: progress_key, progress_label: progress_label) if memo.last&.phase == "commit_template"
|
|
1439
1455
|
ensure
|
|
1440
1456
|
template_result = memo.find { |result| result.phase == "template" } || memo.last
|
|
1441
1457
|
if template_result
|
|
1442
1458
|
progress&.finish_member(
|
|
1443
1459
|
member,
|
|
1444
1460
|
success: memo.all?(&:ok?),
|
|
1445
|
-
status: template_member_finish_status(template_result)
|
|
1461
|
+
status: template_member_finish_status(template_result),
|
|
1462
|
+
**template_progress_identity_options(member, progress_key, progress_label)
|
|
1446
1463
|
)
|
|
1447
1464
|
end
|
|
1448
1465
|
end
|
|
@@ -1559,7 +1576,13 @@ module Kettle
|
|
|
1559
1576
|
|
|
1560
1577
|
if outcomes.all?(&:ok?)
|
|
1561
1578
|
emit_template_event_line(member, ">", "branch worktrees #{entries.length} branches, #{template_jobs(entries)} jobs")
|
|
1562
|
-
|
|
1579
|
+
progress = start_template_progress(
|
|
1580
|
+
entries.map { |entry| template_branch_progress_member(entry) },
|
|
1581
|
+
heading: "templating #{entries.length} branch worktree#{"s" unless entries.length == 1} with #{template_jobs(entries)} job#{"s" unless template_jobs(entries) == 1}:"
|
|
1582
|
+
)
|
|
1583
|
+
branch_results = template_branch_worktree_entries_results(entries, progress: progress)
|
|
1584
|
+
emit_template_progress_summary(branch_results, progress: progress)
|
|
1585
|
+
outcomes.concat(branch_results)
|
|
1563
1586
|
end
|
|
1564
1587
|
end
|
|
1565
1588
|
end
|
|
@@ -1649,7 +1672,18 @@ module Kettle
|
|
|
1649
1672
|
[]
|
|
1650
1673
|
end
|
|
1651
1674
|
|
|
1652
|
-
def template_branch_worktree_entries_results(entries)
|
|
1675
|
+
def template_branch_worktree_entries_results(entries, progress: nil)
|
|
1676
|
+
results = template_branch_worktree_sync_results(entries)
|
|
1677
|
+
return results unless results.all?(&:ok?)
|
|
1678
|
+
|
|
1679
|
+
# A branch worktree is a different checkout, not a different template
|
|
1680
|
+
# profile. Run the exact same member bootstrap boundary used by normal
|
|
1681
|
+
# members before any branch begins its member template body.
|
|
1682
|
+
bootstrap_results = template_member_bootstrap_results(entries.map { |entry| entry.fetch(:member) })
|
|
1683
|
+
tag_template_worktree_results(bootstrap_results, entries)
|
|
1684
|
+
results.concat(bootstrap_results)
|
|
1685
|
+
return results unless bootstrap_results.all?(&:ok?)
|
|
1686
|
+
|
|
1653
1687
|
wave_jobs = template_jobs(entries)
|
|
1654
1688
|
queue = Queue.new
|
|
1655
1689
|
entries.each_with_index { |entry, index| queue << [index, entry] }
|
|
@@ -1661,7 +1695,7 @@ module Kettle
|
|
|
1661
1695
|
loop do
|
|
1662
1696
|
break if mutex.synchronize { stop }
|
|
1663
1697
|
index, entry = queue.pop(true)
|
|
1664
|
-
branch_results = template_branch_worktree_entry_results(entry, wave_jobs: wave_jobs)
|
|
1698
|
+
branch_results = template_branch_worktree_entry_results(entry, progress: progress, wave_jobs: wave_jobs)
|
|
1665
1699
|
mutex.synchronize do
|
|
1666
1700
|
ordered_results[index] = branch_results
|
|
1667
1701
|
stop = true unless branch_results.all?(&:ok?)
|
|
@@ -1671,23 +1705,59 @@ module Kettle
|
|
|
1671
1705
|
end
|
|
1672
1706
|
end
|
|
1673
1707
|
end.each(&:join)
|
|
1674
|
-
ordered_results.compact.flatten
|
|
1708
|
+
results + ordered_results.compact.flatten
|
|
1675
1709
|
end
|
|
1676
1710
|
|
|
1677
|
-
def template_branch_worktree_entry_results(entry, wave_jobs: 1)
|
|
1711
|
+
def template_branch_worktree_entry_results(entry, progress: nil, wave_jobs: 1)
|
|
1678
1712
|
member = entry.fetch(:member)
|
|
1679
1713
|
branch = entry.fetch(:branch)
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1714
|
+
# Bootstrap and upstream synchronization are deliberately performed
|
|
1715
|
+
# for the complete branch set before workers start. The member body is
|
|
1716
|
+
# the same method normal template waves invoke.
|
|
1717
|
+
results = template_results_for_member(
|
|
1718
|
+
member,
|
|
1719
|
+
progress: progress,
|
|
1720
|
+
progress_key: template_branch_progress_key(entry),
|
|
1721
|
+
progress_label: template_branch_progress_label(entry),
|
|
1722
|
+
wave_jobs: wave_jobs
|
|
1723
|
+
)
|
|
1686
1724
|
tag_branch_results(results, branch)
|
|
1687
1725
|
emit_template_event_line(member, results.all?(&:ok?) ? "." : "F", "branch #{branch}")
|
|
1688
1726
|
results
|
|
1689
1727
|
end
|
|
1690
1728
|
|
|
1729
|
+
def template_branch_progress_member(entry)
|
|
1730
|
+
entry.fetch(:member).dup.tap { |member| member.name = template_branch_progress_label(entry) }
|
|
1731
|
+
end
|
|
1732
|
+
|
|
1733
|
+
def template_branch_progress_key(entry)
|
|
1734
|
+
template_branch_progress_label(entry)
|
|
1735
|
+
end
|
|
1736
|
+
|
|
1737
|
+
def template_branch_progress_label(entry)
|
|
1738
|
+
"#{entry.fetch(:member).name}@#{entry.fetch(:branch)}"
|
|
1739
|
+
end
|
|
1740
|
+
|
|
1741
|
+
def template_branch_worktree_sync_results(entries)
|
|
1742
|
+
runner = command_runner
|
|
1743
|
+
entries.filter_map do |entry|
|
|
1744
|
+
member = entry.fetch(:member)
|
|
1745
|
+
upstream = git_upstream_for(member)
|
|
1746
|
+
next unless upstream
|
|
1747
|
+
|
|
1748
|
+
result = runner.call(member: member, phase: "template_branch_sync", command: ["git", "rebase", "@{upstream}"])
|
|
1749
|
+
result.branch = entry.fetch(:branch)
|
|
1750
|
+
result
|
|
1751
|
+
end
|
|
1752
|
+
end
|
|
1753
|
+
|
|
1754
|
+
def tag_template_worktree_results(results, entries)
|
|
1755
|
+
branches_by_root = entries.to_h { |entry| [File.expand_path(entry.fetch(:member).root), entry.fetch(:branch)] }
|
|
1756
|
+
results.each do |result|
|
|
1757
|
+
result.branch = branches_by_root[File.expand_path(result.workdir)] if result.workdir
|
|
1758
|
+
end
|
|
1759
|
+
end
|
|
1760
|
+
|
|
1691
1761
|
def template_branch_worktree_cleanup_results(entries, runner:, control_member:)
|
|
1692
1762
|
entries.filter_map do |entry|
|
|
1693
1763
|
worktree_root = entry[:worktree_root]
|
|
@@ -1964,18 +2034,21 @@ module Kettle
|
|
|
1964
2034
|
end
|
|
1965
2035
|
|
|
1966
2036
|
def release_member_local_branch_target_results
|
|
1967
|
-
|
|
2037
|
+
target_members, current_branch_members = members.partition do |member|
|
|
2038
|
+
member_local_release_config(member)
|
|
2039
|
+
end
|
|
1968
2040
|
results = []
|
|
1969
|
-
|
|
2041
|
+
|
|
2042
|
+
# A member with release targets must not force unrelated sibling
|
|
2043
|
+
# repositories through one-at-a-time release workflows. Run those
|
|
2044
|
+
# members through the normal release scheduler first so configured
|
|
2045
|
+
# waves and their worker budget remain effective.
|
|
2046
|
+
results.concat(current_branch_results(current_branch_members)) unless current_branch_members.empty?
|
|
1970
2047
|
return results unless results.all?(&:ok?)
|
|
1971
2048
|
|
|
1972
|
-
|
|
2049
|
+
target_members.each_with_object(results) do |member, memo|
|
|
1973
2050
|
member_config = member_local_release_config(member)
|
|
1974
|
-
|
|
1975
|
-
memo.concat(member_local_workflow(member: member, member_config: member_config).results)
|
|
1976
|
-
else
|
|
1977
|
-
memo.concat(release_member_results([member], include_family_changelog: false))
|
|
1978
|
-
end
|
|
2051
|
+
memo.concat(member_local_workflow(member: member, member_config: member_config).results)
|
|
1979
2052
|
break memo unless memo.last&.ok?
|
|
1980
2053
|
end
|
|
1981
2054
|
end
|
|
@@ -4324,13 +4397,14 @@ module Kettle
|
|
|
4324
4397
|
append_command_args(command_text, args)
|
|
4325
4398
|
end
|
|
4326
4399
|
|
|
4327
|
-
def start_template_progress(workflow_members)
|
|
4400
|
+
def start_template_progress(workflow_members, heading: nil)
|
|
4328
4401
|
progress = WorkflowProgress.new(
|
|
4329
4402
|
io: progress_io,
|
|
4330
4403
|
label: "templating",
|
|
4331
4404
|
total: workflow_members.length,
|
|
4332
4405
|
jobs: template_jobs(workflow_members),
|
|
4333
|
-
members: workflow_members
|
|
4406
|
+
members: workflow_members,
|
|
4407
|
+
heading: heading
|
|
4334
4408
|
)
|
|
4335
4409
|
progress.start
|
|
4336
4410
|
progress
|
|
@@ -4434,10 +4508,16 @@ module Kettle
|
|
|
4434
4508
|
kettle_jem_template_command?(command_text)
|
|
4435
4509
|
end
|
|
4436
4510
|
|
|
4437
|
-
def emit_member_result_progress(member, result, progress:)
|
|
4511
|
+
def emit_member_result_progress(member, result, progress:, progress_key: member.name, progress_label: member.name)
|
|
4438
4512
|
return unless result
|
|
4439
4513
|
|
|
4440
|
-
progress&.advance(
|
|
4514
|
+
progress&.advance(
|
|
4515
|
+
member,
|
|
4516
|
+
status: result.phase,
|
|
4517
|
+
success: result.ok?,
|
|
4518
|
+
mark: command_result_progress_mark(result),
|
|
4519
|
+
**template_progress_identity_options(member, progress_key, progress_label)
|
|
4520
|
+
)
|
|
4441
4521
|
end
|
|
4442
4522
|
|
|
4443
4523
|
def command_result_progress_mark(result)
|
|
@@ -4484,7 +4564,7 @@ module Kettle
|
|
|
4484
4564
|
progress.summary("release summary: #{release_results.count(&:ok?)}/#{release_results.length} members ok")
|
|
4485
4565
|
end
|
|
4486
4566
|
|
|
4487
|
-
def template_event_line_handler(member, progress: nil)
|
|
4567
|
+
def template_event_line_handler(member, progress: nil, progress_key: member.name, progress_label: member.name)
|
|
4488
4568
|
lambda do |line|
|
|
4489
4569
|
event = parse_template_event(line)
|
|
4490
4570
|
next false unless event
|
|
@@ -4493,7 +4573,7 @@ module Kettle
|
|
|
4493
4573
|
if verbose || debug
|
|
4494
4574
|
emit_template_event_progress(member, event)
|
|
4495
4575
|
elsif progress&.tty?
|
|
4496
|
-
emit_template_event_status(member, event, progress: progress)
|
|
4576
|
+
emit_template_event_status(member, event, progress: progress, progress_key: progress_key, progress_label: progress_label)
|
|
4497
4577
|
end
|
|
4498
4578
|
end
|
|
4499
4579
|
true
|
|
@@ -4611,7 +4691,7 @@ module Kettle
|
|
|
4611
4691
|
end
|
|
4612
4692
|
end
|
|
4613
4693
|
|
|
4614
|
-
def emit_template_event_status(member, event, progress:)
|
|
4694
|
+
def emit_template_event_status(member, event, progress:, progress_key: member.name, progress_label: member.name)
|
|
4615
4695
|
status = case event["type"]
|
|
4616
4696
|
when "phase_start", "phase_finish"
|
|
4617
4697
|
event["phase"].to_s
|
|
@@ -4625,7 +4705,20 @@ module Kettle
|
|
|
4625
4705
|
template_event_summary_label(event)
|
|
4626
4706
|
end
|
|
4627
4707
|
mark = template_event_status_mark(event)
|
|
4628
|
-
|
|
4708
|
+
if status && !status.empty?
|
|
4709
|
+
progress&.update(
|
|
4710
|
+
member,
|
|
4711
|
+
status: status,
|
|
4712
|
+
mark: mark,
|
|
4713
|
+
**template_progress_identity_options(member, progress_key, progress_label)
|
|
4714
|
+
)
|
|
4715
|
+
end
|
|
4716
|
+
end
|
|
4717
|
+
|
|
4718
|
+
def template_progress_identity_options(member, progress_key, progress_label)
|
|
4719
|
+
return {} if progress_key == member.name && progress_label == member.name
|
|
4720
|
+
|
|
4721
|
+
{key: progress_key, label: progress_label}
|
|
4629
4722
|
end
|
|
4630
4723
|
|
|
4631
4724
|
def emit_release_event_progress(member, event)
|
|
@@ -27,6 +27,7 @@ module Kettle
|
|
|
27
27
|
@started = false
|
|
28
28
|
@stopped = false
|
|
29
29
|
@member_totals = {}
|
|
30
|
+
@member_labels = @line_order.to_h { |member_name| [member_name, member_name] }
|
|
30
31
|
@member_counts = Hash.new(0)
|
|
31
32
|
@member_started_at = {}
|
|
32
33
|
@member_finished_elapsed = {}
|
|
@@ -55,62 +56,66 @@ module Kettle
|
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
def start_member(member, total:, status:)
|
|
59
|
+
def start_member(member, total:, status:, key: member.name, label: member.name)
|
|
59
60
|
return unless @enabled
|
|
60
61
|
|
|
61
62
|
synchronize do
|
|
62
|
-
@
|
|
63
|
-
@
|
|
64
|
-
@
|
|
65
|
-
@
|
|
63
|
+
@member_labels[key] = label
|
|
64
|
+
@member_totals[key] = total.to_i
|
|
65
|
+
@member_counts[key] = 0
|
|
66
|
+
@member_started_at[key] ||= monotonic_now
|
|
67
|
+
@member_finished_elapsed.delete(key)
|
|
66
68
|
if @tty
|
|
67
|
-
render(
|
|
69
|
+
render(key, status: status)
|
|
68
70
|
else
|
|
69
|
-
write_line(non_tty_line(
|
|
71
|
+
write_line(non_tty_line(key, mark: ">", status: status))
|
|
70
72
|
end
|
|
71
73
|
end
|
|
72
74
|
end
|
|
73
75
|
|
|
74
|
-
def advance(member, status:, success: true, mark: nil)
|
|
76
|
+
def advance(member, status:, success: true, mark: nil, key: member.name, label: member.name)
|
|
75
77
|
return unless @enabled
|
|
76
78
|
|
|
77
79
|
synchronize do
|
|
80
|
+
@member_labels[key] = label
|
|
78
81
|
event_mark = mark || (success ? "." : "F")
|
|
79
|
-
increment_member_count(
|
|
82
|
+
increment_member_count(key)
|
|
80
83
|
if @tty
|
|
81
|
-
append_event(
|
|
82
|
-
render(
|
|
84
|
+
append_event(key, event_mark)
|
|
85
|
+
render(key, status: status)
|
|
83
86
|
else
|
|
84
|
-
write_line(non_tty_line(
|
|
87
|
+
write_line(non_tty_line(key, mark: event_mark, status: status))
|
|
85
88
|
end
|
|
86
89
|
end
|
|
87
90
|
end
|
|
88
91
|
|
|
89
|
-
def update(member, status:, mark: nil)
|
|
92
|
+
def update(member, status:, mark: nil, key: member.name, label: member.name)
|
|
90
93
|
return unless @enabled
|
|
91
94
|
return if status.to_s.empty?
|
|
92
95
|
|
|
93
96
|
synchronize do
|
|
97
|
+
@member_labels[key] = label
|
|
94
98
|
if @tty
|
|
95
|
-
append_event(
|
|
96
|
-
render(
|
|
99
|
+
append_event(key, mark) if mark
|
|
100
|
+
render(key, status: status)
|
|
97
101
|
else
|
|
98
|
-
write_line(non_tty_line(
|
|
102
|
+
write_line(non_tty_line(key, mark: mark || ">", status: status))
|
|
99
103
|
end
|
|
100
104
|
end
|
|
101
105
|
end
|
|
102
106
|
|
|
103
|
-
def finish_member(member, success:, status:)
|
|
107
|
+
def finish_member(member, success:, status:, key: member.name, label: member.name)
|
|
104
108
|
return unless @enabled
|
|
105
109
|
|
|
106
110
|
synchronize do
|
|
107
|
-
|
|
108
|
-
@
|
|
109
|
-
@
|
|
111
|
+
@member_labels[key] = label
|
|
112
|
+
total = @member_totals[key].to_i
|
|
113
|
+
@member_counts[key] = total if total.positive?
|
|
114
|
+
@member_finished_elapsed[key] = elapsed_seconds_by_name(key)
|
|
110
115
|
if @tty
|
|
111
|
-
render(
|
|
116
|
+
render(key, status: status)
|
|
112
117
|
else
|
|
113
|
-
write_line(non_tty_line(
|
|
118
|
+
write_line(non_tty_line(key, mark: success ? "done" : "failed", status: status))
|
|
114
119
|
end
|
|
115
120
|
end
|
|
116
121
|
end
|
|
@@ -168,15 +173,15 @@ module Kettle
|
|
|
168
173
|
|
|
169
174
|
private
|
|
170
175
|
|
|
171
|
-
def render(
|
|
172
|
-
render_name(
|
|
176
|
+
def render(member_key, status:)
|
|
177
|
+
render_name(member_key, status: status)
|
|
173
178
|
render_tty_block if @tty
|
|
174
179
|
end
|
|
175
180
|
|
|
176
|
-
def append_event(
|
|
181
|
+
def append_event(member_key, mark)
|
|
177
182
|
return if mark.to_s.empty?
|
|
178
183
|
|
|
179
|
-
@member_events[
|
|
184
|
+
@member_events[member_key] = (@member_events[member_key] + mark.to_s).chars.last(EVENT_WIDTH).join
|
|
180
185
|
end
|
|
181
186
|
|
|
182
187
|
def render_name(member_name, status:)
|
|
@@ -222,7 +227,7 @@ module Kettle
|
|
|
222
227
|
def tty_line(member_name)
|
|
223
228
|
Kernel.format(
|
|
224
229
|
FORMAT,
|
|
225
|
-
member: member_name,
|
|
230
|
+
member: @member_labels.fetch(member_name, member_name),
|
|
226
231
|
progress: progress_text(member_name),
|
|
227
232
|
duration: elapsed_text(member_name),
|
|
228
233
|
events: @member_events[member_name].rjust(EVENT_WIDTH),
|
|
@@ -234,15 +239,15 @@ module Kettle
|
|
|
234
239
|
"s" unless count == 1
|
|
235
240
|
end
|
|
236
241
|
|
|
237
|
-
def non_tty_line(
|
|
238
|
-
|
|
242
|
+
def non_tty_line(member_key, mark:, status:)
|
|
243
|
+
label = @member_labels.fetch(member_key, member_key)
|
|
244
|
+
"[#{label}] #{progress_text(member_key)} #{elapsed_text(member_key)} #{mark} #{status}"
|
|
239
245
|
end
|
|
240
246
|
|
|
241
|
-
def increment_member_count(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
@member_counts[
|
|
245
|
-
@member_counts[member_name] = total if total.positive? && @member_counts[member_name] > total
|
|
247
|
+
def increment_member_count(member_key)
|
|
248
|
+
total = @member_totals[member_key].to_i
|
|
249
|
+
@member_counts[member_key] += 1
|
|
250
|
+
@member_counts[member_key] = total if total.positive? && @member_counts[member_key] > total
|
|
246
251
|
end
|
|
247
252
|
|
|
248
253
|
def progress_text(member_name)
|
|
@@ -256,10 +261,6 @@ module Kettle
|
|
|
256
261
|
format_elapsed(elapsed_seconds_by_name(member_name)).rjust(ELAPSED_WIDTH)
|
|
257
262
|
end
|
|
258
263
|
|
|
259
|
-
def elapsed_seconds(member)
|
|
260
|
-
elapsed_seconds_by_name(member.name)
|
|
261
|
-
end
|
|
262
|
-
|
|
263
264
|
def elapsed_seconds_by_name(member_name)
|
|
264
265
|
return @member_finished_elapsed[member_name] if @member_finished_elapsed.key?(member_name)
|
|
265
266
|
|
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.2.
|
|
4
|
+
version: 1.2.96
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -89,22 +89,22 @@ dependencies:
|
|
|
89
89
|
name: kettle-dev
|
|
90
90
|
requirement: !ruby/object:Gem::Requirement
|
|
91
91
|
requirements:
|
|
92
|
-
- - "
|
|
92
|
+
- - "~>"
|
|
93
93
|
- !ruby/object:Gem::Version
|
|
94
|
-
version: 3.0
|
|
95
|
-
- - "
|
|
94
|
+
version: '3.0'
|
|
95
|
+
- - ">="
|
|
96
96
|
- !ruby/object:Gem::Version
|
|
97
|
-
version:
|
|
97
|
+
version: 3.0.33
|
|
98
98
|
type: :runtime
|
|
99
99
|
prerelease: false
|
|
100
100
|
version_requirements: !ruby/object:Gem::Requirement
|
|
101
101
|
requirements:
|
|
102
|
-
- - "
|
|
102
|
+
- - "~>"
|
|
103
103
|
- !ruby/object:Gem::Version
|
|
104
|
-
version: 3.0
|
|
105
|
-
- - "
|
|
104
|
+
version: '3.0'
|
|
105
|
+
- - ">="
|
|
106
106
|
- !ruby/object:Gem::Version
|
|
107
|
-
version:
|
|
107
|
+
version: 3.0.33
|
|
108
108
|
- !ruby/object:Gem::Dependency
|
|
109
109
|
name: kettle-gha-pins
|
|
110
110
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -131,20 +131,20 @@ dependencies:
|
|
|
131
131
|
requirements:
|
|
132
132
|
- - "~>"
|
|
133
133
|
- !ruby/object:Gem::Version
|
|
134
|
-
version: '7.
|
|
134
|
+
version: '7.1'
|
|
135
135
|
- - ">="
|
|
136
136
|
- !ruby/object:Gem::Version
|
|
137
|
-
version: 7.
|
|
137
|
+
version: 7.1.23
|
|
138
138
|
type: :runtime
|
|
139
139
|
prerelease: false
|
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
|
141
141
|
requirements:
|
|
142
142
|
- - "~>"
|
|
143
143
|
- !ruby/object:Gem::Version
|
|
144
|
-
version: '7.
|
|
144
|
+
version: '7.1'
|
|
145
145
|
- - ">="
|
|
146
146
|
- !ruby/object:Gem::Version
|
|
147
|
-
version: 7.
|
|
147
|
+
version: 7.1.23
|
|
148
148
|
- !ruby/object:Gem::Dependency
|
|
149
149
|
name: kettle-test
|
|
150
150
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -304,7 +304,7 @@ dependencies:
|
|
|
304
304
|
version: '3.2'
|
|
305
305
|
- - ">="
|
|
306
306
|
- !ruby/object:Gem::Version
|
|
307
|
-
version: 3.2.
|
|
307
|
+
version: 3.2.3
|
|
308
308
|
type: :development
|
|
309
309
|
prerelease: false
|
|
310
310
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -314,7 +314,7 @@ dependencies:
|
|
|
314
314
|
version: '3.2'
|
|
315
315
|
- - ">="
|
|
316
316
|
- !ruby/object:Gem::Version
|
|
317
|
-
version: 3.2.
|
|
317
|
+
version: 3.2.3
|
|
318
318
|
- !ruby/object:Gem::Dependency
|
|
319
319
|
name: turbo_tests2
|
|
320
320
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -324,7 +324,7 @@ dependencies:
|
|
|
324
324
|
version: '3.2'
|
|
325
325
|
- - ">="
|
|
326
326
|
- !ruby/object:Gem::Version
|
|
327
|
-
version: 3.2.
|
|
327
|
+
version: 3.2.7
|
|
328
328
|
type: :development
|
|
329
329
|
prerelease: false
|
|
330
330
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -334,7 +334,7 @@ dependencies:
|
|
|
334
334
|
version: '3.2'
|
|
335
335
|
- - ">="
|
|
336
336
|
- !ruby/object:Gem::Version
|
|
337
|
-
version: 3.2.
|
|
337
|
+
version: 3.2.7
|
|
338
338
|
- !ruby/object:Gem::Dependency
|
|
339
339
|
name: ruby-progressbar
|
|
340
340
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -443,10 +443,10 @@ licenses:
|
|
|
443
443
|
- AGPL-3.0-only
|
|
444
444
|
metadata:
|
|
445
445
|
homepage_uri: https://kettle-family.galtzo.com
|
|
446
|
-
source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.2.
|
|
447
|
-
changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.2.
|
|
446
|
+
source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.2.96
|
|
447
|
+
changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.2.96/CHANGELOG.md
|
|
448
448
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-family/issues
|
|
449
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.2.
|
|
449
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.2.96
|
|
450
450
|
funding_uri: https://github.com/sponsors/pboling
|
|
451
451
|
wiki_uri: https://github.com/kettle-dev/kettle-family/wiki
|
|
452
452
|
news_uri: https://www.railsbling.com/tags/kettle-family
|
metadata.gz.sig
CHANGED
|
Binary file
|