discharger 0.2.23 → 0.2.24

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: f9f8f3d34471e92401604bcbdc9b1cae5fc0083666895bdf4bf4ab30b40ea381
4
- data.tar.gz: b43d23aea4793cfa6f69c569b36f739156cd4f4d871d9a8ee63b55ecb433846c
3
+ metadata.gz: 9f3ccebbf82065fe09a136e6f5d44a5e78bfa95643b52fee75f40d0763941615
4
+ data.tar.gz: c46241c30ee25101a1e0873e891d03c9beb89a9a65c587324a59a7645334a585
5
5
  SHA512:
6
- metadata.gz: 2e2401d031e40cc3ef91bf5fe230e2837a3c113cfb23699df9e01abf2bb565c5bf686be6298213aed4d605997235a4a2e1f1808f80ad11595ef1eda8c14cef32
7
- data.tar.gz: fbe5642253ef02128866f2e732b2d7d2574361f409b7a44a12a555e16b7f869e93ee68ef702b415ae60f653e629f11ea9283d5dd4a870ab4299e0cf7cc746e9b
6
+ metadata.gz: 2e6ed61916d2d2502eece7911d48d108026e74c5e11b1c689dec61ae451c0e5aeb99decf4215d521d2193f96634c9b880fb0e8cffa22a989db288f434de219c2
7
+ data.tar.gz: 21eee7c2dce99efa8cdf15fbb9d04ac1484209773b3941ead3e950a322a16c1d52f9ea37e95236b9d37ba805eb6e25d80f09f6bda59967114d9c89a9ffa92854
data/CHANGELOG.md CHANGED
@@ -5,6 +5,6 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
- ## [0.2.23] - 2026-01-16
8
+ ## [0.2.24] - 2026-01-22
9
9
 
10
- ## [0.2.22] - 2026-01-07
10
+ ## [0.2.23] - 2026-01-16
@@ -70,11 +70,28 @@ module Discharger
70
70
  create_container(name: name, port: port, image: image, env: env, volume: volume, internal_port: internal_port)
71
71
  end
72
72
 
73
- # Verify container is running
74
- sleep 2
75
- unless system_quiet("docker ps | grep #{name} > /dev/null 2>&1")
76
- log "#{name} container failed to start"
77
- raise "#{name} container failed to start"
73
+ wait_for_container_running(name)
74
+ end
75
+
76
+ def wait_for_container_running(name, timeout: 30)
77
+ require "open3"
78
+ start_time = Time.now
79
+ loop do
80
+ return true if system_quiet("docker ps | grep #{name} > /dev/null 2>&1")
81
+
82
+ status, = Open3.capture3("docker", "inspect", "-f", "{{.State.Status}}", name)
83
+ status = status.strip
84
+ if status == "exited"
85
+ exit_code, = Open3.capture3("docker", "inspect", "-f", "{{.State.ExitCode}}", name)
86
+ logs, = Open3.capture3("docker", "logs", "--tail", "20", name)
87
+ raise "#{name} container exited with code #{exit_code.strip}:\n#{logs}"
88
+ end
89
+
90
+ if Time.now - start_time > timeout
91
+ raise "#{name} container failed to start within #{timeout} seconds (current status: #{status})"
92
+ end
93
+
94
+ sleep 1
78
95
  end
79
96
  end
80
97
 
@@ -1,6 +1,7 @@
1
1
  require "rake/tasklib"
2
2
  require "reissue/rake"
3
3
  require "rainbow/refinement"
4
+ require "open3"
4
5
  using Rainbow
5
6
 
6
7
  module Discharger
@@ -34,6 +35,7 @@ module Discharger
34
35
  attr_accessor :working_branch
35
36
  attr_accessor :staging_branch
36
37
  attr_accessor :production_branch
38
+ attr_accessor :auto_deploy_staging
37
39
 
38
40
  attr_accessor :release_message_channel
39
41
  attr_accessor :version_constant
