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 +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/lib/ruby-gem-release/source_control/git/preparation.rb +83 -0
- data/lib/ruby-gem-release/source_control/git.rb +21 -3
- data/lib/ruby-gem-release/version.rb +1 -1
- data/lib/ruby-gem-release/workflow/context.rb +5 -2
- data/lib/ruby-gem-release/workflow/ruby_gem.rb +8 -3
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb0d582f2aa91a4b7e06e0ca416a6e27a3eb12640ffe11d10f833eb6c2652ca0
|
|
4
|
+
data.tar.gz: cf2c4a04e05ae5f4d148ff2d24fc1ff723e38e2abfb41bf0cd9ade68619ea271
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
@@ -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
|
-
|
|
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
|
-
|
|
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?
|
|
@@ -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
|
|
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
|
-
@
|
|
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 =
|
|
44
|
-
@
|
|
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.
|
|
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
|