kettle-dev 3.0.19 → 3.0.20

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: d876b80536e92761ec39671fee1b416885fceba475be7ade298e9dd8985df29e
4
- data.tar.gz: d9075edc61ba1b98e98b7a4024d53d8c57e4beb0a0239059eeb0ddc6ec597c35
3
+ metadata.gz: 20e87802965f21d08fce4a1bb8eaab16a950611e67268f55284610c9e7601d6a
4
+ data.tar.gz: 26d1ac30a1bba63404ec8463290e20effd4039393c179842e61cf98ed5e89760
5
5
  SHA512:
6
- metadata.gz: aa04b5dc3afa36b4dfdb5c7671ec2fba75fbb0bf73a1d88ee00c0e66d0c81bea453e57670f659a830a4042c98199d9f0fb280602bca5e0840395a998761e3fcd
7
- data.tar.gz: 57ba7e91a1130bcb673b40b1c278b9206157163121a7bac829cf784641d2095153577bae43595d0fcba02f2f7ddb4b008c741f7599819f98e7678ebf36e45ce5
6
+ metadata.gz: d6d0157c9bd6b22580c9c4304ed9ec0d2a87f55d8e8afe33cf4e81e14a3905f979e30397143047979bfed0c795b321acfaa9739988c9fb6f8546c1e45ceffa17
7
+ data.tar.gz: cf6a29d466ad157170224b8aca7cb9569e2de56711825487d18f8e68ef3ca5e5d546b215d2b00d34d9e9dbe49d49e2a326c37883b9eab66cc0835f97420732c0
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,17 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [3.0.20] - 2026-08-30
34
+
35
+ - TAG: [v3.0.20][3.0.20t]
36
+ - COVERAGE: 91.44% -- 5875/6425 lines in 47 files
37
+ - BRANCH COVERAGE: 76.07% -- 2248/2955 branches in 47 files
38
+ - 50.47% documented
39
+
40
+ ### Fixed
41
+
42
+ - Preserve configured monorepo member-path lockfiles during release while rejecting unapproved local paths.
43
+
33
44
  ## [3.0.19] - 2026-08-30
34
45
 
35
46
  - TAG: [v3.0.19][3.0.19t]
@@ -3666,7 +3677,9 @@ Please file a bug if you notice a violation of semantic versioning.
3666
3677
  - Selecting will run the selected workflow via `act`
3667
3678
  - This may move to its own gem in the future.
3668
3679
 
