kettle-gha-pins 0.2.0 → 0.2.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 +18 -1
- data/README.md +4 -4
- data/lib/kettle/gha/pins/action_resolver.rb +14 -14
- data/lib/kettle/gha/pins/cli.rb +51 -37
- data/lib/kettle/gha/pins/github_client.rb +2 -2
- data/lib/kettle/gha/pins/persistent_action_cache.rb +6 -3
- data/lib/kettle/gha/pins/version.rb +1 -1
- data/lib/kettle/gha/pins/version_rubric.rb +7 -3
- data.tar.gz.sig +0 -0
- metadata +5 -19
- 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: 133a74b904371a5a48a6fe9bc0483ae4c3925b99167f394b452386b0a69664fd
|
|
4
|
+
data.tar.gz: d43ede8e0f4a3f3a1400b489e46d077d5744a6c4b0b5231b46b2de4c60951814
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c59c539a7107ea0b9f69464c06656ad317c1515099861e995c022036af1c6cf0c3e0e4227c58f97262f32d2b1b4fd2f4a536eec305c0f5ca93623116ad56eceb
|
|
7
|
+
data.tar.gz: 278b5a77866045c05a677a5e426359a7c34afe2556523a92ae042680a27e6e013e928124e42b0b26a8acc55d446370020e445114eb145c6bc77084cef1045a42
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,21 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [0.2.1] - 2026-07-22
|
|
34
|
+
|
|
35
|
+
- TAG: [v0.2.1][0.2.1t]
|
|
36
|
+
- COVERAGE: 99.08% -- 858/866 lines in 8 files
|
|
37
|
+
- BRANCH COVERAGE: 92.11% -- 350/380 branches in 8 files
|
|
38
|
+
- 22.22% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Lowered the generated gemspec Ruby requirement to `>= 2.4.0` to match
|
|
43
|
+
`kettle-dev`, restored Ruby 2.4-compatible runtime syntax, and explicitly
|
|
44
|
+
required the `set` stdlib used by the CLI.
|
|
45
|
+
- Made CLI line rewrites tolerate Psych scalar column differences across Ruby
|
|
46
|
+
versions.
|
|
47
|
+
|
|
33
48
|
## [0.2.0] - 2026-07-22
|
|
34
49
|
|
|
35
50
|
- TAG: [v0.2.0][0.2.0t]
|
|
@@ -76,7 +91,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
76
91
|
- kettle-jem-template-20260720-005 - Generated README Support & Community rows
|
|
77
92
|
now include a RubyForum help badge.
|
|
78
93
|
|
|
79
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-gha-pins/compare/v0.2.
|
|
94
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-gha-pins/compare/v0.2.1...HEAD
|
|
95
|
+
[0.2.1]: https://github.com/kettle-dev/kettle-gha-pins/compare/v0.2.0...v0.2.1
|
|
96
|
+
[0.2.1t]: https://github.com/kettle-dev/kettle-gha-pins/releases/tag/v0.2.1
|
|
80
97
|
[0.2.0]: https://github.com/kettle-dev/kettle-gha-pins/compare/v0.1.0...v0.2.0
|
|
81
98
|
[0.2.0t]: https://github.com/kettle-dev/kettle-gha-pins/releases/tag/v0.2.0
|
|
82
99
|
[0.1.0]: https://github.com/kettle-dev/kettle-gha-pins/compare/c633526495c7db0a8721a94a71c3def0f3cc71bb...v0.1.0
|
data/README.md
CHANGED
|
@@ -56,8 +56,8 @@ kettle-gha-pins --write --upgrade patch
|
|
|
56
56
|
|
|
57
57
|
### Compatibility
|
|
58
58
|
|
|
59
|
-
Compatible with MRI Ruby
|
|
60
|
-
CI workflows and Appraisals are generated for MRI Ruby
|
|
59
|
+
Compatible with MRI Ruby 2.4.0+, and concordant releases of JRuby, and TruffleRuby.
|
|
60
|
+
CI workflows and Appraisals are generated for MRI Ruby 2.4.0+.
|
|
61
61
|
This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
|
|
62
62
|
may be higher than the gem's runtime compatibility floor when legacy Rubies are
|
|
63
63
|
not practical for the current toolchain.
|
|
@@ -532,7 +532,7 @@ Thanks for RTFM. ☺️
|
|
|
532
532
|
[📌gitmoji]: https://gitmoji.dev
|
|
533
533
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
534
534
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
535
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.
|
|
535
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.866-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
536
536
|
[🔐security]: https://github.com/kettle-dev/kettle-gha-pins/blob/main/SECURITY.md
|
|
537
537
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
538
538
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -558,7 +558,7 @@ Thanks for RTFM. ☺️
|
|
|
558
558
|
| Field | Value |
|
|
559
559
|
|---|---|
|
|
560
560
|
| Package | kettle-gha-pins |
|
|
561
|
-
| Description | 📌
|
|
561
|
+
| Description | 📌 GitHub Actions workflow SHA pin maintenance, including deterministic release-tag parsing, canonicalization, cache-backed GitHub ref resolution, and upgrade planning. |
|
|
562
562
|
| Homepage | https://github.com/kettle-dev/kettle-gha-pins |
|
|
563
563
|
| Source | https://github.com/kettle-dev/kettle-gha-pins |
|
|
564
564
|
| License | `MIT` |
|
|
@@ -167,32 +167,32 @@ module Kettle
|
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
class << self
|
|
170
|
-
def resolve_action_plan(
|
|
171
|
-
ActionResolver.resolve_action_plan(
|
|
170
|
+
def resolve_action_plan(**kwargs)
|
|
171
|
+
ActionResolver.resolve_action_plan(**kwargs)
|
|
172
172
|
end
|
|
173
173
|
|
|
174
|
-
def determine_upgrade_plan(
|
|
175
|
-
ActionResolver.determine_upgrade_plan(
|
|
174
|
+
def determine_upgrade_plan(**kwargs)
|
|
175
|
+
ActionResolver.determine_upgrade_plan(**kwargs)
|
|
176
176
|
end
|
|
177
177
|
|
|
178
|
-
def matching_version_entry(
|
|
179
|
-
ActionResolver.matching_version_entry(
|
|
178
|
+
def matching_version_entry(versions, current_ref, current_sha, client, repo_ref)
|
|
179
|
+
ActionResolver.matching_version_entry(versions, current_ref, current_sha, client, repo_ref)
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
def version_entry_sha(
|
|
183
|
-
ActionResolver.version_entry_sha(
|
|
182
|
+
def version_entry_sha(entry, client, repo_ref)
|
|
183
|
+
ActionResolver.version_entry_sha(entry, client, repo_ref)
|
|
184
184
|
end
|
|
185
185
|
|
|
186
|
-
def short_sha?(
|
|
187
|
-
ActionResolver.short_sha?(
|
|
186
|
+
def short_sha?(candidate)
|
|
187
|
+
ActionResolver.short_sha?(candidate)
|
|
188
188
|
end
|
|
189
189
|
|
|
190
|
-
def non_sha?(
|
|
191
|
-
ActionResolver.non_sha?(
|
|
190
|
+
def non_sha?(candidate)
|
|
191
|
+
ActionResolver.non_sha?(candidate)
|
|
192
192
|
end
|
|
193
193
|
|
|
194
|
-
def stale_sha?(
|
|
195
|
-
ActionResolver.stale_sha?(
|
|
194
|
+
def stale_sha?(current, latest)
|
|
195
|
+
ActionResolver.stale_sha?(current, latest)
|
|
196
196
|
end
|
|
197
197
|
end
|
|
198
198
|
end
|
data/lib/kettle/gha/pins/cli.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "json"
|
|
|
4
4
|
require "open3"
|
|
5
5
|
require "optparse"
|
|
6
6
|
require "pathname"
|
|
7
|
+
require "set"
|
|
7
8
|
|
|
8
9
|
require "psych"
|
|
9
10
|
require "kettle/gha/pins"
|
|
@@ -273,9 +274,11 @@ module Kettle
|
|
|
273
274
|
@options[:progress] = bool
|
|
274
275
|
end
|
|
275
276
|
opt.on("--skip-pattern PATTERN", "Skip workflow paths matching pattern (repeatable)") do |pattern|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
begin
|
|
278
|
+
@options[:reject_patterns] << Regexp.new(pattern)
|
|
279
|
+
rescue RegexpError => e
|
|
280
|
+
Kernel.abort("Invalid --skip-pattern #{pattern.inspect}: #{e.message}")
|
|
281
|
+
end
|
|
279
282
|
end
|
|
280
283
|
opt.on("--[no-]validate", "Validate YAML after editing") do |bool|
|
|
281
284
|
@options[:validate] = bool
|
|
@@ -297,25 +300,27 @@ module Kettle
|
|
|
297
300
|
def load_workflows(paths, state)
|
|
298
301
|
file_progress = progress_bar(title: "Files", total: paths.length)
|
|
299
302
|
paths.each_with_object([]) do |path, workflows|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
303
|
+
begin
|
|
304
|
+
state[:files_scanned] += 1
|
|
305
|
+
begin
|
|
306
|
+
text = File.read(path)
|
|
307
|
+
rescue Errno::EACCES => e
|
|
308
|
+
record_failure(state, path: path, error: "read_error: #{e.message}")
|
|
309
|
+
next
|
|
310
|
+
end
|
|
307
311
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
312
|
+
begin
|
|
313
|
+
parsed = Psych.parse_stream(text)
|
|
314
|
+
rescue Psych::Exception => e
|
|
315
|
+
record_failure(state, path: path, error: "yaml_parse_error: #{e.message}")
|
|
316
|
+
next
|
|
317
|
+
end
|
|
314
318
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
+
uses_nodes = extract_uses_nodes(parsed, text)
|
|
320
|
+
workflows << {path: path, text: text, uses_nodes: uses_nodes} unless uses_nodes.empty?
|
|
321
|
+
ensure
|
|
322
|
+
file_progress&.increment
|
|
323
|
+
end
|
|
319
324
|
end
|
|
320
325
|
end
|
|
321
326
|
|
|
@@ -469,7 +474,7 @@ module Kettle
|
|
|
469
474
|
action: {
|
|
470
475
|
owner: parts[0],
|
|
471
476
|
repo: parts[1],
|
|
472
|
-
path: (parts.length > 2) ? parts[2
|
|
477
|
+
path: (parts.length > 2) ? parts[2..-1].join("/") : nil,
|
|
473
478
|
ref: ref
|
|
474
479
|
}
|
|
475
480
|
}
|
|
@@ -594,14 +599,10 @@ module Kettle
|
|
|
594
599
|
line_text = text.lines[line]
|
|
595
600
|
return nil if line_text.nil?
|
|
596
601
|
|
|
597
|
-
|
|
598
|
-
return nil if raw.nil?
|
|
599
|
-
|
|
600
|
-
token_info = extract_scalar_token(raw)
|
|
602
|
+
token_info = locate_scalar_token(line_text, col, old_token)
|
|
601
603
|
return nil unless token_info
|
|
602
|
-
return nil unless token_info[:token] == old_token
|
|
603
604
|
|
|
604
|
-
suffix =
|
|
605
|
+
suffix = line_text[token_info[:end]..-1].to_s
|
|
605
606
|
match = suffix.match(VERSION_COMMENT_SUFFIX_RE)
|
|
606
607
|
match && match[:version]
|
|
607
608
|
end
|
|
@@ -610,20 +611,16 @@ module Kettle
|
|
|
610
611
|
line_text = text.lines[line]
|
|
611
612
|
return nil if line_text.nil?
|
|
612
613
|
|
|
613
|
-
|
|
614
|
-
return nil if raw.nil?
|
|
615
|
-
|
|
616
|
-
token_info = extract_scalar_token(raw)
|
|
614
|
+
token_info = locate_scalar_token(line_text, col, old_token)
|
|
617
615
|
return nil unless token_info
|
|
618
|
-
return nil unless token_info[:token] == old_token
|
|
619
616
|
|
|
620
617
|
rendered = render_replacement(old_token, new_ref, token_info[:quote])
|
|
621
618
|
return nil unless rendered
|
|
622
619
|
|
|
623
|
-
span = token_info[:
|
|
620
|
+
span = token_info[:end] - token_info[:start]
|
|
624
621
|
new_scalar = rendered[:quoted]
|
|
625
622
|
if new_version && token_info[:quote] == :plain
|
|
626
|
-
suffix =
|
|
623
|
+
suffix = line_text[token_info[:end]..-1].to_s
|
|
627
624
|
comment = suffix.match(VERSION_COMMENT_REPLACEMENT_RE)
|
|
628
625
|
if comment
|
|
629
626
|
span += comment[0].length
|
|
@@ -632,14 +629,31 @@ module Kettle
|
|
|
632
629
|
end
|
|
633
630
|
|
|
634
631
|
{
|
|
635
|
-
start:
|
|
636
|
-
end:
|
|
632
|
+
start: token_info[:start],
|
|
633
|
+
end: token_info[:start] + span,
|
|
637
634
|
new_scalar: new_scalar,
|
|
638
635
|
new_ref: new_ref,
|
|
639
636
|
old_token: old_token
|
|
640
637
|
}
|
|
641
638
|
end
|
|
642
639
|
|
|
640
|
+
def locate_scalar_token(line_text, col, old_token)
|
|
641
|
+
return nil if col.nil? || col.negative? || col >= line_text.length
|
|
642
|
+
|
|
643
|
+
matches = []
|
|
644
|
+
0.upto(line_text.length - 1) do |index|
|
|
645
|
+
token_info = extract_scalar_token(line_text[index..-1])
|
|
646
|
+
next unless token_info
|
|
647
|
+
next unless token_info[:token] == old_token
|
|
648
|
+
|
|
649
|
+
matches << token_info.merge(
|
|
650
|
+
start: index,
|
|
651
|
+
end: index + token_info[:span]
|
|
652
|
+
)
|
|
653
|
+
end
|
|
654
|
+
matches.min_by { |match| [(match[:start] - col).abs, match[:start]] }
|
|
655
|
+
end
|
|
656
|
+
|
|
643
657
|
def apply_edits(original_text, edits)
|
|
644
658
|
lines = original_text.lines
|
|
645
659
|
grouped = edits.group_by { |entry| entry[:line] }
|
|
@@ -652,7 +666,7 @@ module Kettle
|
|
|
652
666
|
next if line.nil?
|
|
653
667
|
|
|
654
668
|
entries.each do |entry|
|
|
655
|
-
line = line[0...entry[:start]].to_s + entry[:new_scalar] + line[entry[:end]
|
|
669
|
+
line = line[0...entry[:start]].to_s + entry[:new_scalar] + line[entry[:end]..-1].to_s
|
|
656
670
|
end
|
|
657
671
|
updated[line_num] = line
|
|
658
672
|
end
|
|
@@ -96,13 +96,13 @@ module Kettle
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
def build_release_versions(data, tag_shas)
|
|
99
|
-
release_tags = data.
|
|
99
|
+
release_tags = data.each_with_object([]) do |release, memo|
|
|
100
100
|
next unless release.is_a?(Hash)
|
|
101
101
|
|
|
102
102
|
tag = release["tag_name"].to_s
|
|
103
103
|
next unless VersionRubric.parse(tag)
|
|
104
104
|
|
|
105
|
-
tag
|
|
105
|
+
memo << tag
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
VersionRubric.build_release_versions(
|
|
@@ -41,7 +41,10 @@ module Kettle
|
|
|
41
41
|
return nil if entries.empty?
|
|
42
42
|
return nil if fresh && entries.length != versions.length
|
|
43
43
|
|
|
44
|
-
entries.
|
|
44
|
+
entries.each_with_object([]) do |entry, memo|
|
|
45
|
+
deserialized = deserialize_version_entry(entry)
|
|
46
|
+
memo << deserialized if deserialized
|
|
47
|
+
end
|
|
45
48
|
.sort_by { |entry| entry[:version_obj] }
|
|
46
49
|
.reverse
|
|
47
50
|
end
|
|
@@ -147,11 +150,11 @@ module Kettle
|
|
|
147
150
|
end
|
|
148
151
|
|
|
149
152
|
def target_cache(version_entries)
|
|
150
|
-
entries = version_entries.
|
|
153
|
+
entries = version_entries.each_with_object([]) do |entry, memo|
|
|
151
154
|
deserialized = deserialize_version_entry(entry)
|
|
152
155
|
next unless deserialized
|
|
153
156
|
|
|
154
|
-
deserialized.merge(cached_at: entry["cached_at"].to_s)
|
|
157
|
+
memo << deserialized.merge(cached_at: entry["cached_at"].to_s)
|
|
155
158
|
end
|
|
156
159
|
return {} if entries.empty?
|
|
157
160
|
|
|
@@ -38,11 +38,15 @@ module Kettle
|
|
|
38
38
|
|
|
39
39
|
def build_release_versions(release_tags:, tag_shas:)
|
|
40
40
|
released_tags = release_tags.each_with_object({}) { |tag, memo| memo[tag.to_s] = true }
|
|
41
|
-
releases = release_tags.
|
|
42
|
-
|
|
41
|
+
releases = release_tags.each_with_object([]) do |tag, memo|
|
|
42
|
+
release_entry = entry(tag: tag, sha: tag_shas[tag.to_s])
|
|
43
|
+
memo << release_entry if release_entry
|
|
44
|
+
end
|
|
45
|
+
tag_versions = tag_shas.each_with_object([]) do |(tag, sha), memo|
|
|
43
46
|
next if released_tags[tag.to_s]
|
|
44
47
|
|
|
45
|
-
entry(tag: tag, sha: sha)
|
|
48
|
+
tag_entry = entry(tag: tag, sha: sha)
|
|
49
|
+
memo << tag_entry if tag_entry
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
sort_versions(canonicalize_equivalent_release_versions(releases + tag_versions)).reverse
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kettle-gha-pins
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -199,20 +199,6 @@ dependencies:
|
|
|
199
199
|
- - ">="
|
|
200
200
|
- !ruby/object:Gem::Version
|
|
201
201
|
version: 3.2.0
|
|
202
|
-
- !ruby/object:Gem::Dependency
|
|
203
|
-
name: ruby-progressbar
|
|
204
|
-
requirement: !ruby/object:Gem::Requirement
|
|
205
|
-
requirements:
|
|
206
|
-
- - "~>"
|
|
207
|
-
- !ruby/object:Gem::Version
|
|
208
|
-
version: '1.13'
|
|
209
|
-
type: :development
|
|
210
|
-
prerelease: false
|
|
211
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
212
|
-
requirements:
|
|
213
|
-
- - "~>"
|
|
214
|
-
- !ruby/object:Gem::Version
|
|
215
|
-
version: '1.13'
|
|
216
202
|
- !ruby/object:Gem::Dependency
|
|
217
203
|
name: stone_checksums
|
|
218
204
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -281,10 +267,10 @@ licenses:
|
|
|
281
267
|
- MIT
|
|
282
268
|
metadata:
|
|
283
269
|
homepage_uri: https://github.com/kettle-dev/kettle-gha-pins
|
|
284
|
-
source_code_uri: https://github.com/kettle-dev/kettle-gha-pins/tree/v0.2.
|
|
285
|
-
changelog_uri: https://github.com/kettle-dev/kettle-gha-pins/blob/v0.2.
|
|
270
|
+
source_code_uri: https://github.com/kettle-dev/kettle-gha-pins/tree/v0.2.1
|
|
271
|
+
changelog_uri: https://github.com/kettle-dev/kettle-gha-pins/blob/v0.2.1/CHANGELOG.md
|
|
286
272
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-gha-pins/issues
|
|
287
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-gha-pins/0.2.
|
|
273
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-gha-pins/0.2.1
|
|
288
274
|
funding_uri: https://github.com/sponsors/pboling
|
|
289
275
|
wiki_uri: https://github.com/kettle-dev/kettle-gha-pins/wiki
|
|
290
276
|
news_uri: https://www.railsbling.com/tags/kettle-gha-pins
|
|
@@ -307,7 +293,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
307
293
|
requirements:
|
|
308
294
|
- - ">="
|
|
309
295
|
- !ruby/object:Gem::Version
|
|
310
|
-
version:
|
|
296
|
+
version: 2.4.0
|
|
311
297
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
312
298
|
requirements:
|
|
313
299
|
- - ">="
|
metadata.gz.sig
CHANGED
|
Binary file
|