bard-api 0.6.1 → 0.6.3

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: 563830ec8c572c92d9ccfe0baacef1e2e24746600e7a8d8508a3fe2819c6650e
4
- data.tar.gz: f015d645e8d3bee75b1975b496ae53a93dc7e3bceeb2f21489a954e142862209
3
+ metadata.gz: e51131122902484d133bcaaf0ca3f01abea607acf01b6b89a7459ad99a5afe45
4
+ data.tar.gz: 713e9aac75181d545f6807259a8031c96064b58fc6c02d32e1bdea5f870cc154
5
5
  SHA512:
6
- metadata.gz: 9f49e14b5cb6ab5b9a56c7b5f138d17c725ccdea8c995f9e9e811580ff0cb7801a65c77ce3ee7a6bc8e93cbc4dfb5748702c858873488e9551da8bc63356a518
7
- data.tar.gz: ccfa6aec43edc4d1f30b23cb92b837e9535ef46f1e3b997791bcd0d0a25bb38b736682ef5a468d28652297b670cd0b80d6ebb8f30a8c9444bd446589d25b4290
6
+ metadata.gz: 8294f16c4750b0e560ecb26477a24527dbb29a229cec6e200fd6494d2d31b88bccbd3f0041516aeb1db87d36c1361e7bae678a0d66035aead9d92e86983f2716
7
+ data.tar.gz: 445de7f208e078a97efe9ec981556d585540003828c60d07de236ea736edae2433e6f9bc0afee3949a1c56267c407761822186328f427fb157cb05ee4780c75d
data/lib/bard/api/app.rb CHANGED
@@ -32,7 +32,10 @@ module Bard
32
32
  # lockfile with not-yet-installed gems. The deploy must start from a clean env.
33
33
  def spawn_detached_deploy(command)
34
34
  Bundler.with_unbundled_env do
35
+ # A Passenger web worker is spawned without a login session, so it has no XDG_RUNTIME_DIR;
36
+ # systemd-run --user needs it to find the (linger-backed) user bus at $XDG_RUNTIME_DIR/bus.
35
37
  pid = Process.spawn(
38
+ { "XDG_RUNTIME_DIR" => "/run/user/#{Process.uid}" },
36
39
  "systemd-run", "--user", "--scope", "--collect", "--quiet", "bash", "-lc", command,
37
40
  :in => "/dev/null", %i[out err] => ["log/bard-deploy.log", "a"],
38
41
  )
@@ -43,9 +46,21 @@ module Bard
43
46
 
44
47
  DEPLOY_LOCK = "tmp/bard-deploy.lock"
45
48
  DEPLOYED_SHA = "tmp/bard-deployed.sha"
49
+ FAILED_SHA = "tmp/bard-deploy-failed.sha"
50
+ DEPLOY_LOG = "log/bard-deploy.log"
51
+ # How long a failed sha short-circuits re-deploy: long enough to end the caller's poll loop
52
+ # without a re-spawn, short enough that a fresh `bard deploy` run can retry the same sha.
53
+ FAILED_COOLDOWN = 60
54
+
46
55
  # Record the deployed sha only after bin/setup fully succeeds — a bare `git pull` advances
47
56
  # HEAD before the bundle/migrate/restart run, so HEAD alone would read as "done" too early.
48
- DEPLOY_COMMAND = "flock -n #{DEPLOY_LOCK} -c 'git pull --ff-only origin master && bin/setup && git rev-parse HEAD > #{DEPLOYED_SHA}'"
57
+ # On any failure, stamp the attempted sha so we don't re-spawn (and restart Puma) on every
58
+ # poll; the marker is written inside the flock, so it's on disk before the lock releases.
59
+ DEPLOY_COMMAND =
60
+ "flock -n #{DEPLOY_LOCK} -c '" \
61
+ "rm -f #{FAILED_SHA}; " \
62
+ "git pull --ff-only origin master && bin/setup && git rev-parse HEAD > #{DEPLOYED_SHA} " \
63
+ "|| git rev-parse origin/master > #{FAILED_SHA}'"
49
64
 
50
65
  def call(env)
51
66
  request = Rack::Request.new(env)
@@ -136,6 +151,17 @@ module Bard
136
151
  return json_response(200, { status: "noop", sha: sha }) if target == sha
137
152
  return json_response(409, { status: "deploying", sha: sha }) if deploy_in_progress?
138
153
 
154
+ # A prior attempt at this exact sha just failed. Report it instead of re-spawning the
155
+ # deploy on every poll (which would restart Puma every few seconds and never converge).
156
+ if target == failed_sha && recently_failed?
157
+ return json_response(500, {
158
+ status: "failed",
159
+ sha: sha,
160
+ error: "deploy failed on the server; see #{DEPLOY_LOG}",
161
+ log: deploy_log_tail,
162
+ })
163
+ end
164
+
139
165
  self.class.deploy_runner.call(DEPLOY_COMMAND)
140
166
  json_response(202, { status: "deploying", sha: sha })
141
167
  end
@@ -148,6 +174,21 @@ module Bard
148
174
  File.read(DEPLOYED_SHA).chomp
149
175
  end
150
176
 
177
+ # The sha whose deploy most recently failed (bin/setup or the git pull errored out).
178
+ def failed_sha
179
+ return "" unless File.exist?(FAILED_SHA)
180
+ File.read(FAILED_SHA).chomp
181
+ end
182
+
183
+ def recently_failed?
184
+ File.exist?(FAILED_SHA) && (Time.now - File.mtime(FAILED_SHA)) < FAILED_COOLDOWN
185
+ end
186
+
187
+ def deploy_log_tail(lines = 30)
188
+ return "" unless File.exist?(DEPLOY_LOG)
189
+ File.readlines(DEPLOY_LOG).last(lines).join
190
+ end
191
+
151
192
  def deploy_in_progress?
152
193
  File.open(DEPLOY_LOCK, File::RDWR | File::CREAT, 0o644) do |lock|
153
194
  acquired = lock.flock(File::LOCK_EX | File::LOCK_NB)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bard
4
4
  module Api
5
- VERSION = "0.6.1"
5
+ VERSION = "0.6.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bard-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micah Geisel
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2026-07-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: jwt
@@ -131,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  - !ruby/object:Gem::Version
132
132
  version: '0'
133
133
  requirements: []
134
- rubygems_version: 4.0.6
134
+ rubygems_version: 3.6.2
135
135
  specification_version: 4
136
136
  summary: REST API for BARD-managed Rails projects
137
137
  test_files: []