reissue 0.4.9 → 0.4.11

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: ec1bcd720b385fc4a7b4ee0ef635d143e6390ed2e5ead9c11b7101648277263f
4
- data.tar.gz: 5c8ba418790813a599ae0f9f96249e69bb146f23883c0369082c6a954f9491f8
3
+ metadata.gz: 2716a8e3df4f6b34bcdaa93f2aeac3ad9ebbe46489c55181a2414bcbd2bc6e58
4
+ data.tar.gz: 8c0090f0e3aef87175c72e4847193f3eb847e0d7307fe21ae89382561cf1ee66
5
5
  SHA512:
6
- metadata.gz: 6d386f5dfb8255426d831e405ed1f831134f0bdf653e40028f64731c6d72b15296cdad6014ed83417bd3e79aa50c016d0b4097450cbe388cbca49d4fa3b20984
7
- data.tar.gz: f98faa91fd66fa1d3080257ff9ab31fbd32dc941e172ce2dbe7f397ef3206e6f04ed6f5463b9a750996c460d455d7b7a8213ad8b654151cf57592137e39ac84b
6
+ metadata.gz: 26336e98efff7be479a552d34fabb965109b23fc9e4acc92977ad090dc13813eca62759b7619e87871126164c5001903ba3c7ec85edb8e9fd794b498a7d8301c
7
+ data.tar.gz: 43e043210fd8315c6f0cd6ff8c9c7e7e85025b452e00f9c9de316baa9f31a8f39151182dbc34d875061d79f6a4d7911382f4554f6ec99a9ea37f2f31aa7fa8b1
data/CHANGELOG.md CHANGED
@@ -5,10 +5,23 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
- ## [0.4.9] - 2026-01-15
8
+ ## [0.4.11] - 2026-02-06
9
+
10
+ ### Added
11
+
12
+ - reissue:initialize task to create changelog and show setup instructions (ad4ae54)
13
+ - working_directory input for monorepo gem releases (55dea65)
14
+ - Gem integration tests for checksums in updated_paths (16b801e)
15
+
16
+ ### Changed
17
+
18
+ - Replace rubygems/release-gem action with explicit release steps (55dea65)
9
19
 
10
20
  ### Fixed
11
21
 
12
- - Adding delete of remote branch after deling the local branch during the reissue:branch task to help with stale tracking reference. (3f6e1fb)
22
+ - Finalize task fails when changelog is already committed (307939e)
23
+ - Checksums not staged during finalize task (307939e)
24
+ - Stage updated_paths fails when files do not exist (16b801e)
25
+ - Release workflow fails with working-directory command not found (9068f04)
13
26
 
14
- ## [0.4.8] - 2025-12-19
27
+ ## [0.4.10] - 2026-01-27
data/README.md CHANGED
@@ -117,7 +117,15 @@ Reissue::Task.create :reissue do |task|
117
117
  # When true, fragments are cleared after a release (only applies when using directory fragments)
118
118
  # Note: Has no effect when using :git fragments
119
119
  task.clear_fragments = true
120
-
120
+
121
+ # Optional: Tag pattern for matching version tags. Defaults to /^v(\d+\.\d+\.\d+.*)$/
122
+ # Must include a capture group for the version number.
123
+ # Only applies when using :git fragments
124
+ # Examples:
125
+ # /^v(\d+\.\d+\.\d+.*)$/ matches "v1.2.3" (default)
126
+ # /^myapp-v(\d+\.\d+\.\d+.*)$/ matches "myapp-v1.2.3"
127
+ task.tag_pattern = /^myapp-v(\d+\.\d+\.\d+.*)$/
128
+
121
129
  # Deprecated: Use `fragment` instead of `fragment_directory`
122
130
  # task.fragment_directory = "changelog_fragments" # DEPRECATED: Use task.fragment instead
123
131
 
@@ -10,6 +10,21 @@ module Reissue
10
10
  # Regex to match changelog section trailers in commit messages
