discharger 0.2.28 → 0.2.29

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: ed420bb45532ec33805ef43ce1ac52c56b349c7600d5019b4f811eeb4275b8e8
4
- data.tar.gz: e37cf9e839380574732bef86f9d087e7117f3ae8472417a363da1948e1cff972
3
+ metadata.gz: 04fa2c7e508709b01420db373058a6ab1cc81314c8cf6aab7a2c1a627e404c86
4
+ data.tar.gz: '09a4b2197db9c3c1509c685192abb53911156c8b7980d96671da59c7049be79f'
5
5
  SHA512:
6
- metadata.gz: f241dc449944f05eeaf4eccf0fb9e5b8d77e4f087cc6e4eef2a79287fa9d28b6088a7b7acd868f0d4a5b295efb08890fa381811665ce3f757dfbb0b1e89924ca
7
- data.tar.gz: 0ffd1f6bad8d1fc3ab7a7f6f5ccf55f0f8a33371a1fb16d07aebcae2bb6c2a2d8b476720a16533221a79bfdbb2cb6953fb96112596e5f212bd8c24b469659184
6
+ metadata.gz: a56b02162d085a4db4ed5460066360c95819f2cc7735dc183f7e522ad31228cbf2a1e1f44c160766b4ceb2f660226f6cfce0b4f7563981a05999016e0e446ae2
7
+ data.tar.gz: ad6369eb6c7f782e92523c9c4e987a2471480e0140d0c918b4ee32b023f83692dddcc98a14a9eac4f2d4f0490e0c5badecedbb64e8e575e59483ab2309289b70
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.28] - 2026-02-17
8
+ ## [0.2.29] - 2026-03-10
9
9
 
10
- ## [0.2.27] - 2026-02-06
10
+ ## [0.2.28] - 2026-02-17
@@ -98,7 +98,7 @@ module Discharger
98
98
  def create_container(name:, port:, image:, internal_port:, env: {}, volume: nil)
99
99
  log "Creating new #{name} container"
100
100
 
101
- cmd = ["docker", "run", "-d", "--name", name, "--user", "postgres", "-p", "#{port}:#{internal_port}"]
101
+ cmd = ["docker", "run", "-d", "--name", name, "-p", "#{port}:#{internal_port}"]
102
102
  env.each { |k, v| cmd.push("-e", "#{k}=#{v}") }
103
103
  cmd.push("-v", volume) if volume
104
104
  cmd.push(image)
@@ -104,8 +104,16 @@ module Discharger
104
104
  exit 0
105
105
  fi
106
106
 
107
- # Fallback to system pg_dump
108
- exec pg_dump "$@"
107
+ # Fallback to system pg_dump (skip this wrapper in PATH to avoid infinite loop)
108
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
109
+ CLEAN_PATH="${PATH//$SCRIPT_DIR:/}"
110
+ CLEAN_PATH="${CLEAN_PATH%:$SCRIPT_DIR}"
111
+ FALLBACK=$(PATH="$CLEAN_PATH" command -v pg_dump 2>/dev/null)
112
+ if [[ -n "$FALLBACK" ]]; then
113
+ exec "$FALLBACK" "$@"
114
+ fi
115
+ echo "Error: pg_dump not found. Start Docker or install PostgreSQL client tools." >&2
116
+ exit 1
109
117
  BASH
110
118
  end
111
119
 
@@ -124,6 +132,7 @@ module Discharger
124
132
  # When running in Docker, host paths don't exist in the container
125
133
  # so we pipe file content via stdin instead
126
134
  INPUT_FILE=""
135
+ HAS_USER=""
127
136
  ARGS=()
128
137
  while [[ $# -gt 0 ]]; do
129
138
  case $1 in
@@ -139,6 +148,11 @@ module Discharger
139
148
  INPUT_FILE="$2"
140
149
  shift 2
141
150
  ;;
151
+ -U|--username|--username=*)
152
+ HAS_USER="1"
153
+ ARGS+=("$1")
154
+ shift
155
+ ;;
142
156
  *)
143
157
  ARGS+=("$1")
144
158
  shift
@@ -146,6 +160,11 @@ module Discharger
146
160
  esac
147
161
  done
148
162
 
163
+ # Default to postgres user if not specified (container runs as root)
164
+ if [[ -z "$HAS_USER" ]]; then
165
+ ARGS=("-U" "postgres" "${ARGS[@]}")
166
+ fi
167
+
149
168
  if [[ -n "$INPUT_FILE" ]]; then
150
169
  docker exec -i "$CONTAINER" #{tool} "${ARGS[@]}" < "$INPUT_FILE"
151
170
  else
@@ -154,8 +173,16 @@ module Discharger
154
173
  exit 0
155
174
  fi
156
175
 