@@ -63,6 +65,7 @@ module Discharger
63
65
  @production_branch = "main"
64
66
  @description = "Release the current version to #{staging_branch}"
65
67
  @clear_fragments = true
68
+ @auto_deploy_staging = false
66
69
  end
67
70
  private attr_reader :tasker
68
71
 
@@ -109,15 +112,72 @@ module Discharger
109
112
  success
110
113
  end
111
114
 
112
- # Echo a message to the console
113
- #
114
- # @param message [String] the message to echo
115
- # return [TrueClass]
116
115
  def sysecho(message, output: $stdout)
117
116
  output.puts message
118
117
  true
119
118
  end
120
119
 
120
+ # Abort if staging branch has different VERSION than working branch
121
+ def validate_version_match!(staging, working, output: $stdout)
122
+ staging_v = git_show_version(staging)
123
+ working_v = git_show_version(working)
124
+
125
+ return sysecho("✓ Versions match (#{working_v})".bg(:green).black, output:) if staging_v == working_v
126
+
127
+ abort <<~ERROR.bg(:red).white
128
+ VERSION mismatch: #{staging}=#{staging_v || "not found"}, #{working}=#{working_v || "not found"}
129
+
130
+ Run: rake #{name}:stage
131
+ Then retry: rake #{name}
132
+ ERROR
133
+ end
134
+
135
+ # Abort if HEAD is not the commit that last touched the version file
136
+ def validate_release_commit!(branch, output: $stdout)
137
+ head_sha = git_local_sha(branch)
138
+ release_sha = git_version_file_commit(branch)
139
+
140
+ if head_sha.nil? || release_sha.nil?
141
+ abort <<~ERROR.bg(:red).white
142
+ Could not determine release commit.
143
+
144
+ HEAD: #{head_sha || "not found"}
145
+ Release commit: #{release_sha || "not found"}
146
+
147
+ Ensure #{branch} exists and #{version_file} has been modified.
148
+ ERROR
149
+ end
150
+
151
+ return sysecho("✓ HEAD is the release commit (#{head_sha[0, 8]})".bg(:green).black, output:) if head_sha == release_sha
152
+
153
+ abort <<~ERROR.bg(:red).white
154
+ HEAD is not the release commit!
155
+
156
+ HEAD: #{head_sha[0, 8]}
157
+ Release commit: #{release_sha[0, 8]} (last commit to touch #{version_file})
158
+
159
+ Something was merged after the release PR. Verify the branch contents and retry.
160
+ ERROR
161
+ end
162
+
163
+ def git_show_version(branch)
164
+ content, _, status = Open3.capture3("git", "show", "origin/#{branch}:#{version_file}")
165
+ return nil unless status.success?
166
+ content[/VERSION\s*=\s*["']([^"']+)["']/, 1]
167
+ end
168
+
169
+ def git_local_sha(branch)
170
+ stdout, _, status = Open3.capture3("git", "rev-parse", branch)
171
+ return nil unless status.success?
172
+ stdout.strip
173
+ end
174
+
175
+ def git_version_file_commit(branch)
176
+ stdout, _, status = Open3.capture3("git", "log", branch, "-1", "--format=%H", "--", version_file)
177
+ return nil unless status.success?
178
+ stdout.strip
179
+ end
180
+
121
181
  def define
122
182
  require "slack-ruby-client"
123
183
  Slack.configure do |config|
@@ -137,22 +197,40 @@ module Discharger
137
197
  DESC
138
198
  task "#{name}": [:environment] do
139
199
  current_version = Object.const_get(version_constant)
200
+
201
+ # When auto_deploy_staging is enabled, release directly from working_branch
202
+ # instead of staging_branch (for CI/CD pipelines that auto-deploy staging)
203
+ release_source = auto_deploy_staging ? working_branch : staging_branch
204
+
140
205
  sysecho <<~MSG
141
206
  Releasing version #{current_version} to production.
142
207
 
143
208
  This will tag the current version and push it to the production branch.
