kettle-family 1.0.0 → 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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +92 -1
- data/README.md +92 -6
- data/lib/kettle/family/cli.rb +69 -13
- data/lib/kettle/family/command_runner.rb +38 -1
- data/lib/kettle/family/config.rb +33 -2
- data/lib/kettle/family/release_state_check.rb +95 -3
- data/lib/kettle/family/report.rb +63 -2
- data/lib/kettle/family/selection.rb +48 -2
- data/lib/kettle/family/version.rb +1 -1
- data/lib/kettle/family/version_bump.rb +5 -4
- data/lib/kettle/family/workflow.rb +189 -8
- data/sig/kettle/family.rbs +0 -63
- data.tar.gz.sig +0 -0
- metadata +12 -12
- 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: 19486d91816150dae28ac5f1e8b31ef3f43b0f4f7004337681f08819fb41b27d
|
|
4
|
+
data.tar.gz: e2bf61a97f739f211accb4fc5cbfe91acc4121077c5f620786d30d217b4cc803
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e8826e083336b3de83e313fc3207c60461e494fc8c1c4ad22b8148b861024ca78adcefa1b5c357d7ed90af79dddb3cda59dc4900434e862739d8d2f930e8e0c3
|
|
7
|
+
data.tar.gz: 1d735e6c84877eab971381d22226c96871e2fa0198bab1d9895bf771abdbbe2d5bf2c69a0d16bd04c0a3cdfdc830c7e7354f526313a5f0b8dbeec2a96df7d908
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,93 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
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.
|
|
70
|
+
- Generated HEAD and runtime dependency HEAD CI workflows no longer include
|
|
71
|
+
JRuby or TruffleRuby jobs for this MRI-only gem.
|
|
72
|
+
|
|
73
|
+
## [1.0.1] - 2026-07-20
|
|
74
|
+
|
|
75
|
+
- TAG: [v1.0.1][1.0.1t]
|
|
76
|
+
- COVERAGE: 95.44% -- 2534/2655 lines in 23 files
|
|
77
|
+
- BRANCH COVERAGE: 77.89% -- 877/1126 branches in 23 files
|
|
78
|
+
- 29.10% documented
|
|
79
|
+
|
|
80
|
+
### Added
|
|
81
|
+
|
|
82
|
+
- `kettle-family release-state` now includes an `ahead` column counting commits
|
|
83
|
+
from the latest release tag to the local default branch when available.
|
|
84
|
+
- `kettle-family release` now accepts `--skip-remotes` and forwards the
|
|
85
|
+
comma-separated remote skip list to member `kettle-release` runs.
|
|
86
|
+
- `kettle-family --only` now accepts release-state tokens `unreleased`,
|
|
87
|
+
`prepared`, and `pending`; multiple tokens are combined with logical AND.
|
|
88
|
+
- `kettle-family template` now accepts `--verbose` and forwards verbose mode to
|
|
89
|
+
member `kettle-jem` runs instead of forcing quiet JSON output.
|
|
90
|
+
|
|
91
|
+
- `kettle-family template` now runs `kettle-jem prepare` before full templating
|
|
92
|
+
for Kettle Jem-powered members so templating-only dependency bootstraps, such
|
|
93
|
+
as parser packages, are available before the full template command loads.
|
|
94
|
+
|
|
95
|
+
- `kettle-family template` now uses `kettle-jem --events` as its default
|
|
96
|
+
templating interface, including verbose and single-job runs, and streams
|
|
97
|
+
newline-delimited JSON template phase, recipe, post-apply, command-step,
|
|
98
|
+
diagnostic, and summary events as member-prefixed progress lines.
|
|
99
|
+
|
|
100
|
+
### Deprecated
|
|
101
|
+
|
|
102
|
+
- `kettle-family bump-version` is now deprecated in favor of `kettle-family bump`.
|
|
103
|
+
|
|
104
|
+
### Fixed
|
|
105
|
+
|
|
106
|
+
- The templating prepare phase now disables only the implicit family local path
|
|
107
|
+
environment variable unless it was explicitly provided, avoiding stale local
|
|
108
|
+
Gemfile activation failures before the prepare payload can refresh generated
|
|
109
|
+
modular Gemfiles.
|
|
110
|
+
- The templating prepare phase now runs outside each member's Bundler context so
|
|
111
|
+
it can repair stale generated Gemfiles before Bundler evaluates them.
|
|
112
|
+
|
|
113
|
+
- `kettle-family` template preparation now handles custom non-`kettle-jem`
|
|
114
|
+
template commands without treating no-op dependency preparation as failure.
|
|
115
|
+
- `kettle-family release-state` now counts `ahead` from the release tag to the
|
|
116
|
+
checked-out member `HEAD`.
|
|
117
|
+
- Generated docs now retain the YARD `_index.html` content wrapper after
|
|
118
|
+
regeneration with the shared YARD postprocessing stack.
|
|
119
|
+
|
|
33
120
|
## [1.0.0] - 2026-07-17
|
|
34
121
|
|
|
35
122
|
- TAG: [v1.0.0][1.0.0t]
|
|
@@ -736,7 +823,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
736
823
|
- Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
|
|
737
824
|
- Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
|
|
738
825
|
|
|
739
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.0.
|
|
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
|
|
829
|
+
[1.0.1]: https://github.com/kettle-dev/kettle-family/compare/v1.0.0...v1.0.1
|
|
830
|
+
[1.0.1t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.0.1
|
|
740
831
|
[1.0.0]: https://github.com/kettle-dev/kettle-family/compare/v0.2.7...v1.0.0
|
|
741
832
|
[1.0.0t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.0.0
|
|
742
833
|
[0.2.7]: https://github.com/kettle-dev/kettle-family/compare/v0.2.6...v0.2.7
|
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] |
|
|
@@ -211,7 +211,7 @@ changelog:
|
|
|
211
211
|
|
|
212
212
|
release:
|
|
213
213
|
env:
|
|
214
|
-
|
|
214
|
+
KETTLE_DEV_DEV: false
|
|
215
215
|
family_changelog:
|
|
216
216
|
enabled: true
|
|
217
217
|
command: bundle exec kettle-changelog
|
|
@@ -273,8 +273,28 @@ kettle-family release-state
|
|
|
273
273
|
```
|
|
274
274
|
|
|
275
275
|
The release-state report lists each gem's current `version.rb`, latest published
|
|
276
|
-
release, latest versioned `CHANGELOG.md` section,
|
|
277
|
-
|
|
276
|
+
release, latest versioned `CHANGELOG.md` section, whether pending changelog work
|
|
277
|
+
exists in either `Unreleased` or an unpublished prepared release section, and
|
|
278
|
+
how many commits the current branch is ahead of the latest release tag.
|
|
279
|
+
|
|
280
|
+
Use release-state tokens with `--only` to select gems by state instead of by
|
|
281
|
+
name. Multiple tokens are combined with logical AND, so this selects only gems
|
|
282
|
+
that are both unreleased and pending. Status tokens cannot be mixed with member
|
|
283
|
+
names in the same `--only` value.
|
|
284
|
+
|
|
285
|
+
```console
|
|
286
|
+
kettle-family release-state --only pending
|
|
287
|
+
kettle-family release-state --only unreleased,prepared
|
|
288
|
+
kettle-family release --execute --only unreleased,pending
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The supported release-state tokens are:
|
|
292
|
+
|
|
293
|
+
| Token | Meaning |
|
|
294
|
+
|-------|---------|
|
|
295
|
+
| `unreleased` | The current `version.rb` is not the latest published gem version. |
|
|
296
|
+
| `prepared` | The changelog already has a versioned section for the current `version.rb`. |
|
|
297
|
+
| `pending` | The member has unreleased changelog work or an unpublished prepared release. |
|
|
278
298
|
|
|
279
299
|
Plan or update GitHub Actions workflow SHA pins across the selected family
|
|
280
300
|
members:
|
|
@@ -291,6 +311,15 @@ Run release prep/build phases without publishing:
|
|
|
291
311
|
kettle-family release --execute
|
|
292
312
|
```
|
|
293
313
|
|
|
314
|
+
When a remote mirror is temporarily unavailable, skip it for the underlying
|
|
315
|
+
`kettle-release` fetch/parity gate instead of removing the remote from each
|
|
316
|
+
member repository:
|
|
317
|
+
|
|
318
|
+
```console
|
|
319
|
+
kettle-family release --execute --publish --skip-remotes cb
|
|
320
|
+
kettle-family release --execute --publish --skip-remotes cb,mirror2
|
|
321
|
+
```
|
|
322
|
+
|
|
294
323
|
Publish through `kettle-release`. A full publish first runs the
|
|
295
324
|
`kettle-pre-release` gate, then prompts once for the gem signing key password
|
|
296
325
|
and leaves RubyGems MFA prompts interactive:
|
|
@@ -321,6 +350,61 @@ If you intentionally need to continue after CI failures, opt in explicitly:
|
|
|
321
350
|
kettle-family release --publish --execute --continue-ci-failures
|
|
322
351
|
```
|
|
323
352
|
|
|
353
|
+
Bump aligned member versions with `bump`. The older `bump-version` command still
|
|
354
|
+
works as a deprecated alias.
|
|
355
|
+
|
|
356
|
+
```console
|
|
357
|
+
kettle-family bump --execute --only pending patch
|
|
358
|
+
kettle-family bump --execute --only unreleased minor
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Run `kettle-jem` templating across the selected family members. Planning shows
|
|
362
|
+
the commands that would run; `--execute` runs them. Executed templating defaults
|
|
363
|
+
to a parallel job count based on CPU cores, capped for readability, and can be
|
|
364
|
+
overridden with `--jobs`.
|
|
365
|
+
|
|
366
|
+
```console
|
|
367
|
+
kettle-family template
|
|
368
|
+
kettle-family template --execute --jobs 4
|
|
369
|
+
kettle-family template --execute --only kettle-family
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Templating uses `kettle-jem --events` as the default child interface, so
|
|
373
|
+
executed runs stream member-prefixed progress while still keeping the final
|
|
374
|
+
family report. Progress marks include:
|
|
375
|
+
|
|
376
|
+
| Mark | Meaning |
|
|
377
|
+
|------|---------|
|
|
378
|
+
| `>` | A phase or command step started. |
|
|
379
|
+
| `.` | A phase, recipe, or step completed without changing files. |
|
|
380
|
+
| `*` | A recipe or step changed files. |
|
|
381
|
+
| `!` | A diagnostic was emitted. |
|
|
382
|
+
| `F` | A phase or step failed. |
|
|
383
|
+
| `done` | The member summary was emitted. |
|
|
384
|
+
|
|
385
|
+
Example progress:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
templating 1 member with 1 job:
|
|
389
|
+
[kettle-family] > recipes
|
|
390
|
+
[kettle-family] * Gemfile
|
|
391
|
+
[kettle-family] * post_apply:git_hooks_executable
|
|
392
|
+
[kettle-family] done 2 files changed
|
|
393
|
+
.
|
|
394
|
+
template summary: 1/1 members ok, 2 files changed
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Use `--verbose` when you need `kettle-jem` verbose diagnostics layered on top of
|
|
398
|
+
the event stream. Environment overrides pass through to every member workflow
|
|
399
|
+
command, which is useful when templating against local unreleased dependencies.
|
|
400
|
+
|
|
401
|
+
```console
|
|
402
|
+
kettle-family template --execute --verbose --jobs 1
|
|
403
|
+
kettle-family template --execute \
|
|
404
|
+
--env K_JEM_TEMPLATING=true \
|
|
405
|
+
--env STRUCTUREDMERGE_DEV=/home/me/src/structuredmerge/ruby/gems
|
|
406
|
+
```
|
|
407
|
+
|
|
324
408
|
## 🔐 Security
|
|
325
409
|
|
|
326
410
|
See [SECURITY.md][🔐security].
|
|
@@ -386,7 +470,7 @@ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with
|
|
|
386
470
|
For example:
|
|
387
471
|
|
|
388
472
|
```ruby
|
|
389
|
-
spec.add_dependency("kettle-family", "~>
|
|
473
|
+
spec.add_dependency("kettle-family", "~> 1.0")
|
|
390
474
|
```
|
|
391
475
|
|
|
392
476
|
<details markdown="1">
|
|
@@ -476,6 +560,8 @@ Thanks for RTFM. ☺️
|
|
|
476
560
|
[✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
|
|
477
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
|
|
478
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
|
|
479
565
|
|
|
480
566
|
[✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
|
|
481
567
|
[⛳️gem-namespace]: https://github.com/kettle-dev/kettle-family
|
|
@@ -583,7 +669,7 @@ Thanks for RTFM. ☺️
|
|
|
583
669
|
[📌gitmoji]: https://gitmoji.dev
|
|
584
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
|
|
585
671
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
586
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-2.
|
|
672
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-2.761-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
587
673
|
[🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
|
|
588
674
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
589
675
|
[📄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
|
@@ -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-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...]"
|
|
@@ -37,7 +37,7 @@ module Kettle
|
|
|
37
37
|
|
|
38
38
|
module SelectionOptions
|
|
39
39
|
def self.included(base)
|
|
40
|
-
base.option :only, value: {type: String, usage: "MEMBERS"}, desc: "Select comma-separated members"
|
|
40
|
+
base.option :only, value: {type: String, usage: "MEMBERS"}, desc: "Select comma-separated members, or release-state tokens: unreleased, prepared, pending"
|
|
41
41
|
base.option :exclude, value: {type: String, usage: "MEMBERS"}, desc: "Exclude comma-separated members"
|
|
42
42
|
base.option :start_at, long: "--start-at", value: {type: String, usage: "MEMBER[@BRANCH]"}, desc: "Select from member through the end of order"
|
|
43
43
|
end
|
|
@@ -65,6 +65,7 @@ module Kettle
|
|
|
65
65
|
module WorkflowOptions
|
|
66
66
|
def self.included(base)
|
|
67
67
|
base.option :debug, desc: "Preserve debug environment for workflow commands"
|
|
68
|
+
base.option :verbose, desc: "Pass verbose mode through to supported workflow commands"
|
|
68
69
|
base.option :jobs, value: {type: Integer, usage: "N"}, desc: "Parallel jobs for supported executed workflows"
|
|
69
70
|
base.option :env, value: {type: String, usage: "KEY=VALUE"}, desc: "Override an environment variable for each member workflow command" do |value|
|
|
70
71
|
parse_env_override(value, workflow_env)
|
|
@@ -134,6 +135,7 @@ module Kettle
|
|
|
134
135
|
report: options[:report],
|
|
135
136
|
execute: truthy_option?(:execute),
|
|
136
137
|
debug: truthy_option?(:debug),
|
|
138
|
+
verbose: truthy_option?(:verbose),
|
|
137
139
|
jobs: options[:jobs],
|
|
138
140
|
workflow_env: workflow_env,
|
|
139
141
|
changelog_section: nil,
|
|
@@ -148,6 +150,7 @@ module Kettle
|
|
|
148
150
|
release_continue_ci_failures: false,
|
|
149
151
|
release_ci_workflows: nil,
|
|
150
152
|
release_skip_bundle_audit: false,
|
|
153
|
+
release_skip_remotes: nil,
|
|
151
154
|
accept: true,
|
|
152
155
|
tag: false,
|
|
153
156
|
push: false,
|
|
@@ -251,6 +254,16 @@ module Kettle
|
|
|
251
254
|
end
|
|
252
255
|
end
|
|
253
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
|
+
|
|
254
267
|
class WorkflowCommand < BaseCommand
|
|
255
268
|
include ExecutionOptions
|
|
256
269
|
include WorkflowOptions
|
|
@@ -353,11 +366,11 @@ module Kettle
|
|
|
353
366
|
end
|
|
354
367
|
end
|
|
355
368
|
|
|
356
|
-
class
|
|
369
|
+
class Bump < BaseCommand
|
|
357
370
|
include ExecutionOptions
|
|
358
371
|
include CommitOptions
|
|
359
372
|
|
|
360
|
-
command_name "bump
|
|
373
|
+
command_name "bump"
|
|
361
374
|
usage "[options] VERSION|major|minor|patch|pre"
|
|
362
375
|
description "Check, plan, or execute family version alignment."
|
|
363
376
|
argument :target_version, required: false, usage: "VERSION|major|minor|patch|pre", desc: "Version or bump target"
|
|
@@ -366,9 +379,31 @@ module Kettle
|
|
|
366
379
|
option :from, value: {type: String, usage: "VERSION"}, desc: "Require selected members to currently match VERSION"
|
|
367
380
|
|
|
368
381
|
def run(target_version = nil)
|
|
369
|
-
raise Error, "
|
|
382
|
+
raise Error, "#{workflow_command_name} requires VERSION, major, minor, patch, or pre" unless target_version
|
|
383
|
+
|
|
384
|
+
run_family(workflow_command_name, target_version: target_version, from_version: options[:from])
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
private
|
|
388
|
+
|
|
389
|
+
def workflow_command_name
|
|
390
|
+
"bump"
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
class BumpVersion < Bump
|
|
395
|
+
command_name "bump-version"
|
|
396
|
+
description "Deprecated alias for bump."
|
|
397
|
+
|
|
398
|
+
def run(target_version = nil)
|
|
399
|
+
stderr.puts("kettle-family: bump-version is deprecated; use bump instead.")
|
|
400
|
+
super
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
private
|
|
370
404
|
|
|
371
|
-
|
|
405
|
+
def workflow_command_name
|
|
406
|
+
"bump-version"
|
|
372
407
|
end
|
|
373
408
|
end
|
|
374
409
|
|
|
@@ -407,6 +442,7 @@ module Kettle
|
|
|
407
442
|
option :continue_ci_failures, long: "--continue-ci-failures", desc: "Set K_RELEASE_CI_CONTINUE=true for release commands"
|
|
408
443
|
option :ci_workflows, long: "--ci-workflows", value: {type: String, usage: "LIST"}, desc: "Pass a comma-separated CI workflow monitor subset through to kettle-release commands"
|
|
409
444
|
option :skip_bundle_audit, long: "--skip-bundle-audit", desc: "Skip bundle:audit/update during release rake checks"
|
|
445
|
+
option :skip_remotes, long: "--skip-remotes", value: {type: String, usage: "LIST"}, desc: "Pass a comma-separated git remote skip list through to kettle-release commands"
|
|
410
446
|
option :no_auto_floors, long: "--no-auto-floors", desc: "Do not raise family dependency floors between member releases" do
|
|
411
447
|
options[:no_auto_floors] = true
|
|
412
448
|
end
|
|
@@ -428,6 +464,7 @@ module Kettle
|
|
|
428
464
|
release_continue_ci_failures: truthy_option?(:continue_ci_failures),
|
|
429
465
|
release_ci_workflows: options[:ci_workflows],
|
|
430
466
|
release_skip_bundle_audit: truthy_option?(:skip_bundle_audit),
|
|
467
|
+
release_skip_remotes: options[:skip_remotes],
|
|
431
468
|
release_auto_dependency_floors: !truthy_option?(:no_auto_floors),
|
|
432
469
|
accept: !options.key?(:accept) || options[:accept],
|
|
433
470
|
tag: truthy_option?(:tag),
|
|
@@ -448,6 +485,12 @@ module Kettle
|
|
|
448
485
|
description "Plan or execute git pull --rebase per member."
|
|
449
486
|
end
|
|
450
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
|
+
|
|
451
494
|
class Up < WorkflowCommand
|
|
452
495
|
command_name "up"
|
|
453
496
|
usage "[options]"
|
|
@@ -468,14 +511,17 @@ module Kettle
|
|
|
468
511
|
command Bupb
|
|
469
512
|
command Bex
|
|
470
513
|
command Install
|
|
514
|
+
command Bump
|
|
471
515
|
command BumpVersion
|
|
472
516
|
command AddChangelog
|
|
473
517
|
command Release
|
|
474
518
|
command Push
|
|
475
519
|
command Pull
|
|
520
|
+
command Sync
|
|
476
521
|
command Up
|
|
477
522
|
command BranchLanes
|
|
478
523
|
command ReleaseState
|
|
524
|
+
command State
|
|
479
525
|
|
|
480
526
|
prepend ReturningMain
|
|
481
527
|
|
|
@@ -514,7 +560,8 @@ module Kettle
|
|
|
514
560
|
else
|
|
515
561
|
Orderer.new(members: members, mode: config.order_mode, hints: config.order_hints).ordered
|
|
516
562
|
end
|
|
517
|
-
|
|
563
|
+
release_state_results = release_state_results_for_selection(config: config, members: ordered, only: options[:only])
|
|
564
|
+
selected = Selection.new(members: ordered, release_state_results: release_state_results).apply(only: options[:only], exclude: options[:exclude], start_at: start_at.member)
|
|
518
565
|
result_members = selected
|
|
519
566
|
results = command_results(command: command, config: config, members: result_members, options: options, start_at: start_at)
|
|
520
567
|
Report.new(
|
|
@@ -542,8 +589,14 @@ module Kettle
|
|
|
542
589
|
command_results_for_current_branch(command: command, config: config, members: members, options: options, start_at: start_at)
|
|
543
590
|
end
|
|
544
591
|
|
|
592
|
+
def release_state_results_for_selection(config:, members:, only:)
|
|
593
|
+
return nil unless only.to_s.split(",").map(&:strip).any? { |token| Selection.status_token?(token) }
|
|
594
|
+
|
|
595
|
+
ReleaseStateCheck.new(config: config, members: members).results
|
|
596
|
+
end
|
|
597
|
+
|
|
545
598
|
def command_results_for_current_branch(command:, config:, members:, options:, start_at: StartAt.new(nil, nil))
|
|
546
|
-
return bump_version_results(members: members, options: options
|
|
599
|
+
return bump_version_results(members: members, options: options, phase: command) if %w[bump bump-version].include?(command)
|
|
547
600
|
return add_changelog_results(members: members, options: options) if command == "add-changelog"
|
|
548
601
|
return branch_lane_results(config: config, members: members) if command == "branch-lanes"
|
|
549
602
|
return release_state_results(config: config, members: members) if command == "release-state"
|
|
@@ -567,11 +620,13 @@ module Kettle
|
|
|
567
620
|
continue_ci_failures: options[:release_continue_ci_failures],
|
|
568
621
|
ci_workflows: options[:release_ci_workflows],
|
|
569
622
|
skip_bundle_audit: options[:release_skip_bundle_audit],
|
|
623
|
+
skip_remotes: options[:release_skip_remotes],
|
|
570
624
|
auto_dependency_floors: options[:release_auto_dependency_floors],
|
|
571
625
|
gha_sha_pins_upgrade: options[:gha_sha_pins_upgrade],
|
|
572
626
|
gha_sha_pins_check: options[:check],
|
|
573
627
|
env_overrides: options[:workflow_env],
|
|
574
628
|
debug: options[:debug],
|
|
629
|
+
verbose: options[:verbose],
|
|
575
630
|
jobs: options[:jobs],
|
|
576
631
|
progress_io: progress_io(command, options),
|
|
577
632
|
bup_args: options[:bup_args],
|
|
@@ -593,14 +648,14 @@ module Kettle
|
|
|
593
648
|
return false if config.release_target_branches.empty?
|
|
594
649
|
return false if command == "release-state"
|
|
595
650
|
return false if command == "branch-lanes"
|
|
596
|
-
return false unless WORKFLOW_COMMANDS.include?(command) || %w[bump-version install add-changelog].include?(command)
|
|
651
|
+
return false unless WORKFLOW_COMMANDS.include?(command) || %w[bump bump-version install add-changelog].include?(command)
|
|
597
652
|
|
|
598
653
|
!WORKFLOW_COMMANDS.include?(command)
|
|
599
654
|
end
|
|
600
655
|
|
|
601
656
|
def member_local_branch_target_command?(command, config, members)
|
|
602
657
|
return false if !config.release_target_branches.empty?
|
|
603
|
-
return false unless %w[bump-version install add-changelog].include?(command)
|
|
658
|
+
return false unless %w[bump bump-version install add-changelog].include?(command)
|
|
604
659
|
|
|
605
660
|
members.any? { |member| member_release_config(member: member, config: config) }
|
|
606
661
|
end
|
|
@@ -686,14 +741,15 @@ module Kettle
|
|
|
686
741
|
StartAt.new(member, branch)
|
|
687
742
|
end
|
|
688
743
|
|
|
689
|
-
def bump_version_results(members:, options:)
|
|
744
|
+
def bump_version_results(members:, options:, phase:)
|
|
690
745
|
require_relative "version_bump"
|
|
691
746
|
|
|
692
747
|
results = VersionBump.new(
|
|
693
748
|
members: members,
|
|
694
749
|
target_version: options[:target_version],
|
|
695
750
|
from_version: options[:from_version],
|
|
696
|
-
mode: bump_version_mode(options)
|
|
751
|
+
mode: bump_version_mode(options),
|
|
752
|
+
phase: phase
|
|
697
753
|
).results
|
|
698
754
|
return results if options[:check] || !options[:commit]
|
|
699
755
|
return results unless results.all?(&:ok?)
|
|
@@ -111,7 +111,7 @@ module Kettle
|
|
|
111
111
|
@otp_coordinator = otp_coordinator
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
def call(member:, phase:, command:, env: {}, interactive: false)
|
|
114
|
+
def call(member:, phase:, command:, env: {}, interactive: false, stdout_line_handler: nil)
|
|
115
115
|
argv = command_argv(member: member, command: command, env: env)
|
|
116
116
|
process_env = process_env(member: member, env: env)
|
|
117
117
|
spawn_options = process_options
|
|
@@ -120,6 +120,8 @@ module Kettle
|
|
|
120
120
|
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
121
121
|
stdout, stderr, status = if interactive
|
|
122
122
|
run_interactive(env: process_env, argv: argv, chdir: member.root, member_name: member.name, process_options: spawn_options)
|
|
123
|
+
elsif stdout_line_handler
|
|
124
|
+
run_streaming(env: process_env, argv: argv, chdir: member.root, process_options: spawn_options, stdout_line_handler: stdout_line_handler)
|
|
123
125
|
else
|
|
124
126
|
Open3.capture3(process_env, *argv, chdir: member.root, **spawn_options)
|
|
125
127
|
end
|
|
@@ -145,6 +147,41 @@ module Kettle
|
|
|
145
147
|
|
|
146
148
|
attr_reader :execute, :accept, :gem_signing_password, :otp_coordinator
|
|
147
149
|
|
|
150
|
+
def run_streaming(env:, argv:, chdir:, process_options:, stdout_line_handler:)
|
|
151
|
+
captured_stdout = +""
|
|
152
|
+
captured_stderr = +""
|
|
153
|
+
stdout_line_buffer = +""
|
|
154
|
+
status = nil
|
|
155
|
+
Open3.popen3(env, *argv, chdir: chdir, **process_options) do |_input, output, error, wait_thread|
|
|
156
|
+
readers = [output, error]
|
|
157
|
+
until readers.empty?
|
|
158
|
+
ready = IO.select(readers)
|
|
159
|
+
ready.first.each do |reader|
|
|
160
|
+
if reader.equal?(output)
|
|
161
|
+
chunk = reader.readpartial(1024)
|
|
162
|
+
captured_stdout << chunk
|
|
163
|
+
stdout_line_buffer = stream_stdout_lines(stdout_line_buffer, chunk, stdout_line_handler)
|
|
164
|
+
else
|
|
165
|
+
captured_stderr << reader.readpartial(1024)
|
|
166
|
+
end
|
|
167
|
+
rescue EOFError
|
|
168
|
+
readers.delete(reader)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
stdout_line_handler.call(stdout_line_buffer) unless stdout_line_buffer.empty?
|
|
172
|
+
status = wait_thread.value
|
|
173
|
+
end
|
|
174
|
+
[captured_stdout, captured_stderr, status]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def stream_stdout_lines(buffer, chunk, handler)
|
|
178
|
+
pending = buffer + chunk
|
|
179
|
+
lines = pending.lines
|
|
180
|
+
remainder = pending.end_with?("\n") ? +"" : lines.pop.to_s
|
|
181
|
+
lines.each { |line| handler.call(line.chomp) }
|
|
182
|
+
remainder
|
|
183
|
+
end
|
|
184
|
+
|
|
148
185
|
def run_interactive(env:, argv:, chdir:, member_name:, process_options:)
|
|
149
186
|
return run_interactive_pty(env: env, argv: argv, chdir: chdir, member_name: member_name, process_options: process_options) if pty_available?
|
|
150
187
|
|
data/lib/kettle/family/config.rb
CHANGED
|
@@ -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
|
|
@@ -278,9 +287,9 @@ module Kettle
|
|
|
278
287
|
def default_release_disable_local_path_env
|
|
279
288
|
local_envs = %w[
|
|
280
289
|
K_JEM_TEMPLATING
|
|
281
|
-
|
|
290
|
+
STRUCTUREDMERGE_DEV
|
|
282
291
|
TSLP_DEV
|
|
283
|
-
|
|
292
|
+
KETTLE_DEV_DEV
|
|
284
293
|
RUBOCOP_LTS_DEV
|
|
285
294
|
PBOLING_DEV
|
|
286
295
|
GALTZO_FLOSS_DEV
|
|
@@ -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)
|