kettle-changelog 1.0.0

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.
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kettle
4
+ module Changelog
5
+ class EntryAdder
6
+ SECTIONS = %w[Added Changed Deprecated Removed Fixed Security].freeze
7
+
8
+ def initialize(section:, entry:, root: Kettle::Dev::CIHelpers.project_root)
9
+ @root = root
10
+ @section = section.to_s
11
+ @entry = normalize_entry(entry)
12
+ @changelog_path = ENV.fetch("K_CHANGELOG_PATH", File.join(@root, "CHANGELOG.md"))
13
+ end
14
+
15
+ def run
16
+ raise Error, "unsupported changelog section #{@section.inspect}" unless SECTIONS.include?(@section)
17
+ raise Error, "missing CHANGELOG.md in #{Kettle::Dev.display_path(@root)}" unless File.file?(@changelog_path)
18
+
19
+ require_markly_crispr!
20
+ source = File.read(@changelog_path)
21
+ context = Ast::Crispr::Markdown::Markly.document_context(content: source, source_label: @changelog_path)
22
+ sections = context.structural_owners(owner_scope: :heading_sections)
23
+ unreleased = find_unreleased_heading!(sections)
24
+ target = find_unreleased_section!(sections, unreleased)
25
+ slice = target_slice(source, target)
26
+ return :unchanged if entry_present?(slice)
27
+
28
+ updated = insert_entry(source, target)
29
+ File.write(@changelog_path, updated)
30
+ :changed
31
+ end
32
+
33
+ private
34
+
35
+ def normalize_entry(entry)
36
+ text = entry.to_s.strip
37
+ raise Error, "changelog entry must not be empty" if text.empty?
38
+
39
+ text.start_with?("- ") ? text : "- #{text}"
40
+ end
41
+
42
+ def require_markly_crispr!
43
+ require "ast/crispr/markdown/markly"
44
+ rescue LoadError => error
45
+ raise Error, "kettle-changelog add-unreleased-entry requires ast-crispr-markdown-markly (#{error.message})"
46
+ end
47
+
48
+ def find_heading!(sections, heading_text:, level:)
49
+ matches = sections.select { |owner| owner.heading_text.to_s.strip == heading_text && owner.level == level }
50
+ raise Error, "expected exactly one #{heading(level, heading_text)} section in CHANGELOG.md, found #{matches.length}" unless matches.length == 1
51
+
52
+ matches.first
53
+ end
54
+
55
+ def find_unreleased_heading!(sections)
56
+ matches = sections.select do |owner|
57
+ owner.level == 2 && owner.heading_source.to_s.strip == "## [Unreleased]"
58
+ end
59
+ raise Error, "expected exactly one ## [Unreleased] section in CHANGELOG.md, found #{matches.length}" unless matches.length == 1
60
+
61
+ matches.first
62
+ end
63
+
64
+ def find_unreleased_section!(sections, unreleased)
65
+ matches = sections.select do |owner|
66
+ owner.heading_text.to_s.strip == @section &&
67
+ owner.level == 3 &&
68
+ owner.location.start_line > unreleased.location.start_line &&
69
+ owner.location.end_line <= unreleased.location.end_line
70
+ end
71
+ raise Error, "expected at least one #{heading(3, @section)} section under ## [Unreleased] in CHANGELOG.md, found none" if matches.empty?
72
+
73
+ matches.first
74
+ end
75
+
76
+ def heading(level, text)
77
+ "#{"#" * level} #{text}"
78
+ end
79
+
80
+ def target_slice(source, target)
81
+ lines = source.lines
82
+ lines[(target.location.start_line - 1)...target.location.end_line].to_a.join
83
+ end
84
+
85
+ def entry_present?(slice)
86
+ slice.lines.any? { |line| line.chomp == @entry }
87
+ end
88
+
89
+ def insert_entry(source, target)
90
+ lines = source.lines
91
+ insertion_index = insertion_index(lines, target)
92
+ payload = entry_payload(lines, insertion_index, target)
93
+ lines.insert(insertion_index, payload)
94
+ lines.join
95
+ end
96
+
97
+ def insertion_index(lines, target)
98
+ first_content_index = target.location.start_line
99
+ index = target.location.end_line
100
+ while index > first_content_index && lines.fetch(index - 1).strip.empty?
101
+ index -= 1
102
+ end
103
+ index
104
+ end
105
+
106
+ def entry_payload(lines, insertion_index, target)
107
+ previous_line = lines[insertion_index - 1].to_s
108
+ next_line = lines[insertion_index].to_s
109
+ before = previous_line.strip.empty? ? "" : "\n"
110
+ after = (next_line.empty? || next_line.strip.empty?) ? "" : "\n"
111
+ "#{before}#{@entry}\n#{after}"
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kettle
4
+ module Changelog
5
+ # Version namespace for this gem.
6
+ module Version
7
+ # Current gem version.
8
+ VERSION = "1.0.0"
9
+ end
10
+ # Current gem version exposed at the traditional constant location.
11
+ VERSION = Version::VERSION # Traditional Constant Location
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "version_gem"
4
+ require "kettle/dev"
5
+ require_relative "changelog/version"
6
+
7
+ module Kettle
8
+ module Changelog
9
+ class Error < StandardError; end
10
+
11
+ autoload :CLI, "kettle/changelog/cli"
12
+ autoload :EntryAdder, "kettle/changelog/entry_adder"
13
+ end
14
+ end
15
+
16
+ Kettle::Changelog::Version.class_eval do
17
+ extend VersionGem::Basic
18
+ end
@@ -0,0 +1,9 @@
1
+ module Kettle
2
+ module Changelog
3
+ VERSION: String
4
+ module Version
5
+ VERSION: String
6
+ end
7
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
8
+ end
9
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,341 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kettle-changelog
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter H. Boling
8
+ bindir: exe
9
+ cert_chain:
10
+ - |
11
+ -----BEGIN CERTIFICATE-----
12
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
13
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
14
+ A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
15
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
16
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
17
+ uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
18
+ LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
19
+ mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
20
+ coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
21
+ FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
22
+ yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
23
+ to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
24
+ qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
25
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
26
+ HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
27
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
28
+ ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
29
+ wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
30
+ L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
31
+ GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
32
+ kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
33
+ QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
34
+ 0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
35
+ DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
36
+ L9nRqA==
37
+ -----END CERTIFICATE-----
38
+ date: 1980-01-02 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: ast-crispr-markdown-markly
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '7.1'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 7.1.1
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '7.1'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 7.1.1
60
+ - !ruby/object:Gem::Dependency
61
+ name: kettle-dev
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 3.0.6
67
+ - - "<"
68
+ - !ruby/object:Gem::Version
69
+ version: 4.0.0
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 3.0.6
77
+ - - "<"
78
+ - !ruby/object:Gem::Version
79
+ version: 4.0.0
80
+ - !ruby/object:Gem::Dependency
81
+ name: version_gem
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '1.1'
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.1.15
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.1'
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 1.1.15
100
+ - !ruby/object:Gem::Dependency
101
+ name: bundler-audit
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: 0.9.3
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - "~>"
112
+ - !ruby/object:Gem::Version
113
+ version: 0.9.3
114
+ - !ruby/object:Gem::Dependency
115
+ name: rake
116
+ requirement: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - "~>"
119
+ - !ruby/object:Gem::Version
120
+ version: '13.0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - "~>"
126
+ - !ruby/object:Gem::Version
127
+ version: '13.0'
128
+ - !ruby/object:Gem::Dependency
129
+ name: require_bench
130
+ requirement: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - "~>"
133
+ - !ruby/object:Gem::Version
134
+ version: '1.0'
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 1.0.4
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '1.0'
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: 1.0.4
148
+ - !ruby/object:Gem::Dependency
149
+ name: anonymous_loader
150
+ requirement: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - "~>"
153
+ - !ruby/object:Gem::Version
154
+ version: '0.1'
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: 0.1.3
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '0.1'
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: 0.1.3
168
+ - !ruby/object:Gem::Dependency
169
+ name: appraisal2
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: '3.2'
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: 3.2.2
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - "~>"
183
+ - !ruby/object:Gem::Version
184
+ version: '3.2'
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: 3.2.2
188
+ - !ruby/object:Gem::Dependency
189
+ name: kettle-test
190
+ requirement: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '2.0'
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: 2.0.19
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - "~>"
203
+ - !ruby/object:Gem::Version
204
+ version: '2.0'
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: 2.0.19
208
+ - !ruby/object:Gem::Dependency
209
+ name: turbo_tests2
210
+ requirement: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - "~>"
213
+ - !ruby/object:Gem::Version
214
+ version: '3.2'
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: 3.2.5
218
+ type: :development
219
+ prerelease: false
220
+ version_requirements: !ruby/object:Gem::Requirement
221
+ requirements:
222
+ - - "~>"
223
+ - !ruby/object:Gem::Version
224
+ version: '3.2'
225
+ - - ">="
226
+ - !ruby/object:Gem::Version
227
+ version: 3.2.5
228
+ - !ruby/object:Gem::Dependency
229
+ name: ruby-progressbar
230
+ requirement: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - - "~>"
233
+ - !ruby/object:Gem::Version
234
+ version: '1.13'
235
+ type: :development
236
+ prerelease: false
237
+ version_requirements: !ruby/object:Gem::Requirement
238
+ requirements:
239
+ - - "~>"
240
+ - !ruby/object:Gem::Version
241
+ version: '1.13'
242
+ - !ruby/object:Gem::Dependency
243
+ name: stone_checksums
244
+ requirement: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - "~>"
247
+ - !ruby/object:Gem::Version
248
+ version: '1.0'
249
+ - - ">="
250
+ - !ruby/object:Gem::Version
251
+ version: 1.0.8
252
+ type: :development
253
+ prerelease: false
254
+ version_requirements: !ruby/object:Gem::Requirement
255
+ requirements:
256
+ - - "~>"
257
+ - !ruby/object:Gem::Version
258
+ version: '1.0'
259
+ - - ">="
260
+ - !ruby/object:Gem::Version
261
+ version: 1.0.8
262
+ - !ruby/object:Gem::Dependency
263
+ name: gitmoji-regex
264
+ requirement: !ruby/object:Gem::Requirement
265
+ requirements:
266
+ - - "~>"
267
+ - !ruby/object:Gem::Version
268
+ version: '2.0'
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ version: 2.0.11
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '2.0'
279
+ - - ">="
280
+ - !ruby/object:Gem::Version
281
+ version: 2.0.11
282
+ description: "\U0001F4DD kettle-changelog formats release sections, manages Unreleased
283
+ entries, and emits machine-readable release events for Ruby gems."
284
+ email:
285
+ - floss@galtzo.com
286
+ executables:
287
+ - kettle-changelog
288
+ extensions: []
289
+ extra_rdoc_files: []
290
+ files:
291
+ - CHANGELOG.md
292
+ - LICENSE.md
293
+ - README.md
294
+ - exe/kettle-changelog
295
+ - lib/kettle/changelog.rb
296
+ - lib/kettle/changelog/cli.rb
297
+ - lib/kettle/changelog/entry_adder.rb
298
+ - lib/kettle/changelog/version.rb
299
+ - sig/kettle/changelog.rbs
300
+ homepage: https://github.com/kettle-dev/kettle-changelog
301
+ licenses:
302
+ - AGPL-3.0-only
303
+ metadata:
304
+ homepage_uri: https://kettle-changelog.galtzo.com
305
+ source_code_uri: https://github.com/kettle-dev/kettle-changelog/tree/v1.0.0
306
+ changelog_uri: https://github.com/kettle-dev/kettle-changelog/blob/v1.0.0/CHANGELOG.md
307
+ bug_tracker_uri: https://github.com/kettle-dev/kettle-changelog/issues
308
+ documentation_uri: https://www.rubydoc.info/gems/kettle-changelog/1.0.0
309
+ funding_uri: https://github.com/sponsors/pboling
310
+ wiki_uri: https://github.com/kettle-dev/kettle-changelog/wiki
311
+ news_uri: https://www.railsbling.com/tags/kettle-changelog
312
+ discord_uri: https://discord.gg/3qme4XHNKN
313
+ mailing_list_uri: https://www.rubyforum.org/tag/kettle-dev
314
+ rubygems_mfa_required: 'true'
315
+ rdoc_options:
316
+ - "--title"
317
+ - "kettle-changelog - \U0001F4DD Release and maintain structured CHANGELOG.md files."
318
+ - "--main"
319
+ - README.md
320
+ - "--exclude"
321
+ - "^sig/"
322
+ - "--line-numbers"
323
+ - "--inline-source"
324
+ - "--quiet"
325
+ require_paths:
326
+ - lib
327
+ required_ruby_version: !ruby/object:Gem::Requirement
328
+ requirements:
329
+ - - ">="
330
+ - !ruby/object:Gem::Version
331
+ version: 4.0.0
332
+ required_rubygems_version: !ruby/object:Gem::Requirement
333
+ requirements:
334
+ - - ">="
335
+ - !ruby/object:Gem::Version
336
+ version: '0'
337
+ requirements: []
338
+ rubygems_version: 4.0.17
339
+ specification_version: 4
340
+ summary: "\U0001F4DD Release and maintain structured CHANGELOG.md files."
341
+ test_files: []
metadata.gz.sig ADDED
Binary file