kettle-dev 2.5.18 → 2.5.19
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 +20 -1
- data/README.md +3 -1
- data/lib/kettle/dev/markdown_reference_validator.rb +254 -0
- data/lib/kettle/dev/pre_release_cli.rb +26 -3
- data/lib/kettle/dev/version.rb +1 -1
- data/lib/kettle/dev.rb +1 -0
- data.tar.gz.sig +0 -0
- metadata +5 -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: a8ffb38694a14518e416b497413025d417137ce7b7cf8673dd31f68aa46c8539
|
|
4
|
+
data.tar.gz: 71d1ff523dc11ba20f72994792ad3edd4ff43a0ceea2c8c84e46e65b77e72977
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7cf27e978644578be5e2839670c4981343b9d84646d59ece70e4d83eb388404dcd52b77c3f90929164ff86f698bc6bfc93ecfa42f8bfc9a2ec342d764030aa3
|
|
7
|
+
data.tar.gz: 59de547a4f7a50905bed8bc66c8b919eca375ff9d4d31bd079371dfee717d540bf800477bae8dad644a2efe7935d7cb44b53e059cb4554a99c54d5655d372dc2
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,23 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [2.5.19] - 2026-08-06
|
|
34
|
+
|
|
35
|
+
- TAG: [v2.5.19][2.5.19t]
|
|
36
|
+
- COVERAGE: 91.34% -- 5431/5946 lines in 47 files
|
|
37
|
+
- BRANCH COVERAGE: 75.28% -- 2037/2706 branches in 47 files
|
|
38
|
+
- 50.64% documented
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Track the released kettle-gha-pins client and its cache/tag-resolution contract in the development lockfile and specs.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- Add release validation for Markdown reference labels and local heading anchors.
|
|
47
|
+
|
|
48
|
+
- Restore the Discord badge reference in CONTRIBUTING.md.
|
|
49
|
+
|
|
33
50
|
## [2.5.18] - 2026-08-03
|
|
34
51
|
|
|
35
52
|
- TAG: [v2.5.18][2.5.18t]
|
|
@@ -3242,7 +3259,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
3242
3259
|
- Selecting will run the selected workflow via `act`
|
|
3243
3260
|
- This may move to its own gem in the future.
|
|
3244
3261
|
|
|
3245
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.
|
|
3262
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.19...HEAD
|
|
3263
|
+
[2.5.19]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.18...v2.5.19
|
|
3264
|
+
[2.5.19t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.5.19
|
|
3246
3265
|
[2.5.18]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.17...v2.5.18
|
|
3247
3266
|
[2.5.18t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.5.18
|
|
3248
3267
|
[2.5.17]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.16...v2.5.17
|
data/README.md
CHANGED
|
@@ -409,6 +409,8 @@ What it does:
|
|
|
409
409
|
- Script: `exe/kettle-release` (run as `kettle-release`)
|
|
410
410
|
- Purpose: guided release helper that:
|
|
411
411
|
- Runs `kettle-pre-release` as step 0 on full releases, aborting before release setup if any pre-release gate fails.
|
|
412
|
+
- Validates Markdown reference definitions and local heading anchors across releasable documentation before network checks.
|
|
413
|
+
Markdown fixtures under `spec/` and `test/`, along with `tmp/`, are intentionally excluded.
|
|
412
414
|
- Skips pre-release checks for any `start_step` greater than `0`, so resumptions begin directly at the requested numbered step.
|
|
413
415
|
- Runs sanity checks (`bin/setup`, `bin/rake`), confirms version/changelog, optionally updates Appraisals, regenerates docs via `bin/rake yard`, commits “🔖 Prepare release vX.Y.Z”.
|
|
414
416
|
- Optionally runs your CI locally with `act` before any push:
|
|
@@ -1005,7 +1007,7 @@ Thanks for RTFM. ☺️
|
|
|
1005
1007
|
[📌gitmoji]: https://gitmoji.dev
|
|
1006
1008
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1007
1009
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1008
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.
|
|
1010
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.946-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1009
1011
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
1010
1012
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1011
1013
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
require "uri"
|
|
5
|
+
|
|
6
|
+
module Kettle
|
|
7
|
+
module Dev
|
|
8
|
+
# Validates Markdown reference labels and local link destinations.
|
|
9
|
+
#
|
|
10
|
+
# This is intentionally a small source scanner rather than a second Markdown
|
|
11
|
+
# rendering pipeline. The release gate needs reference integrity and local
|
|
12
|
+
# anchor checks, while the existing Markdown merge/parser dependencies are
|
|
13
|
+
# not runtime dependencies of kettle-dev.
|
|
14
|
+
class MarkdownReferenceValidator
|
|
15
|
+
Issue = Struct.new(:path, :line, :message)
|
|
16
|
+
Report = Struct.new(:file_count, :reference_count, :local_target_count, :issues)
|
|
17
|
+
|
|
18
|
+
FENCE_RE = /\A\s*(`{3,}|~{3,})/.freeze
|
|
19
|
+
IGNORED_PATH_PREFIXES = %w[tmp/ .git/ spec/ test/].freeze
|
|
20
|
+
REFERENCE_DEFINITION_RE = /\A {0,3}\[([^\]]+)\]:\s*(?:<([^>]+)>|(\S+))/
|
|
21
|
+
REFERENCE_USAGE_RE = /!?\[([^\]]*)\]\[([^\]]*)\]/
|
|
22
|
+
INLINE_LINK_RE = /!?\[[^\]]*\]\((<[^>]+>|[^)]*)\)/
|
|
23
|
+
ATX_HEADING_RE = /\A {0,3}\#{1,6}\s+(.+?)\s*\#*\s*\z/
|
|
24
|
+
SETEXT_HEADING_RE = /\A {0,3}(=+|-+)\s*\z/
|
|
25
|
+
|
|
26
|
+
def initialize(root: Dir.pwd, files: nil)
|
|
27
|
+
@root = File.expand_path(root)
|
|
28
|
+
@files = (files || default_files).reject { |path| ignored_path?(path) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def validate!
|
|
32
|
+
documents = @files.each_with_object({}) do |path, result|
|
|
33
|
+
absolute = absolute_path(path)
|
|
34
|
+
result[path] = parse_document(path, absolute) if File.file?(absolute)
|
|
35
|
+
end
|
|
36
|
+
report = build_report(documents)
|
|
37
|
+
return report if report.issues.empty?
|
|
38
|
+
|
|
39
|
+
warn("[kettle-pre-release] Markdown reference validation failed:")
|
|
40
|
+
report.issues.each do |issue|
|
|
41
|
+
warn(" - #{Kettle::Dev.display_path(issue.path)}:#{issue.line}: #{issue.message}")
|
|
42
|
+
end
|
|
43
|
+
raise Kettle::Dev::Error, "Markdown reference validation failed (#{report.issues.size} issue(s))"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def default_files
|
|
49
|
+
if defined?(Kettle::Dev::PreReleaseCLI::Markdown)
|
|
50
|
+
Kettle::Dev::PreReleaseCLI::Markdown.project_markdown_files.reject { |path| ignored_path?(path) }
|
|
51
|
+
else
|
|
52
|
+
Dir.glob(["**/*.md", "**/*.markdown", "**/*.md.example"]).reject { |path| ignored_path?(path) }.sort
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def ignored_path?(path)
|
|
57
|
+
IGNORED_PATH_PREFIXES.any? { |prefix| path.to_s.start_with?(prefix) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def absolute_path(path)
|
|
61
|
+
File.expand_path(path, @root)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def parse_document(path, absolute)
|
|
65
|
+
lines = File.readlines(absolute, chomp: true)
|
|
66
|
+
definitions = {}
|
|
67
|
+
usages = []
|
|
68
|
+
local_targets = []
|
|
69
|
+
headings = []
|
|
70
|
+
in_fence = false
|
|
71
|
+
fence_char = nil
|
|
72
|
+
fence_length = 0
|
|
73
|
+
previous_text = nil
|
|
74
|
+
|
|
75
|
+
lines.each_with_index do |line, index|
|
|
76
|
+
line_number = index + 1
|
|
77
|
+
fence = line.match(FENCE_RE)
|
|
78
|
+
if in_fence
|
|
79
|
+
if fence && fence[1][0] == fence_char && fence[1].length >= fence_length
|
|
80
|
+
in_fence = false
|
|
81
|
+
end
|
|
82
|
+
next
|
|
83
|
+
elsif fence
|
|
84
|
+
in_fence = true
|
|
85
|
+
fence_char = fence[1][0]
|
|
86
|
+
fence_length = fence[1].length
|
|
87
|
+
next
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
definition = line.match(REFERENCE_DEFINITION_RE)
|
|
91
|
+
if definition
|
|
92
|
+
label = normalize_label(definition[1])
|
|
93
|
+
target = definition[2] || definition[3]
|
|
94
|
+
definitions[label] ||= []
|
|
95
|
+
definitions[label] << [line_number, target]
|
|
96
|
+
local_targets << [line_number, target]
|
|
97
|
+
previous_text = nil
|
|
98
|
+
next
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
line.scan(REFERENCE_USAGE_RE) do |text, label|
|
|
102
|
+
resolved_label = label.empty? ? text : label
|
|
103
|
+
usages << [line_number, normalize_label(resolved_label)]
|
|
104
|
+
end
|
|
105
|
+
line.scan(INLINE_LINK_RE) do |destination|
|
|
106
|
+
target = destination[0]
|
|
107
|
+
target = target[1..-2] if target.start_with?("<") && target.end_with?(">")
|
|
108
|
+
target = target.split(/\s+/, 2).first
|
|
109
|
+
local_targets << [line_number, target] unless target.to_s.empty?
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
if line.match?(SETEXT_HEADING_RE) && previous_text
|
|
113
|
+
headings << [line_number - 1, previous_text]
|
|
114
|
+
previous_text = nil
|
|
115
|
+
else
|
|
116
|
+
heading = heading_for(line)
|
|
117
|
+
headings << heading if heading
|
|
118
|
+
previous_text = line.strip unless line.strip.empty?
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
{
|
|
123
|
+
path: path,
|
|
124
|
+
definitions: definitions,
|
|
125
|
+
usages: usages,
|
|
126
|
+
local_targets: local_targets,
|
|
127
|
+
headings: heading_slugs(headings)
|
|
128
|
+
}
|
|
129
|
+
rescue Errno::EACCES, Errno::ENOENT => error
|
|
130
|
+
{
|
|
131
|
+
path: path,
|
|
132
|
+
definitions: {},
|
|
133
|
+
usages: [],
|
|
134
|
+
local_targets: [],
|
|
135
|
+
headings: [],
|
|
136
|
+
read_error: error
|
|
137
|
+
}
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def build_report(documents)
|
|
141
|
+
issues = []
|
|
142
|
+
reference_count = 0
|
|
143
|
+
local_target_count = 0
|
|
144
|
+
heading_cache = {}
|
|
145
|
+
|
|
146
|
+
documents.each_value do |document|
|
|
147
|
+
if document[:read_error]
|
|
148
|
+
issues << Issue.new(document[:path], 1, "could not read Markdown file: #{document[:read_error].message}")
|
|
149
|
+
next
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
document[:definitions].each do |label, definitions|
|
|
153
|
+
if definitions.length > 1
|
|
154
|
+
definitions.drop(1).each do |line_number, _target|
|
|
155
|
+
issues << Issue.new(document[:path], line_number, "duplicate reference definition #{label.inspect}")
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
document[:usages].each do |line_number, label|
|
|
161
|
+
next if label.include?("<") || label.include?(">")
|
|
162
|
+
|
|
163
|
+
reference_count += 1
|
|
164
|
+
next if document[:definitions].key?(label)
|
|
165
|
+
|
|
166
|
+
issues << Issue.new(document[:path], line_number, "undefined Markdown reference #{label.inspect}")
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
document[:local_targets].each do |line_number, target|
|
|
170
|
+
destination = local_destination(target)
|
|
171
|
+
next unless destination
|
|
172
|
+
|
|
173
|
+
local_target_count += 1
|
|
174
|
+
target_path, fragment = destination
|
|
175
|
+
target_document = target_path.empty? ? document : documents_for_path(documents, document[:path], target_path)
|
|
176
|
+
if target_document.nil?
|
|
177
|
+
issues << Issue.new(document[:path], line_number, "local Markdown target does not exist: #{target_path.inspect}")
|
|
178
|
+
next
|
|
179
|
+
end
|
|
180
|
+
next if fragment.empty?
|
|
181
|
+
|
|
182
|
+
slugs = heading_cache[target_document[:path]] ||= target_document[:headings]
|
|
183
|
+
next if slugs.include?(fragment)
|
|
184
|
+
|
|
185
|
+
issues << Issue.new(document[:path], line_number, "local heading target does not exist: ##{fragment}")
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
Report.new(documents.size, reference_count, local_target_count, issues)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def documents_for_path(documents, source_path, target_path)
|
|
193
|
+
candidate = File.expand_path(target_path, File.dirname(absolute_path(source_path)))
|
|
194
|
+
documents.values.find { |document| absolute_path(document[:path]) == candidate }
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def local_destination(target)
|
|
198
|
+
value = target.to_s.strip
|
|
199
|
+
return nil if value.empty? || value.start_with?("//")
|
|
200
|
+
|
|
201
|
+
uri = URI.parse(value)
|
|
202
|
+
return nil if uri.scheme || uri.host
|
|
203
|
+
path = unescape(uri.path.to_s)
|
|
204
|
+
fragment = unescape(uri.fragment.to_s).downcase
|
|
205
|
+
return nil if fragment.empty?
|
|
206
|
+
return nil unless path.empty? || markdown_path?(path)
|
|
207
|
+
|
|
208
|
+
[path, fragment]
|
|
209
|
+
rescue URI::InvalidURIError
|
|
210
|
+
nil
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def unescape(value)
|
|
214
|
+
parser = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
|
|
215
|
+
parser.unescape(value)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def markdown_path?(path)
|
|
219
|
+
path.downcase.end_with?(".md", ".markdown", ".md.example")
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def normalize_label(label)
|
|
223
|
+
label.to_s.downcase.gsub(/\s+/, " ").strip
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def heading_for(line)
|
|
227
|
+
match = line.match(ATX_HEADING_RE)
|
|
228
|
+
match ? [line[/\A\s*/].to_s.length + 1, match[1]] : nil
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def heading_slugs(headings)
|
|
232
|
+
counts = Hash.new(0)
|
|
233
|
+
headings.each_with_object(Set.new) do |(_line, text), slugs|
|
|
234
|
+
slug = slugify(text)
|
|
235
|
+
next if slug.empty?
|
|
236
|
+
|
|
237
|
+
suffix = counts[slug]
|
|
238
|
+
counts[slug] += 1
|
|
239
|
+
slugs.add(suffix.zero? ? slug : "#{slug}-#{suffix}")
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def slugify(text)
|
|
244
|
+
text.to_s.gsub(/<[^>]+>/, "").downcase
|
|
245
|
+
.gsub(/[*_~`]/, "")
|
|
246
|
+
.gsub(/[^\p{Alnum}\s-]/u, "")
|
|
247
|
+
.gsub(/\s+/, "-")
|
|
248
|
+
.squeeze("-")
|
|
249
|
+
.sub(/\A-/, "")
|
|
250
|
+
.sub(/-\z/, "")
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
@@ -11,6 +11,7 @@ require "net/http"
|
|
|
11
11
|
require "openssl"
|
|
12
12
|
require "time"
|
|
13
13
|
require_relative "cache_progress"
|
|
14
|
+
require_relative "markdown_reference_validator"
|
|
14
15
|
require "kettle/ndjson"
|
|
15
16
|
begin
|
|
16
17
|
require "addressable/uri"
|
|
@@ -24,7 +25,8 @@ module Kettle
|
|
|
24
25
|
# Checks:
|
|
25
26
|
# 1) Ensure GitHub Actions workflow actions are pinned to current SHAs.
|
|
26
27
|
# 2) Normalize Markdown image URLs using Addressable normalization.
|
|
27
|
-
# 3) Validate Markdown
|
|
28
|
+
# 3) Validate Markdown references and local heading targets.
|
|
29
|
+
# 4) Validate Markdown image links resolve via cached HTTP(S) HEAD/GET.
|
|
28
30
|
#
|
|
29
31
|
# Usage: Kettle::Dev::PreReleaseCLI.new(check_num: 1).run
|
|
30
32
|
class PreReleaseCLI
|
|
@@ -288,6 +290,7 @@ module Kettle
|
|
|
288
290
|
checks = []
|
|
289
291
|
checks << method(:check_github_actions_sha_pins!)
|
|
290
292
|
checks << method(:check_markdown_uri_normalization!)
|
|
293
|
+
checks << method(:check_markdown_references!)
|
|
291
294
|
checks << method(:check_markdown_images_http!)
|
|
292
295
|
|
|
293
296
|
start = @check_num
|
|
@@ -376,10 +379,30 @@ module Kettle
|
|
|
376
379
|
normalized.to_s
|
|
377
380
|
end
|
|
378
381
|
|
|
379
|
-
# Check 3: Validate Markdown
|
|
382
|
+
# Check 3: Validate Markdown references and local heading targets.
|
|
383
|
+
# @return [void]
|
|
384
|
+
def check_markdown_references!
|
|
385
|
+
puts "[kettle-pre-release] Check 3: Validate Markdown references and local heading targets"
|
|
386
|
+
report = MarkdownReferenceValidator.new(
|
|
387
|
+
root: Dir.pwd,
|
|
388
|
+
files: Markdown.project_markdown_files
|
|
389
|
+
).validate!
|
|
390
|
+
puts "[kettle-pre-release] Markdown references: #{report.reference_count} references, #{report.local_target_count} local targets, #{report.file_count} files."
|
|
391
|
+
emit_pre_release_event(
|
|
392
|
+
action: "markdown_references",
|
|
393
|
+
status: "ok",
|
|
394
|
+
files: report.file_count,
|
|
395
|
+
references: report.reference_count,
|
|
396
|
+
local_targets: report.local_target_count,
|
|
397
|
+
failures: 0
|
|
398
|
+
)
|
|
399
|
+
nil
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# Check 4: Validate Markdown image links by cached HTTP HEAD/GET.
|
|
380
403
|
# @return [void]
|
|
381
404
|
def check_markdown_images_http!
|
|
382
|
-
puts "[kettle-pre-release] Check
|
|
405
|
+
puts "[kettle-pre-release] Check 4: Validate Markdown image links (cached HTTP HEAD, with GET fallback)"
|
|
383
406
|
urls = Markdown.extract_image_urls_from_files
|
|
384
407
|
puts "[kettle-pre-release] Found #{urls.size} unique image URL(s)."
|
|
385
408
|
skipped = []
|
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 = "2.5.
|
|
8
|
+
VERSION = "2.5.19"
|
|
9
9
|
end
|
|
10
10
|
# Current gem version exposed at the traditional constant location.
|
|
11
11
|
VERSION = Version::VERSION # Traditional Constant Location
|
data/lib/kettle/dev.rb
CHANGED
|
@@ -44,6 +44,7 @@ module Kettle
|
|
|
44
44
|
autoload :InputAdapter, "kettle/dev/input_adapter"
|
|
45
45
|
autoload :InteractiveReleaseCommand, "kettle/dev/interactive_release_command"
|
|
46
46
|
autoload :LockfileReset, "kettle/dev/lockfile_reset"
|
|
47
|
+
autoload :MarkdownReferenceValidator, "kettle/dev/markdown_reference_validator"
|
|
47
48
|
autoload :ReadmeBackers, "kettle/dev/readme_backers"
|
|
48
49
|
autoload :OpenCollectiveConfig, "kettle/dev/open_collective_config"
|
|
49
50
|
autoload :ReleaseNotifier, "kettle/dev/release_notifier"
|
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.5.
|
|
4
|
+
version: 2.5.19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -370,6 +370,7 @@ files:
|
|
|
370
370
|
- lib/kettle/dev/input_adapter.rb
|
|
371
371
|
- lib/kettle/dev/interactive_release_command.rb
|
|
372
372
|
- lib/kettle/dev/lockfile_reset.rb
|
|
373
|
+
- lib/kettle/dev/markdown_reference_validator.rb
|
|
373
374
|
- lib/kettle/dev/open_collective_config.rb
|
|
374
375
|
- lib/kettle/dev/pre_release_cli.rb
|
|
375
376
|
- lib/kettle/dev/rakelib/appraisal.rake
|
|
@@ -401,10 +402,10 @@ licenses:
|
|
|
401
402
|
- AGPL-3.0-only
|
|
402
403
|
metadata:
|
|
403
404
|
homepage_uri: https://kettle-dev.galtzo.com
|
|
404
|
-
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.5.
|
|
405
|
-
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.5.
|
|
405
|
+
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.5.19
|
|
406
|
+
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.5.19/CHANGELOG.md
|
|
406
407
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
|
|
407
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.5.
|
|
408
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.5.19
|
|
408
409
|
funding_uri: https://github.com/sponsors/pboling
|
|
409
410
|
wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
|
|
410
411
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
metadata.gz.sig
CHANGED
|
Binary file
|