Skip to content

Commit 4abf725

Browse files
committed
fix: make deployment smoke checks more resilient
1 parent f56b1b4 commit 4abf725

2 files changed

Lines changed: 55 additions & 23 deletions

File tree

docs/deployment/railway.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Add the following repository secrets in GitHub:
4747
- `RAILWAY_ENVIRONMENT`: target Railway environment name or identifier, usually `production`
4848
- `RAILWAY_PUBLIC_URL`: public HTTPS base URL used by the smoke checks, for example `https://auth-api-production.up.railway.app`
4949

50+
`RAILWAY_PUBLIC_URL` must belong to the same Railway service targeted by `RAILWAY_SERVICE`. If the public URL points to a different service or stale domain, the smoke check will typically return `404` for `/health`.
51+
5052
## Deployment workflow
5153

5254
The deployment workflow lives in `.github/workflows/deploy.yml`.

scripts/smoke-production.sh

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ if [ "${1:-}" = "" ]; then
88
fi
99

1010
base_url="${1%/}"
11+
max_attempts="${SMOKE_MAX_ATTEMPTS:-36}"
12+
retry_delay_seconds="${SMOKE_RETRY_DELAY_SECONDS:-5}"
1113

1214
case "${base_url}" in
1315
http://*|https://*)
@@ -18,31 +20,59 @@ case "${base_url}" in
1820
;;
1921
esac
2022

23+
preview_payload() {
24+
printf '%s' "$1" | tr '\n' ' ' | cut -c1-240
25+
}
26+
2127
curl_json() {
2228
local path="$1"
23-
local payload
24-
25-
payload="$(
26-
curl --fail --silent --show-error \
27-
--location \
28-
--max-redirs 5 \
29-
--proto '=http,https' \
30-
--proto-redir '=https' \
31-
--retry 12 \
32-
--retry-all-errors \
33-
--retry-delay 5 \
34-
"${base_url}${path}"
35-
)"
36-
37-
case "${payload}" in
38-
\{*|\[*)
39-
printf '%s' "${payload}"
40-
;;
41-
*)
42-
echo "Expected JSON from ${base_url}${path}, but received a non-JSON response." >&2
43-
exit 1
44-
;;
45-
esac
29+
local attempt=1
30+
local body_file
31+
local payload=""
32+
local status_code=""
33+
local curl_exit=0
34+
35+
body_file="$(mktemp)"
36+
trap 'rm -f "${body_file}"' RETURN
37+
38+
while [ "${attempt}" -le "${max_attempts}" ]; do
39+
curl_exit=0
40+
status_code="$(
41+
curl --silent --show-error \
42+
--location \
43+
--max-redirs 5 \
44+
--proto '=http,https' \
45+
--proto-redir '=https' \
46+
--connect-timeout 10 \
47+
--max-time 20 \
48+
--output "${body_file}" \
49+
--write-out '%{http_code}' \
50+
"${base_url}${path}"
51+
)" || curl_exit=$?
52+
53+
payload="$(cat "${body_file}")"
54+
55+
if [ "${curl_exit}" -eq 0 ]; then
56+
case "${payload}" in
57+
\{*|\[*)
58+
if [ "${status_code}" = "200" ]; then
59+
printf '%s' "${payload}"
60+
return 0
61+
fi
62+
;;
63+
esac
64+
fi
65+
66+
if [ "${attempt}" -lt "${max_attempts}" ]; then
67+
echo "Waiting for ${base_url}${path} (attempt ${attempt}/${max_attempts}, status=${status_code:-curl-error})" >&2
68+
sleep "${retry_delay_seconds}"
69+
fi
70+
71+
attempt=$((attempt + 1))
72+
done
73+
74+
echo "Expected JSON from ${base_url}${path}, but received status ${status_code:-curl-error} with payload: $(preview_payload "${payload}")" >&2
75+
exit 1
4676
}
4777

4878
health_payload="$(curl_json "/health")"

0 commit comments

Comments
 (0)