gemchain 0.2.0 → 0.2.2
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 +24 -0
- data/lib/gemchain/cascade.rb +18 -3
- data/lib/gemchain/executor.rb +29 -3
- data/lib/gemchain/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7f57089a36952e2778e0ca90654ee97a6484ba1f6f9c002a91c1a30089c6973a
|
|
4
|
+
data.tar.gz: cd1f24b7232ba48c8f1135d8e80374eb656e49e3322d3773b1f3680020761160
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 989b65d9e09fc06ea8445c7137b5e641fd001f7ab332023132a075c91e3a1d7b9649d34470fe78650d2c258507e5f2729d253824d85ec38b082b2efd7121e829
|
|
7
|
+
data.tar.gz: 65efa9a75881d8880d950c2b880816e10d575c9cbf728f427a0679f5fc6fc77c37f41d836a44d5359dbd412b0d8e6bf18db25772c2cae317d37b53dc58dcef1b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
|
+
## [0.2.2] — 2026-08-13
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- **Release skips the commit when nothing is staged** — a source gem whose
|
|
6
|
+
version bump was already committed (e.g. a fix shipped together with the
|
|
7
|
+
bump) crashed the cascade with "nothing to commit, working tree clean".
|
|
8
|
+
`:release` now checks for staged changes (`git diff --cached --quiet`)
|
|
9
|
+
and skips the commit while still building, pushing, and tagging.
|
|
10
|
+
|
|
1
11
|
# Changelog
|
|
2
12
|
|
|
13
|
+
## [0.2.1] — 2026-08-12
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **Release staging skips gitignored `Gemfile.lock`** — `git add` failed for
|
|
18
|
+
gem repos that deliberately ignore their lockfile (e.g. ask-mcp), aborting
|
|
19
|
+
the cascade mid-release. Staging now skips files excluded via `.gitignore`.
|
|
20
|
+
- **Cascade mode detection verifies the release actually happened** — a
|
|
21
|
+
failed run can leave `version.rb` bumped while the gem was never pushed;
|
|
22
|
+
the previous `version.rb == target` check then skipped the source release
|
|
23
|
+
and released dependents against a nonexistent version. `update` now checks
|
|
24
|
+
RubyGems for the published version (injectable for tests) before assuming
|
|
25
|
+
post-release mode.
|
|
26
|
+
|
|
3
27
|
## [0.2.0] — 2026-08-10
|
|
4
28
|
|
|
5
29
|
### Added
|
data/lib/gemchain/cascade.rb
CHANGED
|
@@ -4,8 +4,9 @@ module Gemchain
|
|
|
4
4
|
class Cascade
|
|
5
5
|
Result = Struct.new(:success, :message, :details, keyword_init: true)
|
|
6
6
|
|
|
7
|
-
def initialize(workspace)
|
|
7
|
+
def initialize(workspace, released_check: nil)
|
|
8
8
|
@workspace = workspace
|
|
9
|
+
@released_check = released_check || method(:released_on_rubygems?)
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
# Pre-release guard: warns about gems that depend on +gem_name+.
|
|
@@ -44,7 +45,9 @@ module Gemchain
|
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
# Performs the full cascade update:
|
|
47
|
-
# 1. If the source gem isn't already at +new_version
|
|
48
|
+
# 1. If the source gem isn't already at +new_version+ AND published on
|
|
49
|
+
# RubyGems: bump, test, release it (a version.rb match alone is not
|
|
50
|
+
# enough — a failed run can leave it bumped but unpublished)
|
|
48
51
|
# 2. For each dependent (topological order): update constraint, test, bump, release
|
|
49
52
|
#
|
|
50
53
|
# With test_only: true, only the dependents' :test steps are emitted —
|
|
@@ -60,7 +63,7 @@ module Gemchain
|
|
|
60
63
|
steps = []
|
|
61
64
|
order = @workspace.cascade_order(gem_name)
|
|
62
65
|
|
|
63
|
-
if !test_only && gem.version.to_s != new_version
|
|
66
|
+
if !test_only && (gem.version.to_s != new_version || !@released_check.call(gem_name, new_version))
|
|
64
67
|
# The source must be released before dependents' `bundle update`
|
|
65
68
|
# can resolve the new version from RubyGems.
|
|
66
69
|
steps << {action: :bump, gem: gem_name, version: new_version}
|
|
@@ -105,5 +108,17 @@ module Gemchain
|
|
|
105
108
|
|
|
106
109
|
lines.join("\n")
|
|
107
110
|
end
|
|
111
|
+
|
|
112
|
+
# True when +name+ is published at +version+ on RubyGems. When rubygems
|
|
113
|
+
# is unreachable, assume not published so the full mode (bump → test →
|
|
114
|
+
# release) is preferred — bumping an already-published version is a no-op.
|
|
115
|
+
def released_on_rubygems?(name, version)
|
|
116
|
+
require "json"
|
|
117
|
+
require "net/http"
|
|
118
|
+
body = Net::HTTP.get(URI("https://rubygems.org/api/v1/gems/#{name}.json"))
|
|
119
|
+
JSON.parse(body)["version"] == version
|
|
120
|
+
rescue StandardError
|
|
121
|
+
false
|
|
122
|
+
end
|
|
108
123
|
end
|
|
109
124
|
end
|
data/lib/gemchain/executor.rb
CHANGED
|
@@ -23,6 +23,13 @@ module Gemchain
|
|
|
23
23
|
detail = out.lines.first(5).join.strip if detail.empty?
|
|
24
24
|
raise ExecutionError, "Command failed: #{command.join(' ')}#{detail.empty? ? '' : "\n#{detail}"}"
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
# Runs a command and reports success without raising. Used for
|
|
28
|
+
# conditional checks (e.g. "are there staged changes?").
|
|
29
|
+
def success?(command, chdir: nil)
|
|
30
|
+
_out, _err, status = Open3.capture3(*command, chdir: chdir)
|
|
31
|
+
status.success?
|
|
32
|
+
end
|
|
26
33
|
end
|
|
27
34
|
|
|
28
35
|
BUMP_LEVELS = %i[patch minor major].freeze
|
|
@@ -162,8 +169,7 @@ module Gemchain
|
|
|
162
169
|
name = step[:gem]
|
|
163
170
|
version = step[:version] || bump_dependent(dir, name)
|
|
164
171
|
|
|
165
|
-
files =
|
|
166
|
-
.select { |f| File.exist?(f) }
|
|
172
|
+
files = release_files(dir)
|
|
167
173
|
@runner.run(["git", "add", *files], chdir: dir)
|
|
168
174
|
|
|
169
175
|
message = if step[:dependency]
|
|
@@ -171,7 +177,12 @@ module Gemchain
|
|
|
171
177
|
else
|
|
172
178
|
"Bump to #{version} (gemchain)"
|
|
173
179
|
end
|
|
174
|
-
|
|
180
|
+
# Skip the commit when the release's own bump/constraint changes were
|
|
181
|
+
# already committed (e.g. a fix shipped together with the version
|
|
182
|
+
# bump) — `git commit` would fail on a clean tree.
|
|
183
|
+
unless @runner.success?(["git", "diff", "--cached", "--quiet"], chdir: dir)
|
|
184
|
+
@runner.run(["git", "commit", "-m", message], chdir: dir)
|
|
185
|
+
end
|
|
175
186
|
|
|
176
187
|
@runner.run(["gem", "build", "#{name}.gemspec"], chdir: dir)
|
|
177
188
|
@runner.run(["gem", "push", "#{name}-#{version}.gem"], chdir: dir)
|
|
@@ -179,6 +190,21 @@ module Gemchain
|
|
|
179
190
|
@runner.run(["git", "push", "origin", "HEAD", "--tags"], chdir: dir)
|
|
180
191
|
end
|
|
181
192
|
|
|
193
|
+
# Gemspec and version file are always staged; Gemfile.lock only when it
|
|
194
|
+
# exists and isn't deliberately excluded via .gitignore (gem repos
|
|
195
|
+
# commonly ignore it).
|
|
196
|
+
def release_files(dir)
|
|
197
|
+
files = [gemspec_file(dir), version_file(dir)]
|
|
198
|
+
lockfile = File.join(dir, "Gemfile.lock")
|
|
199
|
+
files << lockfile if File.exist?(lockfile) && !git_ignored?(dir, lockfile)
|
|
200
|
+
files
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def git_ignored?(dir, file)
|
|
204
|
+
_out, _err, status = Open3.capture3("git", "check-ignore", "--no-index", "-q", file, chdir: dir)
|
|
205
|
+
status.success?
|
|
206
|
+
end
|
|
207
|
+
|
|
182
208
|
# Dependents get an automatic version bump (they're being re-released
|
|
183
209
|
# with a tightened constraint); the source gem's version comes from the
|
|
184
210
|
# :bump step.
|
data/lib/gemchain/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gemchain
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kaka Ruto
|
|
@@ -109,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0'
|
|
111
111
|
requirements: []
|
|
112
|
-
rubygems_version: 4.0.
|
|
112
|
+
rubygems_version: 4.0.18
|
|
113
113
|
specification_version: 4
|
|
114
114
|
summary: Cascade gem updates through interdependent gem ecosystems
|
|
115
115
|
test_files: []
|