3669
- [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.19...HEAD
3680
+ [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.20...HEAD
3681
+ [3.0.20]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.19...v3.0.20
3682
+ [3.0.20t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.20
3670
3683
  [3.0.19]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.18...v3.0.19
3671
3684
  [3.0.19t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.19
3672
3685
  [3.0.18]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.17...v3.0.18
data/README.md CHANGED
@@ -508,7 +508,7 @@ What it does:
508
508
  | Role | Lockfile | Used by |
509
509
  | --- | --- | --- |
510
510
  | Family runner | The family/orchestrator bundle | May resolve local sibling gems to run `kettle-family`; it never becomes the target project's lockfile. |
511
- | Canonical release state | Tracked `Gemfile.lock` and, when present, `Appraisal.root.gemfile.lock` | Step 1 Bundler update, steps 3-6 setup/checks/appraisals/docs/prep commit, and step 16 checksums. These commands disable local `*_DEV`/`*_LOCAL` switches. |
511
+ | Canonical release state | Tracked `Gemfile.lock` and, when present, `Appraisal.root.gemfile.lock` | Step 1 Bundler update, steps 3-6 setup/checks/appraisals/docs/prep commit, and step 16 checksums. These commands disable local `*_DEV`/`*_LOCAL` switches, except a narrow member-root policy supplied by `kettle-family` for an explicit monorepo. |
512
512
  | Release task state | `tmp/kettle-release/lockfiles/Gemfile-<pid>.lock` | Steps 14-15 build and publish only. It begins as a copy of canonical `Gemfile.lock` and is deleted at process exit. |
513
513
  | Tool state | A tool-owned Gemfile such as `kettle-changelog/gemfiles/release.gemfile` | The tool's own dependencies. The command still disables local dependency switches before it can trigger target-project work. |
514
514
  | Git-hook state | Canonical release environment | Every release-created commit and amend. Hooks remain enabled, but cannot inherit the family runner's local sibling graph. |
@@ -518,6 +518,14 @@ What it does:
518
518
  a release phase. `ReleaseCLI#release_child_command` owns canonical/tool
519
519
  command construction; `ReleaseCLI#release_project_command` selects the
520
520
  disposable task lock only for build and publish.
521
+
522
+ The monorepo exception is intentionally narrow. `kettle-family` derives
523
+ it only from `family.mode: monorepo` and its configured members root, then
524
+ passes the allowed root and activating environment name to
525
+ `kettle-release`. A sibling Kettle Dev checkout is not covered: normal
526
+ releases must use the released `kettle-family`, `kettle-changelog`, and
527
+ other Kettle dependencies. Local Kettle Dev integration is an explicit
528
+ development opt-in, never a canonical release-lock default.
521
529
  - Tips:
522
530
  - The commit message helper `exe/kettle-commit-msg` prefers project-local `.git-hooks` (then falls back to `~/.git-hooks`).
523
531
  - The goalie file `commit-subjects-goalie.txt` controls when a footer is appended; customize `footer-template.erb.txt` as you like.
@@ -1048,7 +1056,7 @@ Thanks for RTFM. ☺️
1048
1056
  [📌gitmoji]: https://gitmoji.dev
1049
1057
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1050
1058
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1051
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.399-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1059
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.425-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1052
1060
  [🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
1053
1061
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1054
1062
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -21,6 +21,8 @@ module Kettle
21
21
  "GALTZO_FLOSS_DEV" => "false",
22
22
  "UR_BRAIN_DEV" => "false"
23
23
  }.freeze
24
+ ALLOWED_LOCAL_PATH_ROOTS_ENV = "KETTLE_RELEASE_ALLOWED_LOCAL_PATH_ROOTS"
25
+ ALLOWED_LOCAL_PATH_ENVS_ENV = "KETTLE_RELEASE_ALLOWED_LOCAL_PATH_ENVS"
24
26
  RELEASE_LOCKFILES_TARGET = "release-lockfiles"
25
27
  SUPPORTED_TARGETS = ["Gemfile.lock", "Appraisal.root.gemfile.lock", RELEASE_LOCKFILES_TARGET].freeze
26
28
  UNBUNDLED_ENV_KEYS = (BundlerEnvGuard::RESET_ENV_KEYS + %w[
@@ -110,12 +112,18 @@ module Kettle
110
112
  @root = root
111
113
  @command_runner = command_runner
112
114
  @release_platforms = {}
115
+ @allowed_local_path_roots = configured_allowed_local_path_roots
116
+ @allowed_local_path_env_names = configured_allowed_local_path_env_names
113
117
  end
114
118
 
115
119
  def reset(target, skip_changelog_dependency: false)
116
120
  BundlerEnvGuard.warn_unexpected_env!
117
121
  paths = lockfile_paths_for(target)
118
- force_full_update = release_lockfiles_target?(target)
122
+ # A monorepo lockfile may deliberately use paths rooted in the
123
+ # repository's members directory. Keep that valid development graph;
124
+ # only rebuild when an unapproved path or other diagnostic remains.
125
+ force_full_update = release_lockfiles_target?(target) &&
126
+ (allowed_local_path_roots.empty? || paths.any? { |path| normalization_needed?(path) })
119
127
  platforms = release_platforms_for(paths) if force_full_update
120
128
  uninstall_unreleased_local_gems(paths) if force_full_update
121
129
  paths.each do |path|
@@ -251,7 +259,7 @@ module Kettle
251
259
 
252
260
  def diagnostics(path)
253
261
  diagnostics = []
254
- local_path_remote_lines(path).each do |line_number|
262
+ disallowed_local_path_remote_lines(path).each do |line_number|
255
263
  diagnostics << "#{display_path(path)} has local path remote at line #{line_number}"
256
264
  end
257
265
  empty_registry_checksums(path).each do |name, version, line_number|
@@ -308,13 +316,16 @@ module Kettle
308
316
  end
309
317
 
310
318
  def normalization_env
311
- DEFAULT_DISABLED_ENV.merge(dynamic_local_path_env)
319
+ DEFAULT_DISABLED_ENV
320
+ .reject { |name, _| allowed_local_path_env_names.include?(name) }
321
+ .merge(dynamic_local_path_env)
312
322
  end
313
323
 
314
324
  def dynamic_local_path_env
315
325
  ENV.each_with_object({}) do |(key, value), env|
316
326
  next unless key.end_with?("_DEV", "_LOCAL")
317
327
  next unless local_path_env_value?(value)
328
+ next if allowed_local_path_env_names.include?(key)
318
329
 
319
330
  env[key] = "false"
320
331
  end
@@ -329,13 +340,49 @@ module Kettle
329
340
  end
330
341
 
331
342
  def has_local_path_remote?(path)
332
- !local_path_remote_lines(path).empty?
343
+ !disallowed_local_path_remote_lines(path).empty?
333
344
  end
334
345
 
335
346
  def local_path_remote_lines(path)
336
347
  self.class.local_path_remote_lines_from_source(File.read(path))
337
348
  end
338
349
 
350
+ attr_reader :allowed_local_path_roots, :allowed_local_path_env_names
351
+
352
+ def disallowed_local_path_remote_lines(path)
353
+ local_path_remote_lines(path).reject do |line_number|
354
+ allowed_local_path?(local_path_remote_at(path, line_number))
355
+ end
356
+ end
357
+
358
+ def configured_allowed_local_path_roots
359
+ ENV.fetch(ALLOWED_LOCAL_PATH_ROOTS_ENV, "").split(File::PATH_SEPARATOR).filter_map do |value|
360
+ next if value.strip.empty?
361
+
362
+ canonical_path(value)
363
+ end.uniq
364
+ end
365
+
366
+ def configured_allowed_local_path_env_names
367
+ ENV.fetch(ALLOWED_LOCAL_PATH_ENVS_ENV, "").split(",").map(&:strip).reject(&:empty?).uniq
368
+ end
369
+
370
+ def local_path_remote_at(path, line_number)
371
+ File.readlines(path)[line_number - 1].to_s.split("remote:", 2).last.to_s.strip
372
+ end
373
+
374
+ def allowed_local_path?(path)
375
+ remote = canonical_path(path)
376
+ allowed_local_path_roots.any? { |root| remote == root || remote.start_with?("#{root}/") }
377
+ end
378
+
379
+ def canonical_path(path)
380
+ expanded = File.expand_path(path, root)
381
+ File.realpath(expanded)
382
+ rescue Errno::ENOENT
383
+ expanded
384
+ end
385
+
339
386
  def empty_registry_checksums(path)
340
387
  non_registry_gems = non_registry_source_gems(path) | path_dependency_gems(path)
341
388
  in_checksums = false
@@ -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.19"
8
+ VERSION = "3.0.20"
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.19
4
+ version: 3.0.20
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.19
404
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.19/CHANGELOG.md
403
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.0.20
404
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.20/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.19
406
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.0.20
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