209
+ Release source: #{release_source}
144
210
  MSG
145
211
  sysecho "Are you ready to continue? (Press Enter to continue, Type 'x' and Enter to exit)".bg(:yellow).black
146
212
  input = $stdin.gets
147
213
  exit if input.chomp.match?(/^x/i)
148
214
 
149
- continue = syscall(
215
+ # Fetch first, then validate what we fetched
216
+ syscall(
150
217
  ["git checkout #{working_branch}"],
151
218
  ["git branch -D #{staging_branch} 2>/dev/null || true"],
152
219
  ["git branch -D #{production_branch} 2>/dev/null || true"],
153
- ["git fetch origin #{staging_branch}:#{staging_branch} #{production_branch}:#{production_branch}"],
220
+ ["git fetch origin #{release_source}:#{release_source} #{production_branch}:#{production_branch}"]
221
+ )
222
+
223
+ if auto_deploy_staging
224
+ # Ensure HEAD is the release commit (the commit that touched the version file)
225
+ validate_release_commit!(release_source)
226
+ else
227
+ # Standard mode: validate staging branch has same VERSION as working branch
228
+ validate_version_match!(staging_branch, working_branch)
229
+ end
230
+
231
+ continue = syscall(
154
232
  ["git checkout #{production_branch}"],
155
- ["git reset --hard #{staging_branch}"],
233
+ ["git reset --hard #{release_source}"],
156
234
  ["git tag -a v#{current_version} -m 'Release #{current_version}'"],
157
235
  ["git push origin #{production_branch}:#{production_branch} v#{current_version}:v#{current_version}"],
158
236
  ["git push origin v#{current_version}"]
@@ -209,6 +287,10 @@ module Discharger
209
287
 
210
288
  desc description
211
289
  task build: :environment do
290
+ if auto_deploy_staging
291
+ sysecho "Note: auto_deploy_staging is enabled. Staging deploys automatically from #{working_branch}.".bg(:yellow).black
292
+ end
293
+
212
294
  # Allow overriding the working branch via environment variable
213
295
  build_branch = ENV["DISCHARGER_BUILD_BRANCH"] || working_branch
214
296
 
@@ -287,6 +369,9 @@ module Discharger
287
369
 
288
370
  pr_url = "#{pull_request_url}/compare/#{finish_branch}?#{params.to_query}"
289
371
 
372
+ next_step = auto_deploy_staging ? "rake #{name}" : "rake #{name}:stage"
373
+ next_step_desc = auto_deploy_staging ? "release to production" : "stage the release branch"
374
+
290
375
  continue = syscall ["git push origin #{finish_branch} --force"] do
291
376
  sysecho <<~MSG
292
377
  Branch #{finish_branch} created.
@@ -295,8 +380,8 @@ module Discharger
295
380
  #{pr_url}
296
381
 
297
382
  Once the PR is merged, pull down #{working_branch} and run
298
- 'rake #{name}:stage'
299
- to stage the release branch.
383
+ '#{next_step}'
384
+ to #{next_step_desc}.
300
385
  MSG
301
386
  end
302
387
  if continue
@@ -316,6 +401,15 @@ module Discharger
316
401
  bin/rails #{name}:build
317
402
  DESC
318
403
  task stage: [:environment] do
404
+ if auto_deploy_staging
405
+ sysecho <<~MSG.bg(:yellow).black
406
+ Note: auto_deploy_staging is enabled.
407
+ Staging is handled automatically when code is pushed to #{working_branch}.
408
+ To release to production, run: 'rake #{name}'
409
+ MSG
410
+ next
411
+ end
412
+
319
413
  tasker["build"].invoke
320
414
  current_version = Object.const_get(version_constant)
321
415
 
@@ -1,3 +1,3 @@
1
1
  module Discharger
2
- VERSION = "0.2.23"
2
+ VERSION = "0.2.24"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discharger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.23
4
+ version: 0.2.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay