gemchain 0.2.0 → 0.2.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 +14 -0
- data/lib/gemchain/cascade.rb +18 -3
- data/lib/gemchain/executor.rb +16 -2
- data/lib/gemchain/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 29cc49ef5619e2bf869d99e3785600c68fce13cac87d5f455103e82ad67964df
|
|
4
|
+
data.tar.gz: e3ee5374417db2c3bf89028b0eb2527dd698217f850bfc9402e1c68c364aed61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b37952e40c01005984baae5a1d077b62af99ab7b77f9a464578dd16a02ec33b6e4c3a371ab7bdeadd99fbbc6c1e9c590f0744d0ab80e4100aa431e5a9ab9c46
|
|
7
|
+
data.tar.gz: 9f9e33a3c2cf12eeb19e0eb641523dfa6e46eadccef43a79352cb4446e6e8ffd77acad93fc1d9697de9c33fa6590634cbd67c20073ff67bafe8895cac62bec96
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.1] — 2026-08-12
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Release staging skips gitignored `Gemfile.lock`** — `git add` failed for
|
|
8
|
+
gem repos that deliberately ignore their lockfile (e.g. ask-mcp), aborting
|
|
9
|
+
the cascade mid-release. Staging now skips files excluded via `.gitignore`.
|
|
10
|
+
- **Cascade mode detection verifies the release actually happened** — a
|
|
11
|
+
failed run can leave `version.rb` bumped while the gem was never pushed;
|
|
12
|
+
the previous `version.rb == target` check then skipped the source release
|
|
13
|
+
and released dependents against a nonexistent version. `update` now checks
|
|
14
|
+
RubyGems for the published version (injectable for tests) before assuming
|
|
15
|
+
post-release mode.
|
|
16
|
+
|
|
3
17
|
## [0.2.0] — 2026-08-10
|
|
4
18
|
|
|
5
19
|
### 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
|
@@ -162,8 +162,7 @@ module Gemchain
|
|
|
162
162
|
name = step[:gem]
|
|
163
163
|
version = step[:version] || bump_dependent(dir, name)
|
|
164
164
|
|
|
165
|
-
files =
|
|
166
|
-
.select { |f| File.exist?(f) }
|
|
165
|
+
files = release_files(dir)
|
|
167
166
|
@runner.run(["git", "add", *files], chdir: dir)
|
|
168
167
|
|
|
169
168
|
message = if step[:dependency]
|
|
@@ -179,6 +178,21 @@ module Gemchain
|
|
|
179
178
|
@runner.run(["git", "push", "origin", "HEAD", "--tags"], chdir: dir)
|
|
180
179
|
end
|
|
181
180
|
|
|
181
|
+
# Gemspec and version file are always staged; Gemfile.lock only when it
|
|
182
|
+
# exists and isn't deliberately excluded via .gitignore (gem repos
|
|
183
|
+
# commonly ignore it).
|
|
184
|
+
def release_files(dir)
|
|
185
|
+
files = [gemspec_file(dir), version_file(dir)]
|
|
186
|
+
lockfile = File.join(dir, "Gemfile.lock")
|
|
187
|
+
files << lockfile if File.exist?(lockfile) && !git_ignored?(dir, lockfile)
|
|
188
|
+
files
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def git_ignored?(dir, file)
|
|
192
|
+
_out, _err, status = Open3.capture3("git", "check-ignore", "--no-index", "-q", file, chdir: dir)
|
|
193
|
+
status.success?
|
|
194
|
+
end
|
|
195
|
+
|
|
182
196
|
# Dependents get an automatic version bump (they're being re-released
|
|
183
197
|
# with a tightened constraint); the source gem's version comes from the
|
|
184
198
|
# :bump step.
|
data/lib/gemchain/version.rb
CHANGED