kettle-dev 2.5.11 → 2.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +88 -1
- data/README.md +1 -1
- data/exe/kettle-changelog +25 -3
- data/exe/kettle-release +26 -2
- data/exe/kettle-release-secrets-doctor +39 -0
- data/lib/kettle/dev/bundler_env_guard.rb +1 -0
- data/lib/kettle/dev/changelog_cli.rb +43 -1
- data/lib/kettle/dev/ci_monitor.rb +235 -7
- data/lib/kettle/dev/interactive_release_command.rb +16 -5
- data/lib/kettle/dev/lockfile_reset.rb +22 -0
- data/lib/kettle/dev/pre_release_cli.rb +49 -4
- data/lib/kettle/dev/release_cli.rb +342 -18
- data/lib/kettle/dev/release_notifier.rb +27 -0
- data/lib/kettle/dev/release_secrets.rb +16 -1
- data/lib/kettle/dev/release_secrets_doctor.rb +204 -0
- data/lib/kettle/dev/version.rb +1 -1
- data/lib/kettle/dev.rb +2 -0
- data.tar.gz.sig +0 -0
- metadata +10 -6
- 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: 76cf339458385418bcf752559dbb9c6278f3b95ebfa27b26781591564179f263
|
|
4
|
+
data.tar.gz: 66cae3bfb62ecd922bf2b6ecc16049389a860a20dbaa8492fd6578bdcf3b4922
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0ae8aa5d0113e226dab9dbb332b42328bfe738c84ce88a21d919c3a0249d2ad3f70d905aa4cbd76c903608846da8a485a6e68c710934e7eac2443517d71d6a96
|
|
7
|
+
data.tar.gz: 4470d0bd47c7c95a616b8513a6b590911a4086e6d6f31330e96c45059774ac4d172a0c98ccf5aad53384208cf40fb02de237c68c6326a430acaf89adfe9a89c2
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,89 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [2.5.13] - 2026-07-31
|
|
34
|
+
|
|
35
|
+
- TAG: [v2.5.13][2.5.13t]
|
|
36
|
+
- COVERAGE: 91.81% -- 5137/5595 lines in 46 files
|
|
37
|
+
- BRANCH COVERAGE: 76.06% -- 1944/2556 branches in 46 files
|
|
38
|
+
- 50.41% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- `kettle-release` now treats `origin` as the default required parity remote
|
|
43
|
+
while allowing optional mirror remotes to be skipped after fetch retries,
|
|
44
|
+
so a transient Codeberg/GitLab mirror outage does not block publishing.
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- `kettle-release --events` now emits `remote_parity` events for remote parity
|
|
49
|
+
fetch attempts, skipped optional remotes, required failures, and parity
|
|
50
|
+
completion.
|
|
51
|
+
- `kettle-release --events` now emits `ci_monitor` events around CI monitoring
|
|
52
|
+
start, per-workflow GitHub Actions progress, GitLab pipeline outcomes,
|
|
53
|
+
success, and failure.
|
|
54
|
+
- `kettle-release --events` now emits `pre_release` events around
|
|
55
|
+
`kettle-pre-release` checks and selected check summaries.
|
|
56
|
+
- `kettle-changelog --events` now emits `changelog` events around release plan,
|
|
57
|
+
coverage generation, and changelog update activity, and `kettle-release
|
|
58
|
+
--events` forwards those child events.
|
|
59
|
+
- `kettle-release --events` now emits `release_lockfile` and `release_probe`
|
|
60
|
+
events for release lockfile reset/validation and published-gem availability
|
|
61
|
+
probes.
|
|
62
|
+
- `kettle-dev` now requires `kettle-ndjson` 0.1.9 or newer so release event
|
|
63
|
+
streams resolve against the protocol that includes remote parity and CI
|
|
64
|
+
monitor, pre-release, changelog, release lockfile, and release probe events.
|
|
65
|
+
|
|
66
|
+
- `kettle-release --events` now emits GitHub CI wait/start/tick monitor events
|
|
67
|
+
while waiting for workflow runs to appear and complete.
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- `kettle-release --events` now emits clearer `command_step` names and compact
|
|
72
|
+
per-command summaries for common release commands instead of shell-derived
|
|
73
|
+
labels such as `env__u`.
|
|
74
|
+
|
|
75
|
+
## [2.5.12] - 2026-07-31
|
|
76
|
+
|
|
77
|
+
- TAG: [v2.5.12][2.5.12t]
|
|
78
|
+
- COVERAGE: 91.73% -- 4961/5408 lines in 46 files
|
|
79
|
+
- BRANCH COVERAGE: 75.98% -- 1850/2435 branches in 46 files
|
|
80
|
+
- 50.68% documented
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
|
|
84
|
+
- `kettle-release-secrets-doctor` can probe 1Password release secret
|
|
85
|
+
authorization across same-process, child-process, and threaded shapes.
|
|
86
|
+
|
|
87
|
+
- `kettle-release-secrets-doctor` now probes additional 1Password
|
|
88
|
+
authorization boundaries, including parent-child, Bundler child, and
|
|
89
|
+
Bundler-env-reset child process shapes.
|
|
90
|
+
|
|
91
|
+
- `kettle-release --events` now emits `secret_provider` events around release
|
|
92
|
+
secret keepalives and provider-backed prompt responses.
|
|
93
|
+
|
|
94
|
+
### Fixed
|
|
95
|
+
|
|
96
|
+
- `kettle-release` now keeps configured release secrets providers warm during
|
|
97
|
+
CI waits and alerts before provider lookups, reducing missed 1Password
|
|
98
|
+
authorization prompts during long release runs.
|
|
99
|
+
|
|
100
|
+
- `kettle-release` keepalive alerts now include the elapsed release time so
|
|
101
|
+
delayed 1Password prompts are easier to correlate with the run.
|
|
102
|
+
|
|
103
|
+
- `kettle-dev` now requires `kettle-ndjson` 0.1.4 or newer so
|
|
104
|
+
`kettle-release --events=secret_provider` cannot resolve against an older
|
|
105
|
+
event protocol.
|
|
106
|
+
- `kettle-release` lockfile reset now preserves existing bundle platforms and
|
|
107
|
+
adds the current host platform, preventing release-prep lockfiles from losing
|
|
108
|
+
Linux support during full rebuilds.
|
|
109
|
+
- `kettle-pre-release` Markdown image URL normalization now keeps encoded query
|
|
110
|
+
values stable, avoiding release-time churn in shields URLs with nested URL
|
|
111
|
+
parameters.
|
|
112
|
+
- `kettle-release` now runs `bin/setup` with inherited Bundler bootstrap
|
|
113
|
+
variables unset, so a release lockfile reset can install newly selected gems
|
|
114
|
+
before later release tasks run.
|
|
115
|
+
|
|
33
116
|
## [2.5.11] - 2026-07-30
|
|
34
117
|
|
|
35
118
|
- TAG: [v2.5.11][2.5.11t]
|
|
@@ -3077,7 +3160,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
3077
3160
|
- Selecting will run the selected workflow via `act`
|
|
3078
3161
|
- This may move to its own gem in the future.
|
|
3079
3162
|
|
|
3080
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.
|
|
3163
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.13...HEAD
|
|
3164
|
+
[2.5.13]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.12...v2.5.13
|
|
3165
|
+
[2.5.13t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.5.13
|
|
3166
|
+
[2.5.12]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.11...v2.5.12
|
|
3167
|
+
[2.5.12t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.5.12
|
|
3081
3168
|
[2.5.11]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.10...v2.5.11
|
|
3082
3169
|
[2.5.11t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.5.11
|
|
3083
3170
|
[2.5.10]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.9...v2.5.10
|
data/README.md
CHANGED
|
@@ -1005,7 +1005,7 @@ Thanks for RTFM. ☺️
|
|
|
1005
1005
|
[📌gitmoji]: https://gitmoji.dev
|
|
1006
1006
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1007
1007
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1008
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.
|
|
1008
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.595-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1009
1009
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
1010
1010
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1011
1011
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/exe/kettle-changelog
CHANGED
|
@@ -50,9 +50,11 @@ begin
|
|
|
50
50
|
|
|
51
51
|
# This library
|
|
52
52
|
require "kettle/dev"
|
|
53
|
+
require "kettle/ndjson"
|
|
53
54
|
require "kettle/dev/executable_version"
|
|
54
55
|
Kettle::Dev::ExecutableVersion.print_and_exit!(script_basename, ARGV, value_option: true)
|
|
55
|
-
|
|
56
|
+
machine_output = ARGV.any? { |arg| arg == "--json" || arg.start_with?("--events") }
|
|
57
|
+
Kettle::Dev::ExecutableVersion.print_header(script_basename) unless machine_output
|
|
56
58
|
rescue LoadError => e
|
|
57
59
|
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
|
58
60
|
warn("Hint: Ensure the host project has kettle-dev as a dependency and run bundle install.")
|
|
@@ -61,7 +63,7 @@ end
|
|
|
61
63
|
|
|
62
64
|
if ARGV.include?("-h") || ARGV.include?("--help")
|
|
63
65
|
puts <<~USAGE
|
|
64
|
-
Usage: kettle-changelog [--version VERSION] [--yes] [--update-prep] [--pending-release] [--release-state] [--refresh-cache] [--add-unreleased-entry --section SECTION --entry TEXT] [--json] [--no-strict] [--no-coverage-threshold]
|
|
66
|
+
Usage: kettle-changelog [--version VERSION] [--yes] [--update-prep] [--pending-release] [--release-state] [--refresh-cache] [--add-unreleased-entry --section SECTION --entry TEXT] [--json|--events[=TYPES]] [--no-strict] [--no-coverage-threshold]
|
|
65
67
|
|
|
66
68
|
Detects the current version from lib/**/version.rb, the latest live release, and
|
|
67
69
|
the most recent CHANGELOG.md release section, then prompts to confirm the selected plan:
|
|
@@ -82,6 +84,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
|
|
|
82
84
|
--section SECTION Unreleased section to receive the entry (Added, Changed, Deprecated, Removed, Fixed, Security)
|
|
83
85
|
--entry TEXT Changelog entry text; "- " is added when omitted
|
|
84
86
|
--json Print query output as JSON
|
|
87
|
+
--events[=TYPES] Print newline-delimited JSON changelog events
|
|
85
88
|
--no-strict Allow missing coverage and yard data (warnings only, no errors)
|
|
86
89
|
--no-coverage-threshold Generate coverage without hard-failing below configured thresholds
|
|
87
90
|
|
|
@@ -137,6 +140,22 @@ begin
|
|
|
137
140
|
Kettle::Dev::Versioning.normalize_explicit_version(version)
|
|
138
141
|
end
|
|
139
142
|
|
|
143
|
+
def extract_events_arg!(argv)
|
|
144
|
+
events = false
|
|
145
|
+
event_types = nil
|
|
146
|
+
argv.delete_if do |arg|
|
|
147
|
+
if arg == "--events"
|
|
148
|
+
events = true
|
|
149
|
+
elsif arg.start_with?("--events=")
|
|
150
|
+
events = true
|
|
151
|
+
event_types = arg.split("=", 2)[1]
|
|
152
|
+
else
|
|
153
|
+
false
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
[events, event_types]
|
|
157
|
+
end
|
|
158
|
+
|
|
140
159
|
# Determine if strict mode is enabled (default: true)
|
|
141
160
|
strict_mode = !ARGV.include?("--no-strict") && ENV.fetch("K_CHANGELOG_STRICT", "true").downcase != "false"
|
|
142
161
|
update_prep = ARGV.delete("--update-prep")
|
|
@@ -146,6 +165,8 @@ begin
|
|
|
146
165
|
refresh_cache = ARGV.delete("--refresh-cache")
|
|
147
166
|
add_unreleased_entry = ARGV.delete("--add-unreleased-entry") || ARGV.delete("--add-changelog-entry")
|
|
148
167
|
json_output = ARGV.delete("--json")
|
|
168
|
+
events_output, event_types = extract_events_arg!(ARGV)
|
|
169
|
+
Kettle::Dev::ExitAdapter.abort("--events cannot be combined with --json") if events_output && json_output
|
|
149
170
|
coverage_threshold_disabled = ARGV.include?("--no-coverage-threshold") || ARGV.include?("--no-coverage-thresholds")
|
|
150
171
|
coverage_hard = !coverage_threshold_disabled && ENV.fetch("K_CHANGELOG_COVERAGE_HARD", "true").downcase != "false"
|
|
151
172
|
version_override = extract_version_arg!(ARGV)
|
|
@@ -180,7 +201,8 @@ begin
|
|
|
180
201
|
exit(0)
|
|
181
202
|
end
|
|
182
203
|
|
|
183
|
-
|
|
204
|
+
event_stream = events_output ? Kettle::Ndjson.event_stream($stdout, types: event_types) : nil
|
|
205
|
+
cli = Kettle::Dev::ChangelogCLI.new(strict: strict_mode, enforce_coverage_thresholds: coverage_hard, update_prep: update_prep, version: version_override, refresh_cache: refresh_cache, yes: yes, event_stream: event_stream)
|
|
184
206
|
if release_state_query
|
|
185
207
|
state = cli.release_state
|
|
186
208
|
puts(json_output ? JSON.pretty_generate(state) : cli.release_state_table(state))
|
data/exe/kettle-release
CHANGED
|
@@ -49,7 +49,7 @@ end
|
|
|
49
49
|
# Do not guard with __FILE__ == $PROGRAM_NAME because binstubs use Kernel.load.
|
|
50
50
|
if ARGV.include?("-h") || ARGV.include?("--help")
|
|
51
51
|
puts <<~USAGE
|
|
52
|
-
Usage: kettle-release [--version VERSION] [--local-ci] [--yes] [--appraisal-update] [--skip-bundle-audit] [--skip-steps STEPS] [--ci-workflows WORKFLOWS] [--skip-remotes REMOTES] [--secrets-provider NAME] [--json|--events[=TYPES]] [--report PATH] [start_step=<0-19>]
|
|
52
|
+
Usage: kettle-release [--version VERSION] [--local-ci] [--yes] [--appraisal-update] [--skip-bundle-audit] [--skip-steps STEPS] [--ci-workflows WORKFLOWS] [--skip-remotes REMOTES] [--required-remotes REMOTES] [--secrets-provider NAME] [--json|--events[=TYPES]] [--report PATH] [start_step=<0-19>]
|
|
53
53
|
|
|
54
54
|
Automates the release flow for a Ruby gem in the host project.
|
|
55
55
|
|
|
@@ -90,6 +90,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
|
|
|
90
90
|
--skip-bundle-audit # Skip bundle:audit/update during release rake checks
|
|
91
91
|
--ci-workflows WORKFLOWS # Comma-separated workflow files or stems to monitor at CI step 10
|
|
92
92
|
--skip-remotes REMOTES # Comma-separated git remote names to exclude from release fetch/push parity
|
|
93
|
+
--required-remotes REMOTES # Comma-separated remote names that must fetch for release parity; defaults to origin
|
|
93
94
|
--secrets-provider NAME # Release secrets provider: interactive, 1password
|
|
94
95
|
--json # Print final machine-readable release report as JSON
|
|
95
96
|
--events[=TYPES] # Print newline-delimited JSON release events, optionally filtered by type
|
|
@@ -104,6 +105,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
|
|
|
104
105
|
K_RELEASE_LOCAL_CI_WORKFLOW # Name of workflow (without .yml) for local CI; defaults to locked_deps or first
|
|
105
106
|
K_RELEASE_CI_WORKFLOWS # Comma-separated workflow files or stems to monitor at CI step 10
|
|
106
107
|
K_RELEASE_SKIP_REMOTES # Comma-separated git remote names to exclude from release fetch/push parity
|
|
108
|
+
K_RELEASE_REQUIRED_REMOTES # Comma-separated remotes that must fetch for release parity; defaults to origin
|
|
107
109
|
KETTLE_RELEASE_SECRETS_PROVIDER=1password
|
|
108
110
|
# Load release secrets through the configured provider
|
|
109
111
|
KETTLE_RELEASE_1PASSWORD_ITEM=Rubygems
|
|
@@ -215,6 +217,27 @@ def extract_skip_remotes_arg!(argv)
|
|
|
215
217
|
remotes
|
|
216
218
|
end
|
|
217
219
|
|
|
220
|
+
def extract_required_remotes_arg!(argv)
|
|
221
|
+
remotes = nil
|
|
222
|
+
if (idx = argv.index("--required-remotes"))
|
|
223
|
+
remotes = argv[idx + 1]
|
|
224
|
+
if remotes.to_s.empty? || remotes.to_s.start_with?("-")
|
|
225
|
+
Kettle::Dev::ExitAdapter.abort("--required-remotes requires a comma-separated remote list")
|
|
226
|
+
end
|
|
227
|
+
argv.slice!(idx, 2)
|
|
228
|
+
end
|
|
229
|
+
argv.delete_if do |arg|
|
|
230
|
+
if arg.start_with?("--required-remotes=", "required_remotes=")
|
|
231
|
+
remotes = arg.split("=", 2)[1]
|
|
232
|
+
Kettle::Dev::ExitAdapter.abort("--required-remotes requires a comma-separated remote list") if remotes.to_s.empty?
|
|
233
|
+
true
|
|
234
|
+
else
|
|
235
|
+
false
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
remotes
|
|
239
|
+
end
|
|
240
|
+
|
|
218
241
|
def extract_report_arg!(argv)
|
|
219
242
|
report_path = nil
|
|
220
243
|
if (idx = argv.index("--report"))
|
|
@@ -286,12 +309,13 @@ version_override = extract_version_arg!(ARGV)
|
|
|
286
309
|
skip_steps = extract_skip_steps_arg!(ARGV)
|
|
287
310
|
ci_workflows = extract_ci_workflows_arg!(ARGV)
|
|
288
311
|
skip_remotes = extract_skip_remotes_arg!(ARGV)
|
|
312
|
+
required_remotes = extract_required_remotes_arg!(ARGV)
|
|
289
313
|
report_path = extract_report_arg!(ARGV)
|
|
290
314
|
secrets_provider = extract_secrets_provider_arg!(ARGV)
|
|
291
315
|
|
|
292
316
|
begin
|
|
293
317
|
event_stream = events_output ? Kettle::Ndjson.event_stream($stdout, types: event_types) : nil
|
|
294
|
-
Kettle::Dev::ReleaseCLI.new(start_step: start_step, local_ci: local_ci, version: version_override, appraisal_task: appraisal_task, skip_steps: skip_steps, skip_bundle_audit: skip_bundle_audit, ci_workflows: ci_workflows, skip_remotes: skip_remotes, secrets_provider_name: secrets_provider, yes: yes, event_stream: event_stream, json_output: json_output, json_io: $stdout, report_path: report_path).run
|
|
318
|
+
Kettle::Dev::ReleaseCLI.new(start_step: start_step, local_ci: local_ci, version: version_override, appraisal_task: appraisal_task, skip_steps: skip_steps, skip_bundle_audit: skip_bundle_audit, ci_workflows: ci_workflows, skip_remotes: skip_remotes, required_remotes: required_remotes, secrets_provider_name: secrets_provider, yes: yes, event_stream: event_stream, json_output: json_output, json_io: $stdout, report_path: report_path).run
|
|
295
319
|
rescue LoadError => e
|
|
296
320
|
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
|
297
321
|
warn(Array(e.backtrace).join("\n")) if ENV["DEBUG"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "optparse"
|
|
5
|
+
|
|
6
|
+
$stdout.sync = true
|
|
7
|
+
$stderr.sync = true
|
|
8
|
+
|
|
9
|
+
script_basename = File.basename(__FILE__)
|
|
10
|
+
repo_lib = File.expand_path("../lib", __dir__)
|
|
11
|
+
$LOAD_PATH.unshift(repo_lib) if File.directory?(repo_lib) && !$LOAD_PATH.include?(repo_lib)
|
|
12
|
+
|
|
13
|
+
begin
|
|
14
|
+
require "kettle/dev"
|
|
15
|
+
require "kettle/dev/executable_version"
|
|
16
|
+
Kettle::Dev::ExecutableVersion.print_and_exit!(script_basename, ARGV, value_option: true)
|
|
17
|
+
Kettle::Dev::ExecutableVersion.print_header(script_basename)
|
|
18
|
+
rescue LoadError
|
|
19
|
+
warn "kettle-release-secrets-doctor must run with kettle-dev on the load path"
|
|
20
|
+
exit 1
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
options = Kettle::Dev::ReleaseSecretsDoctor.options_from_env
|
|
24
|
+
|
|
25
|
+
OptionParser.new do |parser|
|
|
26
|
+
parser.banner = "Usage: kettle-release-secrets-doctor [options]"
|
|
27
|
+
parser.on("--provider NAME", "Secrets provider name, default: op") { |value| options[:provider] = value }
|
|
28
|
+
parser.on("--sleep SECONDS", Float, "Seconds to wait between probes") { |value| options[:sleep_seconds] = value }
|
|
29
|
+
parser.on("--keepalive SECONDS", Float, "Run keepalive every N seconds while waiting; 0 disables") { |value| options[:keepalive_seconds] = value }
|
|
30
|
+
parser.on("--shape SHAPE", "Shape: #{Kettle::Dev::ReleaseSecretsDoctor::SHAPES.join(", ")}") { |value| options[:shape] = value }
|
|
31
|
+
parser.on("--otp", "Fetch RubyGems OTP after the wait") { options[:otp] = true }
|
|
32
|
+
end.parse!
|
|
33
|
+
|
|
34
|
+
begin
|
|
35
|
+
Kettle::Dev::ReleaseSecretsDoctor.new(options: options, program_name: $PROGRAM_NAME).run
|
|
36
|
+
rescue Kettle::Dev::Error => e
|
|
37
|
+
warn e.message
|
|
38
|
+
exit 1
|
|
39
|
+
end
|
|
@@ -5,6 +5,7 @@ require "json"
|
|
|
5
5
|
require "net/http"
|
|
6
6
|
require "uri"
|
|
7
7
|
require "fileutils"
|
|
8
|
+
require "kettle/ndjson"
|
|
8
9
|
|
|
9
10
|
module Kettle
|
|
10
11
|
module Dev
|
|
@@ -28,7 +29,7 @@ module Kettle
|
|
|
28
29
|
# @param update_prep [Boolean] when true, update the most recent prepared release section in place
|
|
29
30
|
# @param version [String, nil] explicit version override for gems without a literal VERSION constant
|
|
30
31
|
# @param yes [Boolean] when true, approve the selected release plan without prompting
|
|
31
|
-
def initialize(strict: true, enforce_coverage_thresholds: true, update_prep: false, version: nil, root: Kettle::Dev::CIHelpers.project_root, refresh_cache: false, yes: false)
|
|
32
|
+
def initialize(strict: true, enforce_coverage_thresholds: true, update_prep: false, version: nil, root: Kettle::Dev::CIHelpers.project_root, refresh_cache: false, yes: false, event_stream: nil)
|
|
32
33
|
@root = root
|
|
33
34
|
@changelog_path = resolved_changelog_path
|
|
34
35
|
@coverage_root = resolved_coverage_root
|
|
@@ -39,6 +40,7 @@ module Kettle
|
|
|
39
40
|
@version_override = Kettle::Dev::Versioning.normalize_explicit_version(version)
|
|
40
41
|
@refresh_cache = refresh_cache
|
|
41
42
|
@yes = !!yes
|
|
43
|
+
@event_recorder = Kettle::Ndjson.event_recorder(event_stream, phase_timings: [])
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
# Main entry point to update CHANGELOG.md
|
|
@@ -70,6 +72,7 @@ module Kettle
|
|
|
70
72
|
|
|
71
73
|
if plan.fetch(:action) == :update_prepared_release
|
|
72
74
|
update_prepared_release!(changelog, today, owner, repo, line_cov_line, branch_cov_line, yard_line)
|
|
75
|
+
emit_changelog_event(action: "update", status: "ok", version: version, plan: plan.fetch(:action).to_s)
|
|
73
76
|
return
|
|
74
77
|
end
|
|
75
78
|
|
|
@@ -140,6 +143,7 @@ module Kettle
|
|
|
140
143
|
updated = updated.rstrip + "\n"
|
|
141
144
|
|
|
142
145
|
File.write(@changelog_path, updated)
|
|
146
|
+
emit_changelog_event(action: "update", status: "ok", version: version, plan: plan.fetch(:action).to_s)
|
|
143
147
|
puts "CHANGELOG.md updated with v#{version} section."
|
|
144
148
|
end
|
|
145
149
|
|
|
@@ -348,6 +352,16 @@ module Kettle
|
|
|
348
352
|
puts " latest released for current series: #{plan.fetch(:latest_for_series) || "unknown"}"
|
|
349
353
|
puts " latest CHANGELOG.md release: #{plan.fetch(:latest_changelog_version) || "none"}"
|
|
350
354
|
puts " gem: #{plan.fetch(:gem_name) || "unknown"}"
|
|
355
|
+
emit_changelog_event(
|
|
356
|
+
action: "plan",
|
|
357
|
+
status: "ok",
|
|
358
|
+
plan: plan.fetch(:action).to_s,
|
|
359
|
+
version: plan.fetch(:version),
|
|
360
|
+
gem_name: plan.fetch(:gem_name),
|
|
361
|
+
latest_overall: plan.fetch(:latest_overall),
|
|
362
|
+
latest_for_series: plan.fetch(:latest_for_series),
|
|
363
|
+
latest_changelog_version: plan.fetch(:latest_changelog_version)
|
|
364
|
+
)
|
|
351
365
|
if @yes
|
|
352
366
|
puts("Continue with this plan? [y/N]: y")
|
|
353
367
|
return
|
|
@@ -665,20 +679,25 @@ module Kettle
|
|
|
665
679
|
coverage_dir = File.dirname(@coverage_path)
|
|
666
680
|
if Dir.exist?(coverage_dir)
|
|
667
681
|
puts "Cleaning old coverage data from #{Kettle::Dev.display_path(coverage_dir)}..."
|
|
682
|
+
emit_changelog_event(action: "coverage_clean", status: "started", path: Kettle::Dev.display_path(coverage_dir))
|
|
668
683
|
Dir.glob(File.join(coverage_dir, "*")).each do |file|
|
|
669
684
|
File.delete(file) if File.file?(file)
|
|
670
685
|
end
|
|
686
|
+
emit_changelog_event(action: "coverage_clean", status: "ok", path: Kettle::Dev.display_path(coverage_dir))
|
|
671
687
|
end
|
|
672
688
|
|
|
673
689
|
puts "Generating fresh coverage data by running: bundle exec kettle-test"
|
|
690
|
+
emit_changelog_event(action: "coverage", status: "started", command: "bundle exec kettle-test", root: Kettle::Dev.display_path(@coverage_root))
|
|
674
691
|
|
|
675
692
|
success = system(changelog_coverage_env, "bundle", "exec", "kettle-test", chdir: @coverage_root)
|
|
676
693
|
|
|
677
694
|
unless success
|
|
695
|
+
emit_changelog_event(action: "coverage", status: "failed", command: "bundle exec kettle-test", root: Kettle::Dev.display_path(@coverage_root), reason: "exit status #{$?.exitstatus || "unknown"}")
|
|
678
696
|
raise "bundle exec kettle-test failed with exit status #{$?.exitstatus || "unknown"}"
|
|
679
697
|
end
|
|
680
698
|
|
|
681
699
|
puts "Coverage generation complete."
|
|
700
|
+
emit_changelog_event(action: "coverage", status: "ok", command: "bundle exec kettle-test", root: Kettle::Dev.display_path(@coverage_root))
|
|
682
701
|
|
|
683
702
|
ensure_changelog_coverage_json!
|
|
684
703
|
else
|
|
@@ -739,6 +758,29 @@ module Kettle
|
|
|
739
758
|
end
|
|
740
759
|
end
|
|
741
760
|
|
|
761
|
+
def emit_changelog_event(action:, status:, **payload)
|
|
762
|
+
mark = case status.to_s
|
|
763
|
+
when "started"
|
|
764
|
+
">"
|
|
765
|
+
when "ok", "skipped"
|
|
766
|
+
"."
|
|
767
|
+
when "failed"
|
|
768
|
+
"!"
|
|
769
|
+
else
|
|
770
|
+
"?"
|
|
771
|
+
end
|
|
772
|
+
Kettle::Ndjson.emit_event(
|
|
773
|
+
@event_recorder,
|
|
774
|
+
"changelog",
|
|
775
|
+
payload.merge(
|
|
776
|
+
action: action,
|
|
777
|
+
phase: "release",
|
|
778
|
+
status: status,
|
|
779
|
+
mark: mark
|
|
780
|
+
)
|
|
781
|
+
)
|
|
782
|
+
end
|
|
783
|
+
|
|
742
784
|
def changelog_coverage_env
|
|
743
785
|
env = BundlerEnvGuard.unbundled_env.merge(
|
|
744
786
|
"PATH" => ENV.fetch("PATH", ""),
|