kettle-dev 3.0.8 → 3.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7124072093bb694c91e9f06b63821090cb992e1a8747f3f83e212a6b927dc25c
4
- data.tar.gz: 861518ad52298f44bc8f76b9d6f4dbb5e9c11c80c4d97bf2c087d6e0ea20d90c
3
+ metadata.gz: 1e670b2a9da64f848886da0112d47c757607895c073ae8e0063583f9893c05a8
4
+ data.tar.gz: 9c395946450a91ee862b55922a1f5bf9bce6208c700098093d7c6050c535488b
5
5
  SHA512:
6
- metadata.gz: 0f823bf26a24fcfcd3b52179dd960f9226c985a9cfc2d6962364dac67d329e6aa21e876f1bcf97a43e2e66158707d11325a56bb1d41d1327fdf4ecac977c4bce
7
- data.tar.gz: 356bc62c3d680808bd5f89a73427dbfaac36157b29dabbe59bc584b37bc8a2aeaa0d62fd2d9198a32f1e0f8b3dc068b722e00214ae9b26a6e053bc60305c295b
6
+ metadata.gz: a9fd3e50a9f6315eec633c43dabd4447f0d2507e6b74ad9b17b3eb03497d4194895c65aa56010098e9a229e01115b4e0d3c1b3beefbaad26c76f4a6862e883c9
7
+ data.tar.gz: e493aa3febc35c6840001eca3b7f7ec127784b83c57e42feac1ab791a0aaac272e9094fb4589c18ba5e7e98cafb9d3fc256f059147c06f23f687768cb8191e52
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,30 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [3.0.10] - 2026-08-23
34
+
35
+ - TAG: [v3.0.10][3.0.10t]
36
+ - COVERAGE: 91.15% -- 5688/6240 lines in 47 files
37
+ - BRANCH COVERAGE: 76.13% -- 2175/2857 branches in 47 files
38
+ - 50.62% documented
39
+
40
+ ### Fixed
41
+
42
+ - Omit the standalone kettle-changelog dependency from normal release-time Bundler resolution, preventing unpublished downstream gem cycles in monorepo release waves.
43
+
44
+ - Use a dependency-specific environment switch when omitting kettle-changelog from release Bundler resolution.
45
+
46
+ ## [3.0.9] - 2026-08-23
47
+
48
+ - TAG: [v3.0.9][3.0.9t]
49
+ - COVERAGE: 91.36% -- 5698/6237 lines in 47 files
50
+ - BRANCH COVERAGE: 76.08% -- 2172/2855 branches in 47 files
51
+ - 50.62% documented
52
+
53
+ ### Fixed
54
+
55
+ - Keep Bundler platform reconciliation in an isolated lockfile during release builds and publication so normalized release lockfiles remain clean.
56
+
33
57
  ## [3.0.8] - 2026-08-23
34
58
 
35
59
  - TAG: [v3.0.8][3.0.8t]
@@ -3505,7 +3529,11 @@ Please file a bug if you notice a violation of semantic versioning.
3505
3529
  - Selecting will run the selected workflow via `act`
3506
3530
  - This may move to its own gem in the future.
3507
3531
 
