ci: gate prod deploy behind stage smoke test
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
Nothing reaches prod without deploying to marketing-stage first and
passing a 90s HTTP smoke test. Stage uses test Stripe keys
(stripe-secret-key-stage) so checkout can be exercised safely.
Set STRIPE_PUBLISHABLE_KEY on the stage service manually once:
gcloud run services update marketing-stage --region us-central1 \
--project neuron-785695 \
--update-env-vars STRIPE_PUBLISHABLE_KEY=pk_test_...
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
name: Deploy marketing to Cloud Run
|
||||
|
||||
# Pipeline: build → stage → smoke test → prod
|
||||
# Nothing reaches prod without passing the stage smoke test.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
@@ -188,6 +191,74 @@ jobs:
|
||||
docker push "${LATEST%:*}:latest"
|
||||
echo "Fast asset build complete"
|
||||
|
||||
# ── Stage deployment ──────────────────────────────────────────────────────
|
||||
# marketing-stage is a single-region Cloud Run service (us-central1).
|
||||
# It uses stage-specific Stripe keys (sk_test_...) so checkout can be
|
||||
# exercised safely. Prod deploy only runs after the smoke test below passes.
|
||||
#
|
||||
# Note: STRIPE_PUBLISHABLE_KEY (pk_test_...) is not set here — set it
|
||||
# manually on the service once with:
|
||||
# gcloud run services update marketing-stage --region us-central1 \
|
||||
# --project neuron-785695 \
|
||||
# --update-env-vars STRIPE_PUBLISHABLE_KEY=pk_test_...
|
||||
#
|
||||
# --update-env-vars / --update-secrets merges with existing config so
|
||||
# manually-set values like STRIPE_PUBLISHABLE_KEY are preserved across
|
||||
# pipeline deploys.
|
||||
|
||||
- name: Deploy to marketing-stage
|
||||
id: deploy-stage
|
||||
env:
|
||||
IMAGE: ${{ steps.tag.outputs.image }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
gcloud run deploy marketing-stage \
|
||||
--image "$IMAGE" \
|
||||
--region us-central1 \
|
||||
--project neuron-785695 \
|
||||
--update-env-vars "NODE_ENV=production,GCS_SHARE_BUCKET=neuron-shares-prod,SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9jb2pzZ2hhb25sdHVuaWRrenB3Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzc2NDIxNjgsImV4cCI6MjA5MzIxODE2OH0.e0FVFw1aahnrBVvnkR5R8a-RxCx095U8o_gsk7Quq3E,NEURON_LLM_0_FORMAT=anthropic,NEURON_LLM_0_MODEL=claude-sonnet-4-5,NEURON_LLM_0_URL=https://api.anthropic.com/v1/messages" \
|
||||
--update-secrets "SUPABASE_SERVICE_KEY=supabase-service-key:latest,NEURON_LLM_0_KEY=anthropic-api-key:latest,ANTHROPIC_API_KEY=anthropic-api-key:latest,STRIPE_SECRET_KEY=stripe-secret-key-stage:latest,STRIPE_WEBHOOK_SECRET=stripe-webhook-secret-stage:latest,STRIPE_PRICE_PROFESSIONAL=stripe-price-professional-stage:latest,STRIPE_PRICE_FOUNDING=stripe-price-founding-stage:latest,STRIPE_PRICE_FAMILY_CHILD=stripe-price-family-child:latest,RESEND_API_KEY=resend-api-key:latest,DOCUSEAL_WEBHOOK_TOKEN=docuseal-webhook-token:latest" \
|
||||
--allow-unauthenticated \
|
||||
--quiet
|
||||
|
||||
# Get the stable Cloud Run URL and ensure NEURON_ORIGIN is set correctly.
|
||||
# --update-env-vars is idempotent: no new revision is created if the
|
||||
# value is already correct (i.e. on every deploy after the first).
|
||||
STAGE_URL=$(gcloud run services describe marketing-stage \
|
||||
--region us-central1 --project neuron-785695 \
|
||||
--format 'value(status.url)')
|
||||
echo "stage_url=${STAGE_URL}" >> "$GITHUB_OUTPUT"
|
||||
echo "Stage URL: ${STAGE_URL}"
|
||||
|
||||
gcloud run services update marketing-stage \
|
||||
--region us-central1 --project neuron-785695 \
|
||||
--update-env-vars "NEURON_ORIGIN=${STAGE_URL}" \
|
||||
--quiet
|
||||
|
||||
- name: Smoke test stage
|
||||
run: |
|
||||
set -euo pipefail
|
||||
STAGE_URL="${{ steps.deploy-stage.outputs.stage_url }}"
|
||||
echo "Smoke testing stage: ${STAGE_URL}"
|
||||
|
||||
# Poll up to 90s — container cold-start + El page compilation can take ~20s
|
||||
for i in $(seq 1 18); do
|
||||
STATUS=$(curl -sSo /dev/null -w "%{http_code}" --max-time 15 "${STAGE_URL}/" || echo "000")
|
||||
echo "Attempt ${i}/18: HTTP ${STATUS}"
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "Stage smoke test PASSED"
|
||||
exit 0
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
|
||||
echo "Stage smoke test FAILED — aborting prod deploy"
|
||||
exit 1
|
||||
|
||||
# ── Prod deployment ───────────────────────────────────────────────────────
|
||||
# Only runs if the stage smoke test above passed.
|
||||
|
||||
- name: Deploy to all marketing prod regions in parallel
|
||||
env:
|
||||
IMAGE: ${{ steps.tag.outputs.image }}
|
||||
|
||||
Reference in New Issue
Block a user