From 46956c419934479022caa3b154708a378e1d6d8b Mon Sep 17 00:00:00 2001 From: John Dalmolin <82729254+john-dalmolin@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:48:16 -0300 Subject: [PATCH] fix: harden deployment smoke validation --- .github/workflows/deploy.yml | 8 ++++++++ docs/deployment/railway.md | 2 +- scripts/smoke-production.sh | 29 ++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index feab343..54d0532 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -66,6 +66,14 @@ jobs: echo "SMOKE_ENABLED=false" >> "${GITHUB_ENV}" echo "::warning::RAILWAY_PUBLIC_URL is not configured. Deployment will run, but smoke validation will be skipped." else + case "${APP_BASE_URL}" in + https://*) + ;; + *) + echo "::error::RAILWAY_PUBLIC_URL/app_base_url must be a full HTTPS base URL, for example https://auth-api-production.up.railway.app" + exit 1 + ;; + esac echo "SMOKE_ENABLED=true" >> "${GITHUB_ENV}" fi diff --git a/docs/deployment/railway.md b/docs/deployment/railway.md index 204a3e6..760665f 100644 --- a/docs/deployment/railway.md +++ b/docs/deployment/railway.md @@ -45,7 +45,7 @@ Add the following repository secrets in GitHub: - `RAILWAY_PROJECT_ID`: target Railway project identifier - `RAILWAY_SERVICE`: target Railway service name or identifier for the API - `RAILWAY_ENVIRONMENT`: target Railway environment name or identifier, usually `production` -- `RAILWAY_PUBLIC_URL`: public HTTPS base URL used by the smoke checks +- `RAILWAY_PUBLIC_URL`: public HTTPS base URL used by the smoke checks, for example `https://auth-api-production.up.railway.app` ## Deployment workflow diff --git a/scripts/smoke-production.sh b/scripts/smoke-production.sh index e021a65..71a19af 100755 --- a/scripts/smoke-production.sh +++ b/scripts/smoke-production.sh @@ -9,13 +9,40 @@ fi base_url="${1%/}" +case "${base_url}" in + http://*|https://*) + ;; + *) + echo "Expected a full base URL including scheme, for example: https://auth-api-production.up.railway.app" >&2 + exit 1 + ;; +esac + curl_json() { local path="$1" - curl --fail --silent --show-error \ + local payload + + payload="$( + curl --fail --silent --show-error \ + --location \ + --max-redirs 5 \ + --proto '=http,https' \ + --proto-redir '=https' \ --retry 12 \ --retry-all-errors \ --retry-delay 5 \ "${base_url}${path}" + )" + + case "${payload}" in + \{*|\[*) + printf '%s' "${payload}" + ;; + *) + echo "Expected JSON from ${base_url}${path}, but received a non-JSON response." >&2 + exit 1 + ;; + esac } health_payload="$(curl_json "/health")"