3508
- [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.8...HEAD
3532
+ [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.10...HEAD
3533
+ [3.0.10]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.9...v3.0.10
3534
+ [3.0.10t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.10
3535
+ [3.0.9]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.8...v3.0.9
3536
+ [3.0.9t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.9
3509
3537
  [3.0.8]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.7...v3.0.8
3510
3538
  [3.0.8t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.8
3511
3539
  [3.0.7]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.6...v3.0.7
data/README.md CHANGED
@@ -426,7 +426,8 @@ What it does:
426
426
  2. Detect version; RubyGems sanity check; confirm CHANGELOG/version; sync copyright years; update badges/headers
427
427
  3. Run bin/setup
428
428
  4. Run bin/rake (default task)
429
- 5. Run bin/rake appraisal:update if Appraisals present, then bin/rake yard
429
+ 5. Run bin/rake appraisal:generate if Appraisals are present, then bin/rake yard
430
+ (or appraisal:update with --appraisal-update)
430
431
  6. Ensure git user configured; commit release prep
431
432
  7. Optional local CI with `act` (controlled by `K_RELEASE_LOCAL_CI`)
432
433
  8. Ensure trunk in sync across remotes; rebase feature as needed
@@ -442,7 +443,9 @@ What it does:
442
443
  18. Create GitHub Release (requires `GITHUB_TOKEN`)
443
444
  19. Push tags to remotes (final)
444
445
  - Examples:
445
- - After intermittent CI failure, restart from monitoring: `bundle exec kettle-release start_step=10`
446
+ - After a transient CI or provider failure with no code, version, changelog, or lockfile changes, restart from monitoring: `bundle exec kettle-release start_step=10`
447
+ - If the failure required a code or release-metadata change, rerun `bundle exec kettle-release` from step 0 so the release checks, prep metadata, commit, and CI all describe the new release commit.
448
+ - For an intentional same-commit CI bypass, use `bundle exec kettle-release skip_steps=10` or `--skip-steps 10`; this skips remote CI monitoring only and does not claim that CI passed.
446
449
  - After fixing a failed pre-release gate, rerun from step 0: `bundle exec kettle-release`
447
450
  - After intentionally handling a failed pre-release gate, skip it and start numbered release steps: `bundle exec kettle-release start_step=1`
448
451
  - Auto-approve release confirmation prompts: `bundle exec kettle-release --yes`
@@ -460,11 +463,27 @@ What it does:
460
463
  variables, known local-template toggles, and writes checksums while
461
464
  updating path-sourced and checksum-gap gems back to released registry
462
465
  versions.
466
+ - Release lockfile resets set `KETTLE_DEV_SKIP_CHANGELOG_DEPENDENCY=true`.
467
+ This does not skip changelog generation; it keeps the development-only
468
+ `kettle-changelog` gem out of the release bundle so unpublished family
469
+ gems cannot enter Bundler's resolution graph.
463
470
  - During `kettle-release`, release lockfiles are reset before the release
464
471
  prep commit. Before pushing, `kettle-release` validates those committed
465
472
  lockfiles again; if local paths or checksum gaps reappear, it prints the
466
473
  diagnostics, attempts one reset, amends the release prep commit if the
467
474
  reset changed tracked lockfiles, and aborts if diagnostics remain.
475
+ - Release build and publish tasks use a disposable copy of `Gemfile.lock`.
476
+ This is intentional: `bundle lock --add-platform` records the normalized
477
+ CI platforms, but it is not a permanent preservation directive. A later
478
+ non-frozen `bundle exec rake build` or `bundle exec rake release` can
479
+ reconcile the lockfile for the host platform and rewrite the tracked
480
+ file. RubyGems' `bundler/gem_tasks` then sees that rewrite and aborts at
481
+ its clean-tree guard, even though the release inputs were valid. The
482
+ temporary `BUNDLE_LOCKFILE` lets Bundler perform that runtime
483
+ reconciliation without changing the committed release lockfile; it is
484
+ removed when the release process exits. `BUNDLE_FROZEN=true` is not a
485
+ substitute because it converts the same reconciliation into a failure
486
+ when Bundler needs to write its resolved lockfile.
468
487
  - Tips:
469
488
  - The commit message helper `exe/kettle-commit-msg` prefers project-local `.git-hooks` (then falls back to `~/.git-hooks`).
470
489
  - The goalie file `commit-subjects-goalie.txt` controls when a footer is appended; customize `footer-template.erb.txt` as you like.
@@ -993,7 +1012,7 @@ Thanks for RTFM. ☺️
993
1012
  [📌gitmoji]: https://gitmoji.dev
994
1013
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
995
1014
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
996
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.216-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1015
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.240-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
997
1016
  [🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
998
1017
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
999
1018
  [📄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
@@ -64,7 +64,8 @@ if ARGV.include?("-h") || ARGV.include?("--help")
64
64
  2. Detect version; RubyGems sanity check; confirm CHANGELOG/version; sync copyright years; update badges/headers
65
65
  3. Run bin/setup
66
66
  4. Run bin/rake (default task)
67
- 5. Run bin/rake appraisal:generate if Appraisals present
67
+ 5. Run bin/rake appraisal:generate if Appraisals are present
68
+ (or appraisal:update with --appraisal-update)
68
69
  6. Ensure git user configured; commit release prep
69
70
  7. Optional local CI with `act` (controlled by K_RELEASE_LOCAL_CI)
70
71
  8. Ensure trunk in sync across remotes; rebase feature as needed
@@ -81,8 +82,8 @@ if ARGV.include?("-h") || ARGV.include?("--help")
81
82
  19. Push tags to remotes (final)
82
83
 
83
84
  Options:
84
- start_step=<number> # Begin at the numbered step above (e.g., 10 to resume at CI monitoring)
85
- skip_steps=<numbers> # Comma-separated numbered steps to skip while running the rest
85
+ start_step=<number> # Begin at the numbered step above; use 10 only for a transient CI failure on the same commit
86
+ skip_steps=<numbers> # Comma-separated numbered steps to skip while running the rest; 10 skips remote CI monitoring
86
87
  --skip-steps NUMBERS # Alias for skip_steps=NUMBERS (e.g., --skip-steps 10 or --skip-steps 10,18)
87
88
  --version VERSION # Use this version instead of detecting VERSION from lib/**/version.rb
88
89
  --yes # Auto-approve release confirmation prompts
@@ -99,12 +100,19 @@ if ARGV.include?("-h") || ARGV.include?("--help")
99
100
  --local-ci # Sensitive release mode: run act locally, publish before any git push,
100
101
  # create the git tag locally, then push commits and tags after publish
101
102
 
103
+ Recovery guidance:
104
+ start_step=10 # Retry only CI monitoring after a transient CI/provider failure; do not use after code or metadata changes
105
+ start_step=11 # Continue after CI monitoring only when that same release commit was intentionally accepted
106
+ skip_steps=10 # Skip remote CI monitoring for the same prepared release commit; this does not rerun or replace CI
107
+ kettle-release # After code, version, changelog, or lockfile changes, rerun the complete flow from step 0
108
+
102
109
  Environment:
103
110
  SKIP_GEM_SIGNING=true # Build/release unsigned; avoids PEM password prompts
104
111
  GEM_CERT_USER=<user> # Select certs/<user>.pem for signing
105
112
  K_RELEASE_LOCAL_CI=ask|1|0 # Use 'act' locally before push; 'ask' prompts, '1' forces, default off
106
113
  K_RELEASE_LOCAL_CI_WORKFLOW # Name of workflow (without .yml) for local CI; defaults to locked_deps or first
107
114
  K_RELEASE_CI_WORKFLOWS # Comma-separated workflow files or stems to monitor at CI step 10
115
+ K_RELEASE_CI_CONTINUE=true # Continue after a failed CI result; monitoring still runs and failures remain visible
108
116
  K_RELEASE_SKIP_REMOTES # Comma-separated git remote names to exclude from release fetch/push parity
109
117
  K_RELEASE_REQUIRED_REMOTES # Comma-separated remotes that must fetch for release parity; defaults to origin
110
118
  KETTLE_RELEASE_SECRETS_PROVIDER=1password
@@ -132,8 +140,8 @@ if ARGV.include?("-h") || ARGV.include?("--help")
132
140
  kettle-release # full flow from the top (start_step=0)
133
141
  kettle-release --local-ci # run local act CI, publish gem, then push commits/tags
134
142
  kettle-release start_step=1 # skip pre-release checks and start numbered release steps
135
- kettle-release start_step=10 # resume by monitoring CI for the current branch
136
- kettle-release skip_steps=10 # run the release but skip remote CI monitoring
143
+ kettle-release start_step=10 # retry CI monitoring after a transient failure on the unchanged release commit
144
+ kettle-release skip_steps=10 # intentionally skip remote CI monitoring for the unchanged release commit
137
145
  SKIP_GEM_SIGNING=true kettle-release start_step=14 # build+release without signing
138
146
  USAGE
139
147
  exit 0
@@ -34,18 +34,31 @@ module Kettle
34
34
  @release_platforms = {}
35
35
  end
36
36
 
37
- def reset(target)
37
+ def reset(target, skip_changelog_dependency: false)
38
38
  BundlerEnvGuard.warn_unexpected_env!
39
39
  paths = lockfile_paths_for(target)
40
40
  force_full_update = release_lockfiles_target?(target)
41
+ skip_changelog_dependency ||= force_full_update
41
42
  platforms = release_platforms_for(paths) if force_full_update
42
43
  uninstall_unreleased_local_gems(paths) if force_full_update
43
44
  paths.each do |path|
44
- reset_lockfile!(path, full_update: force_full_update, platforms: platforms&.fetch(path)) if force_full_update || normalization_needed?(path)
45
+ if force_full_update || normalization_needed?(path)
46
+ reset_lockfile!(
47
+ path,
48
+ full_update: force_full_update,
49
+ platforms: platforms&.fetch(path),
50
+ skip_changelog_dependency: skip_changelog_dependency
51
+ )
52
+ end
45
53
  end
46
54
  if force_full_update && uninstall_unreleased_local_gems(paths)
47
55
  paths.each do |path|
48
- reset_lockfile!(path, full_update: true, platforms: platforms.fetch(path))
56
+ reset_lockfile!(
57
+ path,
58
+ full_update: true,
59
+ platforms: platforms.fetch(path),
60
+ skip_changelog_dependency: skip_changelog_dependency
61
+ )
49
62
  end
50
63
  end
51
64
  diagnostics = paths.flat_map { |path| diagnostics(path) }
@@ -54,7 +67,7 @@ module Kettle
54
67
  paths
55
68
  end
56
69
 
57
- def reset_lockfile!(path, full_update: false, platforms: nil)
70
+ def reset_lockfile!(path, full_update: false, platforms: nil, skip_changelog_dependency: false)
58
71
  gemfile = gemfile_for_lockfile(path)
59
72
  unless gemfile && File.file?(gemfile)
60
73
  warn("Cannot reset #{display_path(path)} because its Gemfile was not found.")
@@ -67,6 +80,7 @@ module Kettle
67
80
  gemfile: gemfile,
68
81
  full_update: full_update,
69
82
  platforms: platforms,
83
+ skip_changelog_dependency: skip_changelog_dependency,
70
84
  isolated_gem_home: gem_home
71
85
  )
72
86
  if full_update || has_local_path_remote?(path)
@@ -77,7 +91,7 @@ module Kettle
77
91
  end
78
92
  end
79
93
 
80
- def reset_command(path:, gemfile:, full_update: false, platforms: nil, isolated_gem_home: nil)
94
+ def reset_command(path:, gemfile:, full_update: false, platforms: nil, skip_changelog_dependency: false, isolated_gem_home: nil)
81
95
  update_gems = (full_update || has_local_path_remote?(path)) ? [] : reset_update_gems(path)
82
96
  platforms ||= reset_platforms(path)
83
97
  removed_platforms = full_update ? [] : lockfile_platforms(path) - platforms
@@ -85,6 +99,7 @@ module Kettle
85
99
  "BUNDLE_GEMFILE" => gemfile,
86
100
  "BUNDLE_LOCKFILE" => path
87
101
  )
102
+ env["KETTLE_DEV_SKIP_CHANGELOG_DEPENDENCY"] = "true" if skip_changelog_dependency
88
103
  if isolated_gem_home
89
104
  env["GEM_HOME"] = isolated_gem_home
90
105
  env["GEM_PATH"] = isolated_gem_home
@@ -217,6 +217,7 @@ module Kettle
217
217
  @started_at = nil
218
218
  @finished_report = nil
219
219
  @changelog_generated_coverage = false
220
+ @release_task_lockfile_path = nil
220
221
  end
221
222
 
222
223
  def run
@@ -242,6 +243,7 @@ module Kettle
242
243
  record_diagnostic("release_error", "#{e.class}: #{e.message}", severity: "error", blocking: true)
243
244
  raise
244
245
  ensure
246
+ cleanup_release_task_lockfile!
245
247
  finish_release_report(status: status, error: error)
246
248
  end
247
249
 
@@ -687,7 +689,10 @@ module Kettle
687
689
  emit_release_lockfile_event(action: "reset", status: "started", stage: stage, attempt: attempt, attempts: attempts)
688
690
  puts "Resetting release lockfiles with local path dependencies disabled #{stage} (attempt #{attempt}/#{attempts})..."
689
691
  begin
690
- lockfile_reset.reset(Kettle::Dev::LockfileReset::RELEASE_LOCKFILES_TARGET)
692
+ lockfile_reset.reset(
693
+ Kettle::Dev::LockfileReset::RELEASE_LOCKFILES_TARGET,
694
+ skip_changelog_dependency: true
695
+ )
691
696
  emit_release_lockfile_event(action: "reset", status: "ok", stage: stage, attempt: attempt, attempts: attempts)
692
697
  break
693
698
  rescue Kettle::Dev::Error => error
@@ -773,7 +778,7 @@ module Kettle
773
778
  end
774
779
 
775
780
  def normalize_release_lockfile!(path)
776
- lockfile_reset.reset_lockfile!(path)
781
+ lockfile_reset.reset_lockfile!(path, skip_changelog_dependency: true)
777
782
  end
778
783
 
779
784
  def release_gemfile_for_lockfile(path)
@@ -781,7 +786,7 @@ module Kettle
781
786
  end
782
787
 
783
788
  def release_lockfile_normalization_env
784
- lockfile_reset.normalization_env
789
+ lockfile_reset.normalization_env.merge("KETTLE_DEV_SKIP_CHANGELOG_DEPENDENCY" => "true")
785
790
  end
786
791
 
787
792
  def release_lockfile_diagnostics(path)
@@ -972,10 +977,47 @@ module Kettle
972
977
  release_lockfile_normalization_env.each do |key, value|
973
978
  command << " #{key}=#{Shellwords.escape(value)}"
974
979
  end
980
+ if release_task_command?(project_command)
981
+ if (lockfile = release_task_lockfile_path)
982
+ command << " BUNDLE_LOCKFILE=#{Shellwords.escape(lockfile)}"
983
+ end
984
+ end
975
985
  command << " #{project_command}"
976
986
  command
977
987
  end
978
988
 
989
+ def release_task_command?(command)
990
+ ["bundle exec rake build", "bundle exec rake release"].include?(command.to_s.strip)
991
+ end
992
+
993
+ # Bundler may reconcile the current machine's platform while loading a
994
+ # project bundle. That is useful during development, but it can dirty the
995
+ # release-preparation commit between the final lockfile reset and
996
+ # bundler/gem_tasks' release:guard_clean check. Keep that reconciliation
997
+ # in a disposable lockfile so the committed, normalized lockfile remains
998
+ # unchanged throughout build and publication.
999
+ def release_task_lockfile_path
1000
+ return @release_task_lockfile_path if @release_task_lockfile_path
1001
+
1002
+ source = File.join(@root, "Gemfile.lock")
1003
+ return unless File.file?(source)
1004
+
1005
+ directory = File.join(@root, "tmp", "kettle-release", "lockfiles")
1006
+ FileUtils.mkdir_p(directory)
1007
+ @release_task_lockfile_path = File.join(directory, "Gemfile-#{$$}.lock")
1008
+ FileUtils.cp(source, @release_task_lockfile_path)
1009
+ @release_task_lockfile_path
1010
+ rescue SystemCallError => error
1011
+ abort("Unable to isolate the release task lockfile: #{error.message}")
1012
+ end
1013
+
1014
+ def cleanup_release_task_lockfile!
1015
+ return unless @release_task_lockfile_path
1016
+
1017
+ FileUtils.rm_f(@release_task_lockfile_path)
1018
+ @release_task_lockfile_path = nil
1019
+ end
1020
+
979
1021
  def confirm_yes!(message, prompt, abort_message)
980
1022
  puts(message)
981
1023
  if @yes
@@ -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"
8
+ VERSION = "3.0.10"
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.8
4
+ version: 3.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -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.8
404
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.8/CHANGELOG.md
403
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.0.10
404
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.10/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.8
406
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.0.10
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