11
11
  TRAILER_REGEX = /^(#{VALID_SECTIONS.join("|")}):\s*(.+)$/i
12
12
 
13
+ # Default pattern for matching version tags (e.g., "v1.2.3")
14
+ DEFAULT_TAG_PATTERN = /^v(\d+\.\d+\.\d+.*)$/
15
+
16
+ # Initialize the handler with optional tag pattern for custom tag formats
17
+ #
18
+ # @param tag_pattern [Regexp, nil] Optional regex pattern for matching version tags.
19
+ # Must include a capture group for the version number.
20
+ # Examples:
21
+ # - /^v(\d+\.\d+\.\d+.*)$/ matches "v1.2.3" (default)
22
+ # - /^myapp-v(\d+\.\d+\.\d+.*)$/ matches "myapp-v1.2.3"
23
+ # - /^qualified-v(\d+\.\d+\.\d+.*)$/ matches "qualified-v0.3.5"
24
+ def initialize(tag_pattern: nil)
25
+ @tag_pattern = tag_pattern || DEFAULT_TAG_PATTERN
26
+ end
27
+
13
28
  # Read changelog entries from git commit trailers
14
29
  #
15
30
  # @return [Hash] A hash of changelog entries organized by section
@@ -52,9 +67,11 @@ module Reissue
52
67
  tag = last_tag
53
68
  return nil unless tag
54
69
 
55
- # Extract version number from tag (e.g., "v1.2.3" -> "1.2.3")
56
- version_string = tag.sub(/^v/, "")
57
- ::Gem::Version.new(version_string)
70
+ # Extract version number from tag using the pattern's capture group
71
+ match = tag.match(@tag_pattern)
72
+ return nil unless match && match[1]
73
+
74
+ ::Gem::Version.new(match[1])
58
75
  end
59
76
 
60
77
  private
@@ -103,14 +120,31 @@ module Reissue
103
120
  commits
104
121
  end
105
122
 
106
- # Find the most recent semantic version tag (v*.*.*) by tag creation date across all branches
107
- # This ensures we exclude commits that are already in ANY tagged release, not just the current branch
108
- # Supports both numeric (v1.2.3) and alphanumeric (v2025.10.C) version tags
123
+ # Find the highest semantic version tag matching the configured pattern
124
+ # Uses the tag_pattern regex to filter tags and finds the highest version
109
125
  #
110
- # @return [String, nil] The most recent version tag or nil if no tags found
126
+ # @return [String, nil] The highest version tag or nil if no tags found
111
127
  def find_last_tag
112
- tag = `git for-each-ref --sort=-creatordate --format='%(refname:short)' 'refs/tags/v[0-9]*.[0-9]*.[a-zA-Z0-9]*' --count=1 2>/dev/null`.strip
113
- tag.empty? ? nil : tag
128
+ output = `git tag -l 2>/dev/null`.strip
129
+ return nil if output.empty?
130
+
131
+ tags = output.split("\n")
132
+
133
+ matching_tags = tags.filter_map do |tag|
134
+ match = tag.match(@tag_pattern)
135
+ next unless match && match[1]
136
+
137
+ begin
138
+ version = ::Gem::Version.new(match[1])
139
+ {tag: tag, version: version}
140
+ rescue ArgumentError
141
+ nil
142
+ end
143
+ end
144
+
145
+ return nil if matching_tags.empty?
146
+
147
+ matching_tags.max_by { |t| t[:version] }&.dig(:tag)
114
148
  end
115
149
 
116
150
  def parse_trailers_from_commits(commits)
@@ -22,9 +22,10 @@ module Reissue
22
22
  #
23
23
  # @param fragment_option [nil, String, Symbol] The fragment configuration
24
24
  # @param valid_sections [Array<String>, nil] List of valid section names (for directory handler)
25
+ # @param tag_pattern [Regexp, nil] Optional regex pattern for matching version tags (for git handler)
25
26
  # @return [FragmentHandler] The appropriate handler instance
26
27
  # @raise [ArgumentError] If the option is not supported
27
- def self.for(fragment_option, valid_sections: nil)
28
+ def self.for(fragment_option, valid_sections: nil, tag_pattern: nil)
28
29
  case fragment_option
29
30
  when nil
30
31
  require_relative "fragment_handler/null_fragment_handler"
@@ -36,7 +37,7 @@ module Reissue
36
37
  DirectoryFragmentHandler.new(fragment_option, **options)
37
38
  when :git
38
39
  require_relative "fragment_handler/git_fragment_handler"
39
- GitFragmentHandler.new
40
+ GitFragmentHandler.new(tag_pattern: tag_pattern)
40
41
  else
41
42
  raise ArgumentError, "Invalid fragment option: #{fragment_option.inspect}"
42
43
  end
data/lib/reissue/rake.rb CHANGED
@@ -98,6 +98,15 @@ module Reissue
98
98
  # Set this to :branch to push to a new branch.
99
99
  attr_accessor :push_reissue
100
100
 
101
+ # Optional regex pattern for matching version tags.
102
+ # Must include a capture group for the version number.
103
+ # Examples:
104
+ # - /^v(\d+\.\d+\.\d+.*)$/ matches "v1.2.3" (default)
105
+ # - /^myapp-v(\d+\.\d+\.\d+.*)$/ matches "myapp-v1.2.3"
106
+ # - /^qualified-v(\d+\.\d+\.\d+.*)$/ matches "qualified-v0.3.5"
107
+ # Default: nil (uses default pattern matching "v1.2.3")
108
+ attr_accessor :tag_pattern
109
+
101
110
  def initialize(name = :reissue, formatter: Reissue, tasker: Rake::Task)
102
111
  @name = name
103
112
  @formatter = formatter
@@ -116,6 +125,7 @@ module Reissue
116
125
  @version_limit = 2
117
126
  @version_redo_proc = nil
118
127
  @push_reissue = :branch
128
+ @tag_pattern = nil
119
129
  end
120
130
 
121
131
  attr_reader :formatter, :tasker
@@ -159,6 +169,20 @@ module Reissue
159
169
  end
160
170
  end
161
171
 
172
+ # Check if there are staged changes ready to commit.
173
+ def changes_to_commit?
174
+ _, _, status = Open3.capture3("git diff --cached --quiet")
175
+ !status.success?
176
+ end
177
+
178
+ # Stage updated_paths that exist on disk.
179
+ def stage_updated_paths
180
+ existing = updated_paths.select { |p| File.exist?(p) }
181
+ if existing.any?
182
+ run_command("git add #{existing.join(" ")}", "Failed to stage additional paths: #{existing.join(", ")}")
183
+ end
184
+ end
185
+
162
186
  def define
163
187
  desc description
164
188
  task name, [:segment] do |task, args|
@@ -176,13 +200,12 @@ module Reissue
176
200
  tasker["#{name}:clear_fragments"].invoke
177
201
 
178
202
  run_command("git add -u", "Failed to stage updated files")
179
- if updated_paths&.any?
180
- run_command("git add #{updated_paths.join(" ")}", "Failed to stage additional paths: #{updated_paths.join(", ")}")
181
- end
203
+ stage_updated_paths
182
204
 
183
205
  bump_message = "Bump version to #{new_version}"
184
206
  if commit
185
207
  if reissue_version_with_branch?
208
+ tasker["#{name}:branch"].reenable
186
209
  tasker["#{name}:branch"].invoke("reissue/#{new_version}")
187
210
  end
188
211
  run_command("git commit -m '#{bump_message}'", "Failed to commit version bump")
@@ -223,8 +246,13 @@ module Reissue
223
246
  tasker["#{name}:branch"].invoke("finalize/#{version}")
224
247
  end
225
248
  run_command("git add -u", "Failed to stage finalized changelog")
226
- run_command("git commit -m '#{finalize_message}'", "Failed to commit finalized changelog")
227
- tasker["#{name}:push"].invoke if push_finalize?
249
+ stage_updated_paths
250
+ if changes_to_commit?
251
+ run_command("git commit -m '#{finalize_message}'", "Failed to commit finalized changelog")
252
+ tasker["#{name}:push"].invoke if push_finalize?
253
+ else
254
+ puts finalize_message
255
+ end
228
256
  else
229
257
  puts finalize_message
230
258
  end
@@ -262,7 +290,7 @@ module Reissue
262
290
  task "#{name}:preview" do
263
291
  if fragment
264
292
  require_relative "fragment_handler"
265
- handler = Reissue::FragmentHandler.for(fragment)
293
+ handler = Reissue::FragmentHandler.for(fragment, tag_pattern: tag_pattern)
266
294
 
267
295
  # Show comparison tag for git trailers
268
296
  if fragment == :git && handler.respond_to?(:last_tag)
@@ -329,7 +357,7 @@ module Reissue
329
357
  require_relative "fragment_handler"
330
358
  require_relative "version_updater"
331
359
 
332
- handler = Reissue::FragmentHandler.for(:git)
360
+ handler = Reissue::FragmentHandler.for(:git, tag_pattern: tag_pattern)
333
361
 
334
362
  # Get current version from version file
335
363
  version_content = File.read(version_file)
@@ -363,3 +391,75 @@ module Reissue
363
391
  end
364
392
  end
365
393
  end
394
+
395
+ # Define the reissue:initialize task as a standalone task
396
+ # This works without any configuration, allowing users to bootstrap their project
397
+ namespace :reissue do
398
+ desc "Initialize reissue by creating a CHANGELOG.md and showing Rakefile configuration"
399
+ task :initialize do
400
+ changelog_file = "CHANGELOG.md"
401
+
402
+ if File.exist?(changelog_file)
403
+ puts "✓ #{changelog_file} already exists"
404
+ else
405
+ Reissue.generate_changelog(changelog_file)
406
+ puts "✓ Created #{changelog_file}"
407
+ end
408
+
409
+ puts
410
+ puts "Add the following to your Rakefile to enable reissue tasks:"
411
+ puts
412
+ puts <<~RAKEFILE
413
+ require "reissue/rake"
414
+
415
+ Reissue::Task.create :reissue do |task|
416
+ task.version_file = "lib/your_gem/version.rb" # Required: path to your VERSION constant
417
+ end
418
+ RAKEFILE
419
+
420
+ puts
421
+ puts "Optional configuration:"
422
+ puts
423
+ puts <<~OPTIONS
424
+ Reissue::Task.create :reissue do |task|
425
+ task.version_file = "lib/your_gem/version.rb"
426
+
427
+ # Changelog options
428
+ task.changelog_file = "CHANGELOG.md" # Default: "CHANGELOG.md"
429
+ task.version_limit = 2 # Versions to keep in changelog
430
+
431
+ # Fragment handling for changelog entries
432
+ task.fragment = :git # Use git commit trailers (Added:, Fixed:, etc.)
433
+ # task.fragment = "changelog_fragments" # Or use a directory of fragment files
434
+ task.clear_fragments = false # Clear fragment files after release. Not necessary when using git trailers.
435
+
436
+ # Git workflow options
437
+ task.commit = true # Auto-commit version bumps
438
+ task.commit_finalize = true # Auto-commit changelog finalization
439
+ task.push_reissue = :branch # Push strategy: false, true, or :branch
440
+ task.push_finalize = false # Push after finalize: false, true, or :branch
441
+
442
+ # Custom tag pattern for version detection (must include capture group)
443
+ # task.tag_pattern = /^myapp-v(\\d+\\.\\d+\\.\\d+.*)$/
444
+ end
445
+ OPTIONS
446
+
447
+ puts
448
+ puts "For Ruby gems, use reissue/gem for automatic integration with bundler tasks:"
449
+ puts
450
+ puts <<~GEM_USAGE
451
+ require "reissue/gem"
452
+
453
+ Reissue::Task.create :reissue do |task|
454
+ task.version_file = "lib/your_gem/version.rb"
455
+ task.fragment = :git
456
+ end
457
+ GEM_USAGE
458
+
459
+ puts
460
+ puts "This automatically runs reissue:bump and reissue:finalize before `rake build`"
461
+ puts "and runs reissue after `rake release`."
462
+ puts
463
+ puts "Run `rake -T reissue` to see all available tasks after configuration."
464
+ end
465
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reissue
4
- VERSION = "0.4.9"
4
+ VERSION = "0.4.11"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reissue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9
4
+ version: 0.4.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay