From 96d3bf831ee2a6353e1a761d8577d14cb26464da Mon Sep 17 00:00:00 2001 From: FragginWagon Date: Thu, 10 Sep 2026 02:30:45 -0400 Subject: [PATCH] feat: add production environment preflight --- .github/workflows/quality.yml | 1 + docs/DEPLOYMENT.md | 10 +++++ scripts/validate-production-env.sh | 54 +++++++++++++++++++++++++ scripts/validate-production-env.test.sh | 23 +++++++++++ 4 files changed, 88 insertions(+) create mode 100755 scripts/validate-production-env.sh create mode 100755 scripts/validate-production-env.test.sh diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 777b79c..6b59741 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -59,6 +59,7 @@ jobs: sh scripts/restore-postgres.test.sh sh scripts/restore-image-storage.test.sh sh scripts/smoke-production.test.sh + sh scripts/validate-production-env.test.sh - name: Run integration tests env: TEST_DATABASE_URL: postgresql://pokemon_inventory:ci-password@localhost:5433/pokemon_inventory_test diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index effba1a..84c7796 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -35,6 +35,16 @@ provider's HTTPS endpoint and provide its token through `PRICING_HTTP_PROVIDER_TOKEN` when required. Production startup rejects the fixture provider, missing endpoints, and non-HTTPS endpoints. +Load the deployment environment into the shell and run the side-effect-free +preflight before deploying: + +```sh +set -a +. ./.env +set +a +./scripts/validate-production-env.sh +``` + Start the stack and apply migrations with: ```sh diff --git a/scripts/validate-production-env.sh b/scripts/validate-production-env.sh new file mode 100755 index 0000000..980b3b3 --- /dev/null +++ b/scripts/validate-production-env.sh @@ -0,0 +1,54 @@ +#!/bin/sh +set -eu + +require_value() { + variable_name=$1 + eval "variable_value=\${$variable_name:-}" + if [ -z "$variable_value" ]; then + printf '%s\n' "${variable_name} is required for production deployment." >&2 + exit 1 + fi +} + +for variable_name in \ + POSTGRES_DB \ + POSTGRES_USER \ + POSTGRES_PASSWORD \ + DATABASE_URL \ + REDIS_URL \ + SMTP_URL \ + SMTP_FROM \ + MFA_ENCRYPTION_KEY \ + PRICING_HTTP_PROVIDER_ENDPOINT + do + require_value "$variable_name" +done + +case "$DATABASE_URL" in + postgresql://*) ;; + *) printf '%s\n' 'DATABASE_URL must use the postgresql:// scheme.' >&2; exit 1 ;; +esac + +case "$REDIS_URL" in + redis://*|rediss://*) ;; + *) printf '%s\n' 'REDIS_URL must use the redis:// or rediss:// scheme.' >&2; exit 1 ;; +esac + +case "$PRICING_HTTP_PROVIDER_ENDPOINT" in + https://*) ;; + *) printf '%s\n' 'PRICING_HTTP_PROVIDER_ENDPOINT must use HTTPS.' >&2; exit 1 ;; +esac + +if [ "${PRICING_FIXTURE_PROVIDER_ENABLED:-false}" = 'true' ]; then + printf '%s\n' 'PRICING_FIXTURE_PROVIDER_ENABLED must be false in production.' >&2 + exit 1 +fi + +case "$POSTGRES_PASSWORD" in + change-me|password|secret|example*) + printf '%s\n' 'POSTGRES_PASSWORD must not use a development placeholder.' >&2 + exit 1 + ;; +esac + +printf '%s\n' 'production environment validation passed' diff --git a/scripts/validate-production-env.test.sh b/scripts/validate-production-env.test.sh new file mode 100755 index 0000000..31cb4d3 --- /dev/null +++ b/scripts/validate-production-env.test.sh @@ -0,0 +1,23 @@ +#!/bin/sh +set -eu + +script=./scripts/validate-production-env.sh + +base_env='POSTGRES_DB=inventory POSTGRES_USER=inventory POSTGRES_PASSWORD=real-password DATABASE_URL=postgresql://inventory:real-password@db:5432/inventory REDIS_URL=rediss://redis:6380 SMTP_URL=smtp://mail:1025 SMTP_FROM=no-reply@example.com MFA_ENCRYPTION_KEY=stable-key PRICING_HTTP_PROVIDER_ENDPOINT=https://provider.example/prices' + +if env -i PATH="$PATH" sh -c "sh $script" >/dev/null 2>&1; then + printf '%s\n' 'expected missing environment to fail' >&2 + exit 1 +fi + +if env -i PATH="$PATH" sh -c "$base_env PRICING_FIXTURE_PROVIDER_ENABLED=true sh $script" >/dev/null 2>&1; then + printf '%s\n' 'expected fixture provider configuration to fail' >&2 + exit 1 +fi + +if ! env -i PATH="$PATH" sh -c "$base_env sh $script" >/dev/null; then + printf '%s\n' 'expected valid environment to pass' >&2 + exit 1 +fi + +printf '%s\n' 'production environment validation tests passed'