157
- # Fallback to system #{tool}
158
- exec #{tool} "$@"
176
+ # Fallback to system #{tool} (skip this wrapper in PATH to avoid infinite loop)
177
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
178
+ CLEAN_PATH="${PATH//$SCRIPT_DIR:/}"
179
+ CLEAN_PATH="${CLEAN_PATH%:$SCRIPT_DIR}"
180
+ FALLBACK=$(PATH="$CLEAN_PATH" command -v #{tool} 2>/dev/null)
181
+ if [[ -n "$FALLBACK" ]]; then
182
+ exec "$FALLBACK" "$@"
183
+ fi
184
+ echo "Error: #{tool} not found. Start Docker or install PostgreSQL client tools." >&2
185
+ exit 1
159
186
  BASH
160
187
  end
161
188
 
@@ -179,6 +179,20 @@ module Discharger
179
179
  stdout.strip
180
180
  end
181
181
 
182
+ def existing_pr_number(base, head)
183
+ stdout, _, status = Open3.capture3(
184
+ "gh", "pr", "list",
185
+ "--base", base,
186
+ "--head", head,
187
+ "--state", "open",
188
+ "--json", "number",
189
+ "--jq", ".[0].number // empty"
190
+ )
191
+ return nil unless status.success?
192
+ pr = stdout.strip
193
+ pr.empty? ? nil : pr
194
+ end
195
+
182
196
  def define
183
197
  require "slack-ruby-client"
184
198
  Slack.configure do |config|
@@ -189,14 +203,17 @@ module Discharger
189
203
  ---------- STEP 3 ----------
190
204
  Release the current version to production
191
205
 
192
- This task rebases the production branch on the staging branch and tags the
193
- current version. The production branch and the tag will be pushed to the
194
- remote repository.
206
+ This task merges the release branch into production via a GitHub pull
207
+ request and tags the current version.
195
208
 
196
209
  After the release is complete, a new branch will be created to bump the
197
210
  version for the next release.
198
211
  DESC
199
212
  task "#{name}": [:environment] do
213
+ unless system("gh --version > /dev/null 2>&1")
214
+ abort "Error: GitHub CLI (gh) is required for the release process but was not found. Install it: https://cli.github.com"
215
+ end
216
+
200
217
  current_version = Object.const_get(version_constant)
201
218
 
202
219
  # When auto_deploy_staging is enabled, release directly from working_branch
@@ -213,27 +230,45 @@ module Discharger
213
230
  input = $stdin.gets
214
231
  exit if input.chomp.match?(/^x/i)
215
232
 
216
- # Fetch first, then validate what we fetched
217
233
  syscall(
218
234
  ["git checkout #{working_branch}"],
219
235
  ["git branch -D #{staging_branch} 2>/dev/null || true"],
220
- ["git branch -D #{production_branch} 2>/dev/null || true"],
221
- ["git fetch origin #{release_source}:#{release_source} #{production_branch}:#{production_branch}"]
236
+ ["git branch -D #{production_branch} 2>/dev/null || true"]
222
237
  )
223
238
 
224
239
  if auto_deploy_staging
225
- # Ensure HEAD is the release commit (the commit that touched the version file)
240
+ syscall(
241
+ ["git fetch origin #{production_branch}:#{production_branch} #{working_branch}"],
242
+ ["git reset --hard origin/#{working_branch}"]
243
+ )
226
244
  validate_release_commit!(release_source)
227
245
  else
228
- # Standard mode: validate staging branch has same VERSION as working branch
246
+ syscall(
247
+ ["git fetch origin #{release_source}:#{release_source} #{production_branch}:#{production_branch}"]
248
+ )
229
249
  validate_version_match!(staging_branch, working_branch)
230
250
  end
231
251
 
252
+ pr_ref = release_source
253
+ if auto_deploy_staging
254
+ pr_number = existing_pr_number(production_branch, release_source)
255
+ if pr_number
256
+ sysecho "Reusing existing PR ##{pr_number} from #{release_source} to #{production_branch}."
257
+ pr_ref = pr_number
258
+ else
259
+ syscall(
260
+ ["gh pr create --base #{production_branch} --head #{release_source} --title 'Release #{current_version}' --body 'Deploy #{current_version} to production.'"]
261
+ )
262
+ end
263
+ end
264
+
265
+ syscall(
266
+ ["gh pr merge #{pr_ref} --merge"]
267
+ )
268
+
232
269
  continue = syscall(
233
- ["git checkout #{production_branch}"],
234
- ["git reset --hard #{release_source}"],
235
- ["git tag -a v#{current_version} -m 'Release #{current_version}'"],
236
- ["git push origin #{production_branch}:#{production_branch} v#{current_version}:v#{current_version}"],
270
+ ["git fetch origin #{production_branch}:#{production_branch}"],
271
+ ["git tag -a v#{current_version} -m 'Release #{current_version}' #{production_branch}"],
237
272
  ["git push origin v#{current_version}"]
238
273
  ) do
239
274
  tasker["#{name}:slack"].invoke("Released #{app_name} #{current_version} (#{commit_identifier.call}) to production.", release_message_channel, ":chipmunk:")
@@ -242,7 +277,8 @@ module Discharger
242
277
  tasker["#{name}:slack"].reenable
243
278
  tasker["#{name}:slack"].invoke(text, release_message_channel, ":log:", last_message_ts)
244
279
  end
245
- syscall ["git checkout #{working_branch}"]
280
+ # Signal success — no branch switch needed since we stay on working_branch throughout
281
+ true
246
282
  end
247
283
 
248
284
  abort "Release failed." unless continue
@@ -1,3 +1,3 @@
1
1
  module Discharger
2
- VERSION = "0.2.28"
2
+ VERSION = "0.2.29"
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.28
4
+ version: 0.2.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay