kettle-dev 2.4.0 → 2.4.1
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 +17 -1
- data/README.md +1 -1
- data/lib/kettle/dev/release_cli.rb +191 -2
- data/lib/kettle/dev/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -4
- 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: 77a7621fa0d906b716e933205ff585081b8746345530f540a8c83f6e67d3f347
|
|
4
|
+
data.tar.gz: ae54a1e1f33347caa8c6d07eae632db0b88c95583a838fece942bd9bb1d84bfb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 03b528fd8d85c047d18606f023a0f9f217ca88556ed26ddbc62504a282bceda6a42ea315c0cd0fdd0e2e4307fefeda357d34fcf4fab98d83dc5214c9d202bbb2
|
|
7
|
+
data.tar.gz: d630c32d5f8cfbb28b74cdc552a9d331aa73d25de2d80298736f759f2bfe3181649c845a1d812c5ead41f9792a3169091f07ae33a2afb1610028b191effb08e7
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,20 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [2.4.1] - 2026-07-24
|
|
34
|
+
|
|
35
|
+
- TAG: [v2.4.1][2.4.1t]
|
|
36
|
+
- COVERAGE: 92.29% -- 3928/4256 lines in 38 files
|
|
37
|
+
- BRANCH COVERAGE: 76.09% -- 1550/2037 branches in 38 files
|
|
38
|
+
- 58.66% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- `kettle-release` now normalizes and revalidates release lockfiles after
|
|
43
|
+
mutating setup/appraisal/doc steps, before committing or pushing, so local
|
|
44
|
+
path remotes and locally installed registry gems with empty lockfile
|
|
45
|
+
checksums cannot leak into CI.
|
|
46
|
+
|
|
33
47
|
## [2.4.0] - 2026-07-23
|
|
34
48
|
|
|
35
49
|
- TAG: [v2.4.0][2.4.0t]
|
|
@@ -2646,7 +2660,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
2646
2660
|
- Selecting will run the selected workflow via `act`
|
|
2647
2661
|
- This may move to its own gem in the future.
|
|
2648
2662
|
|
|
2649
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.4.
|
|
2663
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.4.1...HEAD
|
|
2664
|
+
[2.4.1]: https://github.com/kettle-dev/kettle-dev/compare/v2.4.0...v2.4.1
|
|
2665
|
+
[2.4.1t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.4.1
|
|
2650
2666
|
[2.4.0]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.11...v2.4.0
|
|
2651
2667
|
[2.4.0t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.4.0
|
|
2652
2668
|
[2.3.11]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.10...v2.3.11
|
data/README.md
CHANGED
|
@@ -891,7 +891,7 @@ Thanks for RTFM. ☺️
|
|
|
891
891
|
[📌gitmoji]: https://gitmoji.dev
|
|
892
892
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
893
893
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
894
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-4.
|
|
894
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-4.256-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
895
895
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
896
896
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
897
897
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -10,6 +10,7 @@ require "net/http"
|
|
|
10
10
|
require "json"
|
|
11
11
|
require "uri"
|
|
12
12
|
require "yaml"
|
|
13
|
+
require "set"
|
|
13
14
|
|
|
14
15
|
# External gems
|
|
15
16
|
require "kettle/rb/compat_matrix"
|
|
@@ -256,6 +257,7 @@ module Kettle
|
|
|
256
257
|
|
|
257
258
|
# 6. git user + commit release prep
|
|
258
259
|
if run_step?(6)
|
|
260
|
+
prepare_release_lockfiles_for_commit!
|
|
259
261
|
ensure_git_user!
|
|
260
262
|
version ||= detect_version
|
|
261
263
|
committed = commit_release_prep!(version)
|
|
@@ -279,10 +281,16 @@ module Kettle
|
|
|
279
281
|
end
|
|
280
282
|
|
|
281
283
|
# 9. push branches
|
|
282
|
-
|
|
284
|
+
if run_step?(9) && !local_ci?
|
|
285
|
+
validate_release_lockfiles!(stage: "before push")
|
|
286
|
+
push!
|
|
287
|
+
end
|
|
283
288
|
|
|
284
289
|
# 10. monitor CI after push
|
|
285
|
-
|
|
290
|
+
if run_step?(10) && !local_ci?
|
|
291
|
+
validate_release_lockfiles!(stage: "before CI monitoring")
|
|
292
|
+
monitor_workflows_after_push!
|
|
293
|
+
end
|
|
286
294
|
|
|
287
295
|
# 11. merge feature into trunk and push
|
|
288
296
|
if run_step?(11) && !local_ci?
|
|
@@ -505,6 +513,187 @@ module Kettle
|
|
|
505
513
|
run_changelog!
|
|
506
514
|
end
|
|
507
515
|
|
|
516
|
+
def prepare_release_lockfiles_for_commit!
|
|
517
|
+
dirty_lockfiles = release_lockfile_paths.select { |path| release_lockfile_normalization_needed?(path) }
|
|
518
|
+
unless dirty_lockfiles.empty?
|
|
519
|
+
puts "Normalizing release lockfiles with local path dependencies disabled..."
|
|
520
|
+
dirty_lockfiles.each { |path| normalize_release_lockfile!(path) }
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
validate_release_lockfiles!(stage: "before release prep commit")
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def validate_release_lockfiles!(stage:)
|
|
527
|
+
diagnostics = release_lockfile_paths.flat_map { |path| release_lockfile_diagnostics(path) }
|
|
528
|
+
return if diagnostics.empty?
|
|
529
|
+
|
|
530
|
+
abort(<<~MSG)
|
|
531
|
+
Release lockfile validation failed #{stage}:
|
|
532
|
+
#{diagnostics.map { |diagnostic| " - #{diagnostic}" }.join("\n")}
|
|
533
|
+
Re-run bundle lock/update with local path development env disabled before releasing.
|
|
534
|
+
MSG
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def release_lockfile_paths
|
|
538
|
+
candidates = [
|
|
539
|
+
File.join(@root, "Gemfile.lock"),
|
|
540
|
+
File.join(@root, "Appraisal.root.gemfile.lock")
|
|
541
|
+
]
|
|
542
|
+
candidates.select { |path| File.file?(path) }.sort
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def release_lockfile_normalization_needed?(path)
|
|
546
|
+
release_lockfile_has_local_path_remote?(path) || !release_lockfile_empty_registry_checksums(path).empty?
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def normalize_release_lockfile!(path)
|
|
550
|
+
gemfile = release_gemfile_for_lockfile(path)
|
|
551
|
+
unless gemfile && File.file?(gemfile)
|
|
552
|
+
warn("Cannot normalize #{Kettle::Dev.display_path(path)} because its Gemfile was not found.")
|
|
553
|
+
return
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
update_gems = release_lockfile_empty_registry_checksums(path).map(&:first).uniq.sort
|
|
557
|
+
env = release_lockfile_normalization_env.merge("BUNDLE_GEMFILE" => gemfile)
|
|
558
|
+
command = +"env"
|
|
559
|
+
env.each do |key, value|
|
|
560
|
+
command << " #{key}=#{Shellwords.escape(value)}"
|
|
561
|
+
end
|
|
562
|
+
command << " bundle lock"
|
|
563
|
+
command << " --update #{update_gems.map { |gem_name| Shellwords.escape(gem_name) }.join(" ")}" unless update_gems.empty?
|
|
564
|
+
run_cmd!(command)
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
def release_gemfile_for_lockfile(path)
|
|
568
|
+
basename = File.basename(path)
|
|
569
|
+
return File.join(@root, "Gemfile") if basename == "Gemfile.lock"
|
|
570
|
+
|
|
571
|
+
path.delete_suffix(".lock")
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def release_lockfile_normalization_env
|
|
575
|
+
{
|
|
576
|
+
"KETTLE_DEV_DEV" => "false",
|
|
577
|
+
"K_JEM_TEMPLATING" => "false",
|
|
578
|
+
"STRUCTUREDMERGE_DEV" => "false",
|
|
579
|
+
"TREE_SITTER_LANGUAGE_PACK_DEV" => "false",
|
|
580
|
+
"RUBOCOP_LTS_LOCAL" => "false",
|
|
581
|
+
"GALTZO_FLOSS_DEV" => "false",
|
|
582
|
+
"UR_BRAIN_DEV" => "false"
|
|
583
|
+
}
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
def release_lockfile_diagnostics(path)
|
|
587
|
+
diagnostics = []
|
|
588
|
+
release_lockfile_local_path_remote_lines(path).each do |line_number|
|
|
589
|
+
diagnostics << "#{release_lockfile_label(path)} has local path remote at line #{line_number}"
|
|
590
|
+
end
|
|
591
|
+
release_lockfile_empty_registry_checksums(path).each do |name, version, line_number|
|
|
592
|
+
diagnostics << "#{release_lockfile_label(path)} CHECKSUMS has no sha256 for #{name} #{version} at line #{line_number}"
|
|
593
|
+
end
|
|
594
|
+
diagnostics
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
def release_lockfile_has_local_path_remote?(path)
|
|
598
|
+
!release_lockfile_local_path_remote_lines(path).empty?
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
def release_lockfile_local_path_remote_lines(path)
|
|
602
|
+
File.readlines(path).filter_map.with_index(1) do |line, index|
|
|
603
|
+
next unless line.start_with?(" remote: /", " remote: ./", " remote: ../")
|
|
604
|
+
|
|
605
|
+
index
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
def release_lockfile_empty_registry_checksums(path)
|
|
610
|
+
path_gems = release_lockfile_path_source_gems(path) | release_lockfile_path_dependency_gems(path)
|
|
611
|
+
in_checksums = false
|
|
612
|
+
entries = File.readlines(path).filter_map.with_index(1) do |line, index|
|
|
613
|
+
stripped = line.strip
|
|
614
|
+
if stripped == "CHECKSUMS"
|
|
615
|
+
in_checksums = true
|
|
616
|
+
next
|
|
617
|
+
end
|
|
618
|
+
next unless in_checksums
|
|
619
|
+
next if stripped.empty?
|
|
620
|
+
next if stripped == "BUNDLED WITH"
|
|
621
|
+
|
|
622
|
+
match = stripped.match(/\A([A-Za-z0-9_.-]+) \(([^)]+)\)(?:\s+(sha256=.*))?\z/)
|
|
623
|
+
next unless match
|
|
624
|
+
|
|
625
|
+
name = match[1]
|
|
626
|
+
checksum = match[3].to_s
|
|
627
|
+
next if !checksum.empty?
|
|
628
|
+
next if path_gems.include?(name)
|
|
629
|
+
|
|
630
|
+
[name, match[2], index]
|
|
631
|
+
end
|
|
632
|
+
return [] unless release_lockfile_has_any_sha_checksum?(path)
|
|
633
|
+
|
|
634
|
+
entries
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
def release_lockfile_has_any_sha_checksum?(path)
|
|
638
|
+
in_checksums = false
|
|
639
|
+
File.readlines(path).any? do |line|
|
|
640
|
+
stripped = line.strip
|
|
641
|
+
if stripped == "CHECKSUMS"
|
|
642
|
+
in_checksums = true
|
|
643
|
+
next false
|
|
644
|
+
end
|
|
645
|
+
next false unless in_checksums
|
|
646
|
+
|
|
647
|
+
stripped.include?("sha256=")
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
def release_lockfile_path_source_gems(path)
|
|
652
|
+
gems = Set.new
|
|
653
|
+
in_path = false
|
|
654
|
+
in_specs = false
|
|
655
|
+
File.readlines(path).each do |line|
|
|
656
|
+
header = line.strip
|
|
657
|
+
if header.match?(/\A[A-Z][A-Z ]*\z/)
|
|
658
|
+
in_path = header == "PATH"
|
|
659
|
+
in_specs = false
|
|
660
|
+
next
|
|
661
|
+
end
|
|
662
|
+
next unless in_path
|
|
663
|
+
|
|
664
|
+
if header == "specs:"
|
|
665
|
+
in_specs = true
|
|
666
|
+
next
|
|
667
|
+
end
|
|
668
|
+
next unless in_specs
|
|
669
|
+
|
|
670
|
+
match = line.match(/\A ([A-Za-z0-9_.-]+) \([^)]+\)/)
|
|
671
|
+
gems << match[1] if match
|
|
672
|
+
end
|
|
673
|
+
gems
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
def release_lockfile_path_dependency_gems(path)
|
|
677
|
+
gems = Set.new
|
|
678
|
+
in_dependencies = false
|
|
679
|
+
File.readlines(path).each do |line|
|
|
680
|
+
header = line.strip
|
|
681
|
+
if header.match?(/\A[A-Z][A-Z ]*\z/)
|
|
682
|
+
in_dependencies = header == "DEPENDENCIES"
|
|
683
|
+
next
|
|
684
|
+
end
|
|
685
|
+
next unless in_dependencies
|
|
686
|
+
|
|
687
|
+
match = line.match(/\A ([A-Za-z0-9_.-]+)!\z/)
|
|
688
|
+
gems << match[1] if match
|
|
689
|
+
end
|
|
690
|
+
gems
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
def release_lockfile_label(path)
|
|
694
|
+
Kettle::Dev.display_path(path)
|
|
695
|
+
end
|
|
696
|
+
|
|
508
697
|
def run_changelog!
|
|
509
698
|
cmd = "bundle exec kettle-changelog"
|
|
510
699
|
cmd = "#{cmd} --version #{Shellwords.escape(@version_override)}" if @version_override
|
data/lib/kettle/dev/version.rb
CHANGED
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: 2.4.
|
|
4
|
+
version: 2.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -349,10 +349,10 @@ licenses:
|
|
|
349
349
|
- AGPL-3.0-only
|
|
350
350
|
metadata:
|
|
351
351
|
homepage_uri: https://kettle-dev.galtzo.com
|
|
352
|
-
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.4.
|
|
353
|
-
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.4.
|
|
352
|
+
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.4.1
|
|
353
|
+
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.4.1/CHANGELOG.md
|
|
354
354
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
|
|
355
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.4.
|
|
355
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.4.1
|
|
356
356
|
funding_uri: https://github.com/sponsors/pboling
|
|
357
357
|
wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
|
|
358
358
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
metadata.gz.sig
CHANGED
|
Binary file
|