kettle-dev 3.0.5 → 3.0.7
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 +35 -1
- data/README.md +4 -18
- data/exe/kettle-release +17 -2
- data/lib/kettle/dev/ci_monitor.rb +83 -74
- data/lib/kettle/dev/markdown_reference_validator.rb +11 -1
- data/lib/kettle/dev/release_cli.rb +46 -4
- data/lib/kettle/dev/version.rb +1 -1
- 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: a3fdb8abe3a10685ec3e0fc37d17a0c0b5f85ed834ba85c8863e34e0bd64e5f9
|
|
4
|
+
data.tar.gz: 6261b1b044c0c301c219f5c2c9a0d2e6260b5b231784d49e75fc9e3ae12f536a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a33c7c722b54f372053469108187e4aab0fb0135633870fc78f33364d85e37c7ef41bf3db95e5a0d571881f8aba735262ff11327a57ba62964dbe66c5007808
|
|
7
|
+
data.tar.gz: 05f5b29d1459e646224fad07bfe1ac0c0987e594a68c829014311ac4ef02ebc52fbdf922e7c23f14f56ca92feedd87a2bce055fb5e809ff1cf10a49fd32e7eac
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,36 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [3.0.7] - 2026-08-15
|
|
34
|
+
|
|
35
|
+
- TAG: [v3.0.7][3.0.7t]
|
|
36
|
+
- COVERAGE: 91.41% -- 5674/6207 lines in 47 files
|
|
37
|
+
- BRANCH COVERAGE: 76.29% -- 2169/2843 branches in 47 files
|
|
38
|
+
- 50.62% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Ignore Ruby-style bracket expressions when validating Markdown reference links.
|
|
43
|
+
|
|
44
|
+
- Poll all unfinished GitHub Actions workflows each cycle so late-dispatched workflows cannot be missed by the global CI startup timeout.
|
|
45
|
+
|
|
46
|
+
## [3.0.6] - 2026-08-11
|
|
47
|
+
|
|
48
|
+
- TAG: [v3.0.6][3.0.6t]
|
|
49
|
+
- COVERAGE: 91.47% -- 5670/6199 lines in 47 files
|
|
50
|
+
- BRANCH COVERAGE: 76.17% -- 2161/2837 branches in 47 files
|
|
51
|
+
- 50.62% documented
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- Add --skip-changelog to release without skipping pre-release gates or the default task.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- Retry RubyGems publication outside the parent Bundler environment after an expired-edge OTP, with a short delay for TOTP refresh.
|
|
60
|
+
|
|
61
|
+
- Make --skip-changelog releases omit the unpublished standalone kettle-changelog dependency during lockfile normalization.
|
|
62
|
+
|
|
33
63
|
## [3.0.5] - 2026-08-10
|
|
34
64
|
|
|
35
65
|
- TAG: [v3.0.5][3.0.5t]
|
|
@@ -3464,7 +3494,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
3464
3494
|
- Selecting will run the selected workflow via `act`
|
|
3465
3495
|
- This may move to its own gem in the future.
|
|
3466
3496
|
|
|
3467
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.
|
|
3497
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.7...HEAD
|
|
3498
|
+
[3.0.7]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.6...v3.0.7
|
|
3499
|
+
[3.0.7t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.7
|
|
3500
|
+
[3.0.6]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.5...v3.0.6
|
|
3501
|
+
[3.0.6t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.6
|
|
3468
3502
|
[3.0.5]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.4...v3.0.5
|
|
3469
3503
|
[3.0.5t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.5
|
|
3470
3504
|
[3.0.4]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.3...v3.0.4
|
data/README.md
CHANGED
|
@@ -107,7 +107,7 @@ out to `kettle-release` for each member that needs publishing.
|
|
|
107
107
|
|
|
108
108
|
### Compatibility
|
|
109
109
|
|
|
110
|
-
Compatible with MRI Ruby 2.4.0+,
|
|
110
|
+
Compatible with MRI Ruby 2.4.0+, JRuby, and TruffleRuby.
|
|
111
111
|
CI workflows and Appraisals are generated for MRI Ruby 2.4+.
|
|
112
112
|
This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
|
|
113
113
|
may be higher than the gem's runtime compatibility floor when legacy Rubies are
|
|
@@ -702,8 +702,7 @@ See [SECURITY.md][🔐security].
|
|
|
702
702
|
## 🤝 Contributing
|
|
703
703
|
|
|
704
704
|
If you need some ideas of where to help, you could work on adding more code coverage,
|
|
705
|
-
|
|
706
|
-
or use the gem and think about how it could be better.
|
|
705
|
+
check [issues][🤝gh-issues] or [PRs][🤝gh-pulls], or use the gem and think about how it could be better.
|
|
707
706
|
|
|
708
707
|
We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
|
|
709
708
|
|
|
@@ -739,19 +738,6 @@ Made with [contributors-img][🖐contrib-rocks].
|
|
|
739
738
|
|
|
740
739
|
Also see GitLab Contributors: [https://gitlab.com/kettle-dev/kettle-dev/-/graphs/main][🚎contributors-gl]
|
|
741
740
|
|
|
742
|
-
<details markdown="1">
|
|
743
|
-
<summary>⭐️ Star History</summary>
|
|
744
|
-
|
|
745
|
-
<a href="https://star-history.com/kettle-dev/kettle-dev&Date">
|
|
746
|
-
<picture>
|
|
747
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kettle-dev/kettle-dev&type=Date&theme=dark" />
|
|
748
|
-
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kettle-dev/kettle-dev&type=Date" />
|
|
749
|
-
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kettle-dev/kettle-dev&type=Date" />
|
|
750
|
-
</picture>
|
|
751
|
-
</a>
|
|
752
|
-
|
|
753
|
-
</details>
|
|
754
|
-
|
|
755
741
|
## 📌 Versioning
|
|
756
742
|
|
|
757
743
|
This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
|
|
@@ -760,7 +746,7 @@ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with
|
|
|
760
746
|
For example:
|
|
761
747
|
|
|
762
748
|
```ruby
|
|
763
|
-
spec.add_dependency("kettle-dev", "~>
|
|
749
|
+
spec.add_dependency("kettle-dev", "~> 3.0")
|
|
764
750
|
```
|
|
765
751
|
|
|
766
752
|
<details markdown="1">
|
|
@@ -1007,7 +993,7 @@ Thanks for RTFM. ☺️
|
|
|
1007
993
|
[📌gitmoji]: https://gitmoji.dev
|
|
1008
994
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1009
995
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1010
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.
|
|
996
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.207-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1011
997
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
1012
998
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1013
999
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
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] [--required-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-changelog] [--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
|
|
|
@@ -87,6 +87,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
|
|
|
87
87
|
--version VERSION # Use this version instead of detecting VERSION from lib/**/version.rb
|
|
88
88
|
--yes # Auto-approve release confirmation prompts
|
|
89
89
|
--appraisal-update # Use slower appraisal:update instead of default appraisal:generate
|
|
90
|
+
--skip-changelog # Skip kettle-changelog but retain pre-release gates and the default task
|
|
90
91
|
--skip-bundle-audit # Skip bundle:audit/update during release rake checks
|
|
91
92
|
--ci-workflows WORKFLOWS # Comma-separated workflow files or stems to monitor at CI step 10
|
|
92
93
|
--skip-remotes REMOTES # Comma-separated git remote names to exclude from release fetch/push parity
|
|
@@ -175,6 +176,19 @@ def extract_skip_steps_arg!(argv)
|
|
|
175
176
|
skip_steps
|
|
176
177
|
end
|
|
177
178
|
|
|
179
|
+
def extract_skip_changelog_arg!(argv)
|
|
180
|
+
skip_changelog = !!argv.delete("--skip-changelog")
|
|
181
|
+
argv.delete_if do |arg|
|
|
182
|
+
if arg.start_with?("skip_changelog=")
|
|
183
|
+
skip_changelog = arg.split("=", 2)[1].to_s.downcase != "false"
|
|
184
|
+
true
|
|
185
|
+
else
|
|
186
|
+
false
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
skip_changelog
|
|
190
|
+
end
|
|
191
|
+
|
|
178
192
|
def extract_ci_workflows_arg!(argv)
|
|
179
193
|
workflows = nil
|
|
180
194
|
if (idx = argv.index("--ci-workflows"))
|
|
@@ -300,6 +314,7 @@ local_ci = ARGV.include?("--local-ci")
|
|
|
300
314
|
yes = !!ARGV.delete("--yes")
|
|
301
315
|
appraisal_task = ARGV.delete("--appraisal-update") ? "appraisal:update" : nil
|
|
302
316
|
skip_bundle_audit = !!ARGV.delete("--skip-bundle-audit")
|
|
317
|
+
skip_changelog = extract_skip_changelog_arg!(ARGV)
|
|
303
318
|
json_output = !!ARGV.delete("--json")
|
|
304
319
|
events_output, event_types = extract_events_arg!(ARGV)
|
|
305
320
|
Kettle::Dev::ExitAdapter.abort("--events cannot be combined with --json") if events_output && json_output
|
|
@@ -315,7 +330,7 @@ secrets_provider = extract_secrets_provider_arg!(ARGV)
|
|
|
315
330
|
|
|
316
331
|
begin
|
|
317
332
|
event_stream = events_output ? Kettle::Ndjson.event_stream($stdout, types: event_types) : nil
|
|
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
|
|
333
|
+
Kettle::Dev::ReleaseCLI.new(start_step: start_step, local_ci: local_ci, version: version_override, appraisal_task: appraisal_task, skip_steps: skip_steps, skip_changelog: skip_changelog, 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
|
|
319
334
|
rescue LoadError => e
|
|
320
335
|
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
|
321
336
|
warn(Array(e.backtrace).join("\n")) if ENV["DEBUG"]
|
|
@@ -342,50 +342,29 @@ module Kettle
|
|
|
342
342
|
poll_interval = github_poll_interval
|
|
343
343
|
start_deadline = monotonic_time + start_timeout
|
|
344
344
|
keepalive_timer = keepalive_timer(keepalive)
|
|
345
|
-
idx = 0
|
|
346
345
|
all_started_emitted = false
|
|
347
346
|
loop do
|
|
348
347
|
keepalive_timer.call
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
total: total
|
|
366
|
-
)
|
|
367
|
-
end
|
|
368
|
-
if started.size == total && !all_started_emitted
|
|
369
|
-
all_started_emitted = true
|
|
370
|
-
emit_ci_monitor_event(
|
|
371
|
-
event_recorder,
|
|
372
|
-
action: "github_started",
|
|
373
|
-
status: "ok",
|
|
374
|
-
provider: "github",
|
|
375
|
-
completed: passed.size,
|
|
376
|
-
total: total,
|
|
377
|
-
started: started.size
|
|
378
|
-
)
|
|
379
|
-
end
|
|
380
|
-
if Kettle::Dev::CIHelpers.success?(run)
|
|
381
|
-
unless passed[wf] || failed[wf]
|
|
382
|
-
passed[wf] = true
|
|
383
|
-
completed_workflow = wf
|
|
384
|
-
pbar&.increment
|
|
348
|
+
|
|
349
|
+
# Poll each unfinished workflow once per cycle. Polling one workflow
|
|
350
|
+
# per sleep made the global start timeout dependent on workflow order:
|
|
351
|
+
# late-dispatched workflows could be checked only once before timing
|
|
352
|
+
# out, while completed workflows consumed the remaining polls.
|
|
353
|
+
pending_workflows = workflows.reject { |candidate| passed[candidate] || failed[candidate] }
|
|
354
|
+
break if pending_workflows.empty?
|
|
355
|
+
|
|
356
|
+
completed = passed.size + failed.size
|
|
357
|
+
pending_workflows.each do |wf|
|
|
358
|
+
keepalive_timer.call
|
|
359
|
+
run = Kettle::Dev::CIHelpers.latest_run(owner: owner, repo: repo, workflow_file: wf, branch: branch, require_head: true, head_sha: head_sha)
|
|
360
|
+
completed_workflow = nil
|
|
361
|
+
if run
|
|
362
|
+
unless started[wf]
|
|
363
|
+
started[wf] = true
|
|
385
364
|
emit_ci_monitor_event(
|
|
386
365
|
event_recorder,
|
|
387
366
|
action: "github_workflow",
|
|
388
|
-
status: "
|
|
367
|
+
status: "started",
|
|
389
368
|
provider: "github",
|
|
390
369
|
workflow: wf,
|
|
391
370
|
url: run["html_url"],
|
|
@@ -395,45 +374,76 @@ module Kettle
|
|
|
395
374
|
total: total
|
|
396
375
|
)
|
|
397
376
|
end
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
conclusion: run["conclusion"],
|
|
410
|
-
completed: passed.size,
|
|
411
|
-
total: total,
|
|
412
|
-
reason: "Workflow failed"
|
|
413
|
-
)
|
|
414
|
-
unless continue_ci_failures?
|
|
415
|
-
abort("Workflow failed: #{wf} -> #{wf_url} Fix the workflow, then restart this tool from CI validation with: #{restart_hint}")
|
|
377
|
+
if started.size == total && !all_started_emitted
|
|
378
|
+
all_started_emitted = true
|
|
379
|
+
emit_ci_monitor_event(
|
|
380
|
+
event_recorder,
|
|
381
|
+
action: "github_started",
|
|
382
|
+
status: "ok",
|
|
383
|
+
provider: "github",
|
|
384
|
+
completed: passed.size,
|
|
385
|
+
total: total,
|
|
386
|
+
started: started.size
|
|
387
|
+
)
|
|
416
388
|
end
|
|
389
|
+
if Kettle::Dev::CIHelpers.success?(run)
|
|
390
|
+
unless passed[wf] || failed[wf]
|
|
391
|
+
passed[wf] = true
|
|
392
|
+
completed_workflow = wf
|
|
393
|
+
pbar&.increment
|
|
394
|
+
emit_ci_monitor_event(
|
|
395
|
+
event_recorder,
|
|
396
|
+
action: "github_workflow",
|
|
397
|
+
status: "ok",
|
|
398
|
+
provider: "github",
|
|
399
|
+
workflow: wf,
|
|
400
|
+
url: run["html_url"],
|
|
401
|
+
run_status: run["status"],
|
|
402
|
+
conclusion: run["conclusion"],
|
|
403
|
+
completed: passed.size,
|
|
404
|
+
total: total
|
|
405
|
+
)
|
|
406
|
+
end
|
|
407
|
+
elsif Kettle::Dev::CIHelpers.failed?(run) && !passed[wf] && !failed[wf]
|
|
408
|
+
puts
|
|
409
|
+
wf_url = run["html_url"] || "https://github.com/#{owner}/#{repo}/actions/workflows/#{wf}"
|
|
410
|
+
emit_ci_monitor_event(
|
|
411
|
+
event_recorder,
|
|
412
|
+
action: "github_workflow",
|
|
413
|
+
status: "failed",
|
|
414
|
+
provider: "github",
|
|
415
|
+
workflow: wf,
|
|
416
|
+
url: wf_url,
|
|
417
|
+
run_status: run["status"],
|
|
418
|
+
conclusion: run["conclusion"],
|
|
419
|
+
completed: passed.size,
|
|
420
|
+
total: total,
|
|
421
|
+
reason: "Workflow failed"
|
|
422
|
+
)
|
|
423
|
+
unless continue_ci_failures?
|
|
424
|
+
abort("Workflow failed: #{wf} -> #{wf_url} Fix the workflow, then restart this tool from CI validation with: #{restart_hint}")
|
|
425
|
+
end
|
|
417
426
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
427
|
+
failed[wf] = true
|
|
428
|
+
pbar&.increment
|
|
429
|
+
puts "Continuing CI monitoring despite #{wf} failure because K_RELEASE_CI_CONTINUE=true."
|
|
430
|
+
end
|
|
421
431
|
end
|
|
432
|
+
completed = passed.size + failed.size
|
|
433
|
+
emit_ci_monitor_event(
|
|
434
|
+
event_recorder,
|
|
435
|
+
action: "github_tick",
|
|
436
|
+
status: "started",
|
|
437
|
+
provider: "github",
|
|
438
|
+
workflow: wf,
|
|
439
|
+
run_status: run && run["status"],
|
|
440
|
+
conclusion: run && run["conclusion"],
|
|
441
|
+
completed_workflow: completed_workflow,
|
|
442
|
+
completed: completed,
|
|
443
|
+
total: total,
|
|
444
|
+
started: started.size
|
|
445
|
+
)
|
|
422
446
|
end
|
|
423
|
-
completed = passed.size + failed.size
|
|
424
|
-
emit_ci_monitor_event(
|
|
425
|
-
event_recorder,
|
|
426
|
-
action: "github_tick",
|
|
427
|
-
status: "started",
|
|
428
|
-
provider: "github",
|
|
429
|
-
workflow: wf,
|
|
430
|
-
run_status: run && run["status"],
|
|
431
|
-
conclusion: run && run["conclusion"],
|
|
432
|
-
completed_workflow: completed_workflow,
|
|
433
|
-
completed: completed,
|
|
434
|
-
total: total,
|
|
435
|
-
started: started.size
|
|
436
|
-
)
|
|
437
447
|
break if completed == total
|
|
438
448
|
if started.size < total && monotonic_time >= start_deadline
|
|
439
449
|
missing = (workflows - started.keys).join(", ")
|
|
@@ -452,7 +462,6 @@ module Kettle
|
|
|
452
462
|
abort("Timed out after #{start_timeout}s waiting for GitHub Actions workflows to start for HEAD #{head_sha[0, 12]}: #{missing}. Confirm GitHub Actions started, then restart this tool from CI validation with: #{restart_hint}")
|
|
453
463
|
end
|
|
454
464
|
|
|
455
|
-
idx = (idx + 1) % total
|
|
456
465
|
sleep(poll_interval)
|
|
457
466
|
end
|
|
458
467
|
pbar&.finish unless pbar&.finished?
|
|
@@ -98,7 +98,11 @@ module Kettle
|
|
|
98
98
|
next
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
line.scan
|
|
101
|
+
line.to_enum(:scan, REFERENCE_USAGE_RE).each do
|
|
102
|
+
match = Regexp.last_match
|
|
103
|
+
next if markdown_bracket_expression?(line, match.begin(0))
|
|
104
|
+
|
|
105
|
+
text, label = match.captures
|
|
102
106
|
resolved_label = label.empty? ? text : label
|
|
103
107
|
usages << [line_number, normalize_label(resolved_label)]
|
|
104
108
|
end
|
|
@@ -223,6 +227,12 @@ module Kettle
|
|
|
223
227
|
label.to_s.downcase.gsub(/\s+/, " ").strip
|
|
224
228
|
end
|
|
225
229
|
|
|
230
|
+
def markdown_bracket_expression?(line, index)
|
|
231
|
+
return false unless index.positive?
|
|
232
|
+
|
|
233
|
+
line[index - 1].match?(/[[:alnum:]_\])]/)
|
|
234
|
+
end
|
|
235
|
+
|
|
226
236
|
def heading_for(line)
|
|
227
237
|
match = line.match(ATX_HEADING_RE)
|
|
228
238
|
match ? [line[/\A\s*/].to_s.length + 1, match[1]] : nil
|
|
@@ -26,6 +26,7 @@ module Kettle
|
|
|
26
26
|
module Dev
|
|
27
27
|
class ReleaseCLI
|
|
28
28
|
RUBYGEMS_INVALID_OTP = /Your OTP code is incorrect\. Please check it and retry\./.freeze
|
|
29
|
+
OTP_RETRY_DELAY_SECONDS = 2
|
|
29
30
|
QUIET_ENV = {
|
|
30
31
|
"KETTLE_JEM_QUIET" => "true",
|
|
31
32
|
"KETTLE_JEM_DEBUG" => "false",
|
|
@@ -125,6 +126,14 @@ module Kettle
|
|
|
125
126
|
|
|
126
127
|
def command_env_for(cmd)
|
|
127
128
|
env_hash = command_env
|
|
129
|
+
if gem_push_command?(cmd)
|
|
130
|
+
# RubyGems publication is an unbundled operation. In particular, an
|
|
131
|
+
# OTP retry can run after the parent release task has selected a
|
|
132
|
+
# different Gemfile; carrying that bundle into `gem push` can make
|
|
133
|
+
# RubyGems load stale local dependency state before it publishes.
|
|
134
|
+
return env_hash.merge(BundlerEnvGuard.unbundled_env)
|
|
135
|
+
end
|
|
136
|
+
|
|
128
137
|
return env_hash unless project_bundle_command?(cmd)
|
|
129
138
|
|
|
130
139
|
env_hash.merge(BundlerEnvGuard.unbundled_env).merge(
|
|
@@ -142,6 +151,12 @@ module Kettle
|
|
|
142
151
|
false
|
|
143
152
|
end
|
|
144
153
|
|
|
154
|
+
def gem_push_command?(cmd)
|
|
155
|
+
effective_command_words(cmd).first(2) == ["gem", "push"]
|
|
156
|
+
rescue ArgumentError
|
|
157
|
+
false
|
|
158
|
+
end
|
|
159
|
+
|
|
145
160
|
def effective_command_words(cmd)
|
|
146
161
|
words = Shellwords.split(cmd.to_s)
|
|
147
162
|
words.shift while words.first&.match?(/\A[A-Za-z_][A-Za-z0-9_]*=/)
|
|
@@ -175,12 +190,13 @@ module Kettle
|
|
|
175
190
|
|
|
176
191
|
public
|
|
177
192
|
|
|
178
|
-
def initialize(start_step: 0, local_ci: false, version: nil, appraisal_task: nil, skip_steps: nil, skip_bundle_audit: nil, ci_workflows: nil, skip_remotes: nil, required_remotes: nil, secrets_provider_name: nil, yes: false, **options)
|
|
193
|
+
def initialize(start_step: 0, local_ci: false, version: nil, appraisal_task: nil, skip_steps: nil, skip_changelog: nil, skip_bundle_audit: nil, ci_workflows: nil, skip_remotes: nil, required_remotes: nil, secrets_provider_name: nil, yes: false, **options)
|
|
179
194
|
@root = Kettle::Dev::CIHelpers.project_root
|
|
180
195
|
@git = Kettle::Dev::GitAdapter.new(@root)
|
|
181
196
|
@start_step = (start_step || 0).to_i
|
|
182
197
|
@start_step = 0 if @start_step < 0
|
|
183
198
|
@skip_steps = normalize_skip_steps(skip_steps)
|
|
199
|
+
@skip_changelog = truthy_value?(skip_changelog) || truthy_value?(ENV["KETTLE_DEV_SKIP_CHANGELOG"])
|
|
184
200
|
@ci_workflows = normalize_ci_workflows(ci_workflows || ENV["K_RELEASE_CI_WORKFLOWS"])
|
|
185
201
|
@skip_remotes = normalize_remote_names(skip_remotes || ENV["K_RELEASE_SKIP_REMOTES"], "skip remotes")
|
|
186
202
|
@required_remotes = normalize_required_remotes(required_remotes)
|
|
@@ -209,8 +225,10 @@ module Kettle
|
|
|
209
225
|
status = "ok"
|
|
210
226
|
error = nil
|
|
211
227
|
with_bundle_audit_skip_env do
|
|
212
|
-
|
|
213
|
-
|
|
228
|
+
with_skip_changelog_env do
|
|
229
|
+
with_machine_stdout_redirect do
|
|
230
|
+
run_with_release_environment
|
|
231
|
+
end
|
|
214
232
|
end
|
|
215
233
|
end
|
|
216
234
|
rescue SystemExit => e
|
|
@@ -637,7 +655,15 @@ module Kettle
|
|
|
637
655
|
def run_pre_release_checks!
|
|
638
656
|
puts "Running pre-release checks via kettle-pre-release..."
|
|
639
657
|
Kettle::Dev::PreReleaseCLI.new(check_num: 1, event_recorder: @event_recorder).run
|
|
640
|
-
|
|
658
|
+
if skip_changelog?
|
|
659
|
+
puts "Skipping kettle-changelog because --skip-changelog was provided."
|
|
660
|
+
else
|
|
661
|
+
run_changelog!
|
|
662
|
+
end
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
def skip_changelog?
|
|
666
|
+
@skip_changelog
|
|
641
667
|
end
|
|
642
668
|
|
|
643
669
|
def prepare_release_lockfiles_for_commit!
|
|
@@ -1368,6 +1394,10 @@ module Kettle
|
|
|
1368
1394
|
status: "started",
|
|
1369
1395
|
reason: "RubyGems rejected the first OTP"
|
|
1370
1396
|
)
|
|
1397
|
+
# A rejection at the TOTP boundary can leave the provider returning the
|
|
1398
|
+
# same code for a moment. Wait briefly before starting the retry so the
|
|
1399
|
+
# next prompt can obtain a refreshed code.
|
|
1400
|
+
sleep(OTP_RETRY_DELAY_SECONDS)
|
|
1371
1401
|
run_cmd!("gem push #{Shellwords.escape(gem_path)}")
|
|
1372
1402
|
emit_secret_event(
|
|
1373
1403
|
source: release_secrets_provider_label,
|
|
@@ -1489,6 +1519,18 @@ module Kettle
|
|
|
1489
1519
|
end
|
|
1490
1520
|
end
|
|
1491
1521
|
|
|
1522
|
+
def with_skip_changelog_env
|
|
1523
|
+
return yield unless skip_changelog?
|
|
1524
|
+
|
|
1525
|
+
previous = ENV["KETTLE_DEV_SKIP_CHANGELOG"]
|
|
1526
|
+
ENV["KETTLE_DEV_SKIP_CHANGELOG"] = "true"
|
|
1527
|
+
yield
|
|
1528
|
+
ensure
|
|
1529
|
+
if skip_changelog?
|
|
1530
|
+
previous.nil? ? ENV.delete("KETTLE_DEV_SKIP_CHANGELOG") : ENV["KETTLE_DEV_SKIP_CHANGELOG"] = previous
|
|
1531
|
+
end
|
|
1532
|
+
end
|
|
1533
|
+
|
|
1492
1534
|
def git_output(args)
|
|
1493
1535
|
# Route all git interactions through the GitAdapter so tests can safely mock them
|
|
1494
1536
|
out, ok = @git.capture(args)
|
data/lib/kettle/dev/version.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Kettle
|
|
|
5
5
|
# Version namespace for this gem.
|
|
6
6
|
module Version
|
|
7
7
|
# Current gem version.
|
|
8
|
-
VERSION = "3.0.
|
|
8
|
+
VERSION = "3.0.7"
|
|
9
9
|
end
|
|
10
10
|
# Current gem version exposed at the traditional constant location.
|
|
11
11
|
VERSION = Version::VERSION # Traditional Constant Location
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kettle-dev
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -60,7 +60,7 @@ dependencies:
|
|
|
60
60
|
version: '0.3'
|
|
61
61
|
- - ">="
|
|
62
62
|
- !ruby/object:Gem::Version
|
|
63
|
-
version: 0.3.
|
|
63
|
+
version: 0.3.13
|
|
64
64
|
type: :runtime
|
|
65
65
|
prerelease: false
|
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -70,7 +70,7 @@ dependencies:
|
|
|
70
70
|
version: '0.3'
|
|
71
71
|
- - ">="
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
|
-
version: 0.3.
|
|
73
|
+
version: 0.3.13
|
|
74
74
|
- !ruby/object:Gem::Dependency
|
|
75
75
|
name: kettle-ndjson
|
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,7 +80,7 @@ dependencies:
|
|
|
80
80
|
version: '0.1'
|
|
81
81
|
- - ">="
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
|
-
version: 0.1.
|
|
83
|
+
version: 0.1.12
|
|
84
84
|
type: :runtime
|
|
85
85
|
prerelease: false
|
|
86
86
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -90,7 +90,7 @@ dependencies:
|
|
|
90
90
|
version: '0.1'
|
|
91
91
|
- - ">="
|
|
92
92
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: 0.1.
|
|
93
|
+
version: 0.1.12
|
|
94
94
|
- !ruby/object:Gem::Dependency
|
|
95
95
|
name: kettle-rb
|
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,7 +100,7 @@ dependencies:
|
|
|
100
100
|
version: '0.1'
|
|
101
101
|
- - ">="
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: 0.1.
|
|
103
|
+
version: 0.1.10
|
|
104
104
|
type: :runtime
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -110,7 +110,7 @@ dependencies:
|
|
|
110
110
|
version: '0.1'
|
|
111
111
|
- - ">="
|
|
112
112
|
- !ruby/object:Gem::Version
|
|
113
|
-
version: 0.1.
|
|
113
|
+
version: 0.1.10
|
|
114
114
|
- !ruby/object:Gem::Dependency
|
|
115
115
|
name: kettle-test
|
|
116
116
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -120,7 +120,7 @@ dependencies:
|
|
|
120
120
|
version: '2.0'
|
|
121
121
|
- - ">="
|
|
122
122
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: 2.0.
|
|
123
|
+
version: 2.0.20
|
|
124
124
|
type: :runtime
|
|
125
125
|
prerelease: false
|
|
126
126
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -130,7 +130,7 @@ dependencies:
|
|
|
130
130
|
version: '2.0'
|
|
131
131
|
- - ">="
|
|
132
132
|
- !ruby/object:Gem::Version
|
|
133
|
-
version: 2.0.
|
|
133
|
+
version: 2.0.20
|
|
134
134
|
- !ruby/object:Gem::Dependency
|
|
135
135
|
name: ruby-progressbar
|
|
136
136
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -400,10 +400,10 @@ licenses:
|
|
|
400
400
|
- AGPL-3.0-only
|
|
401
401
|
metadata:
|
|
402
402
|
homepage_uri: https://kettle-dev.galtzo.com
|
|
403
|
-
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.0.
|
|
404
|
-
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.
|
|
403
|
+
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.0.7
|
|
404
|
+
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.7/CHANGELOG.md
|
|
405
405
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
|
|
406
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.0.
|
|
406
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.0.7
|
|
407
407
|
funding_uri: https://github.com/sponsors/pboling
|
|
408
408
|
wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
|
|
409
409
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
metadata.gz.sig
CHANGED
|
Binary file
|