ruby-gem-release 0.3.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b3f5a468e45bd12e4299965c4e9417c9b49b0ac11e49339e5dd448c03ee10de
4
- data.tar.gz: afb1782d46c31b3a2a93f582315f88d0c24947518a5fe9d3d5731acf01b7b46e
3
+ metadata.gz: bb0d582f2aa91a4b7e06e0ca416a6e27a3eb12640ffe11d10f833eb6c2652ca0
4
+ data.tar.gz: cf2c4a04e05ae5f4d148ff2d24fc1ff723e38e2abfb41bf0cd9ade68619ea271
5
5
  SHA512:
6
- metadata.gz: e25947ecf903be0158b6958a77fbccf5e50cdd74b0984f7c3f7ab3cf22c72b26fa0aaf90b0006bbbcc478d8e3b232152cbb8fc52ea07c973323d5150bbca2255
7
- data.tar.gz: 8c97476f80580b55cff61957917135539962a63fb664948895a8e7b301cdeb6f5bfe3f44d87286fcaeec5ffb25f82d34df7457e10d28cd197676bac952154809
6
+ metadata.gz: 1d1a8f271c218dbcac3b94cebfb0259559f817f7e64e6581bb51352c3aaa38fd95de13336098d4501aab8ec114d3ec04cfc56861ada30a5bbe6a16b1bfd8ce0a
7
+ data.tar.gz: 2f1f8a38fa8de16d07cd5e9968b298114ae78ab478494b5d452fdbd4202e94be18f797fb27986f4f07e88772f4447d1d61b8899928a1214d7c210d6a411aba26
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.1 (2026/11/07)
4
+
5
+ - [#23](https://github.com/dblock/ruby-gem-release/pull/23): Reject dirty checkouts after dependency installation and commit only staged release preparation changes, preventing generated Bundler artifacts and unrelated files from entering releases - [@dblock](https://github.com/dblock).
6
+
3
7
  ## 0.3.0 (2026/11/07)
4
8
 
5
9
  - [#22](https://github.com/dblock/ruby-gem-release/pull/22): Make the release timezone configurable with a UTC default, use Eastern Time for this project's releases, and prepare version 0.3.0 - [@dblock](https://github.com/dblock).
data/README.md CHANGED
@@ -53,7 +53,7 @@ permissions:
53
53
 
54
54
  jobs:
55
55
  release:
56
- uses: dblock/ruby-gem-release/.github/workflows/release.yml@v0.2.3
56
+ uses: dblock/ruby-gem-release/.github/workflows/release.yml@v0.3.0
57
57
  with:
58
58
  ruby-version: '3.3'
59
59
  rubygems-owner: ${{ inputs.rubygems-owner }}
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module RubyGemRelease
6
+ module SourceControl
7
+ class Git
8
+ class Preparation
9
+ def initialize(directory:, &command)
10
+ @path = File.join(directory, 'prepared-tree')
11
+ @command = command
12
+ end
13
+
14
+ def check_clean!
15
+ entries = changes
16
+ return if entries.empty?
17
+
18
+ raise unexpected_changes('Release requires a clean checkout after dependency installation', entries)
19
+ end
20
+
21
+ def stage_changes!
22
+ if block_given?
23
+ check_clean!
24
+ yield
25
+ end
26
+ paths = changed_paths
27
+ run('--literal-pathspecs', 'add', '--', *paths) unless paths.empty?
28
+ FileUtils.mkdir_p(File.dirname(@path))
29
+ File.write(@path, run('write-tree').strip)
30
+ end
31
+
32
+ def verify!
33
+ entries = changes
34
+ return if entries.empty? && !File.file?(@path)
35
+
36
+ prepared = File.file?(@path) && File.read(@path)
37
+ staged_only = entries.all? { |entry| entry.first[1] == ' ' }
38
+ return if staged_only && prepared == run('write-tree').strip
39
+
40
+ raise unexpected_changes('Working tree or index changed outside release preparation; commit refused', entries)
41
+ end
42
+
43
+ def clear!
44
+ FileUtils.rm_f(@path)
45
+ end
46
+
47
+ private
48
+
49
+ def changed_paths
50
+ changes.flat_map do |status, path, source|
51
+ next [] if status[1] == ' '
52
+
53
+ status[0].match?(/[RC]/) ? [path] : [path, source].compact
54
+ end.uniq
55
+ end
56
+
57
+ def changes
58
+ fields = run('status', '--porcelain=v1', '-z', '--untracked-files=all').split("\0")
59
+ entries = []
60
+ until fields.empty?
61
+ field = fields.shift
62
+ entry = [field[0, 2], field[3..]]
63
+ entry << fields.shift if entry.first.match?(/[RC]/)
64
+ entries << entry
65
+ end
66
+ entries
67
+ end
68
+
69
+ def unexpected_changes(message, entries)
70
+ details = entries.first(20).map { |status, path, source| " #{status} #{path.inspect}#{" (from #{source.inspect})" if source}" }
71
+ details << " ... #{entries.size - 20} more paths" if entries.size > 20
72
+ "#{message} (#{entries.size} paths):\n#{details.join("\n")}\n" \
73
+ 'Remove generated files, restore unexpected tracked/index changes, or intentionally ignore dependency artifacts such as .bundle/config and vendor/bundle. ' \
74
+ 'Stage intended release edits with stage_changes! during preparation, not publication.'
75
+ end
76
+
77
+ def run(*)
78
+ @command.call(*)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -3,6 +3,7 @@
3
3
  require 'open3'
4
4
  require 'tmpdir'
5
5
  require 'fileutils'
6
+ require_relative 'git/preparation'
6
7
 
7
8
  module RubyGemRelease
8
9
  module SourceControl
@@ -36,6 +37,14 @@ module RubyGemRelease
36
37
  raise 'Default branch advanced; start a new release' unless remote_head == expected
37
38
  end
38
39
 
40
+ def check_clean!
41
+ preparation.check_clean!
42
+ end
43
+
44
+ def stage_changes!(&)
45
+ preparation.stage_changes!(&)
46
+ end
47
+
39
48
  def commit!(release)
40
49
  @release = release
41
50
  @initial_commit = ENV['RELEASE_INITIAL_COMMIT'] || head
@@ -87,15 +96,24 @@ module RubyGemRelease
87
96
  end
88
97
 
89
98
  def commit_changes(message, required:)
90
- run('add', '-A')
91
- output = run('diff', '--cached', '--name-only')
99
+ preparation.verify!
100
+ output = run('diff', '--cached', '--name-only', '-z')
92
101
  raise 'Preparing the next development iteration did not change any files' if required && output.empty?
93
- return head if output.empty?
102
+
103
+ if output.empty?
104
+ preparation.clear!
105
+ return head
106
+ end
94
107
 
95
108
  run('commit', '-m', message)
109
+ preparation.clear!
96
110
  head
97
111
  end
98
112
 
113
+ def preparation
114
+ @preparation ||= Preparation.new(directory: @directory, &method(:run))
115
+ end
116
+
99
117
  def run(*)
100
118
  output, error, status = Open3.capture3('git', *)
101
119
  raise "Git command failed: #{error.strip}\n#{output.strip}" unless status.success?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyGemRelease
4
- VERSION = '0.3.0'
4
+ VERSION = '0.3.1'
5
5
  end
@@ -18,9 +18,10 @@ module RubyGemRelease
18
18
  def capture!
19
19
  check_branch
20
20
  validate_timezone(ENV.fetch('TZ', 'UTC'))
21
+ git = configured_git
22
+ git.check_clean!
21
23
  package = Package::RubyGem.new(gemspec: ENV.fetch('INPUT_GEMSPEC', nil))
22
24
  release = initial_release(package)
23
- git = configured_git
24
25
  git.check_current!(release)
25
26
  export('TZ' => ENV.fetch('TZ', 'UTC'), 'GEMSPEC' => package.gemspec, 'RELEASE_PREVIOUS_VERSION' => release.version,
26
27
  'RELEASE_DATE' => release.date.iso8601, 'RELEASE_INITIAL_COMMIT' => git.head)
@@ -32,7 +33,9 @@ module RubyGemRelease
32
33
  expected = ENV.fetch('INPUT_VERSION', '')
33
34
  raise "Prepared version #{version} does not match expected version #{expected}" unless expected.empty? || version == expected
34
35
 
35
- SourceControl::Git.new.check_tag!(version)
36
+ git = SourceControl::Git.new
37
+ git.check_tag!(version)
38
+ git.stage_changes!
36
39
  export('RELEASE_VERSION' => version)
37
40
  end
38
41
 
@@ -27,7 +27,9 @@ module RubyGemRelease
27
27
  private
28
28
 
29
29
  def prepare_release(release)
30
- @changelog&.release!(release.with_version(@version.read))
30
+ @git.stage_changes! do
31
+ @changelog&.release!(release.with_version(@version.read))
32
+ end
31
33
  end
32
34
 
33
35
  def publish(release)
@@ -40,8 +42,11 @@ module RubyGemRelease
40
42
  end
41
43
 
42
44
  def prepare_next(release)
43
- next_release = release.with_next_version(@version.increment!)
44
- @changelog&.prepare_next!(next_release)
45
+ next_release = nil
46
+ @git.stage_changes! do
47
+ next_release = release.with_next_version(@version.increment!)
48
+ @changelog&.prepare_next!(next_release)
49
+ end
45
50
  @git.commit_next!(next_release)
46
51
  @git.push!
47
52
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-gem-release
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Doubrovkine
@@ -56,6 +56,7 @@ files:
56
56
  - lib/ruby-gem-release/package/ruby_gem.rb
57
57
  - lib/ruby-gem-release/release.rb
58
58
  - lib/ruby-gem-release/source_control/git.rb
59
+ - lib/ruby-gem-release/source_control/git/preparation.rb
59
60
  - lib/ruby-gem-release/tasks.rb
60
61
  - lib/ruby-gem-release/version.rb
61
62
  - lib/ruby-gem-release/version/ruby_constant.rb