From 5bd44e625a4cb60b3caaa4bbf496c01aa0f3ca9a Mon Sep 17 00:00:00 2001 From: Atti Ur Rehman Date: Wed, 24 Jun 2026 17:16:26 +0300 Subject: [PATCH] fix(cd): make NEON_DATABASE_URL_RO optional in Container App secrets Azure rejects empty database-url-ro when NEON_DATABASE_URL_RO is unset. Fall back to the owner DSN for DATABASE_URL_RO; skip optional Langfuse secret when tracing keys are not configured. --- .github/workflows/cd.yml | 56 +++++++++++++++++++++++++++++------- scripts/secrets-reference.sh | 8 ++++-- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 4dd56a5..245a33c 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -123,17 +123,51 @@ jobs: - name: Inject secrets + env vars shell: bash + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }} + GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }} + NEON_DATABASE_URL: ${{ secrets.NEON_DATABASE_URL }} + NEON_DATABASE_URL_RO: ${{ secrets.NEON_DATABASE_URL_RO }} + LANGFUSE_SECRET_KEY: ${{ secrets.LANGFUSE_SECRET_KEY }} + LANGFUSE_PUBLIC_KEY: ${{ secrets.LANGFUSE_PUBLIC_KEY }} + FRONTEND_URL: ${{ secrets.FRONTEND_URL }} run: | + set -euo pipefail + + # Read-only DSN: optional GitHub secret — fall back to owner URL (matches Settings) + if [[ -n "${NEON_DATABASE_URL_RO}" ]]; then + DB_RO_SECRET_REF="secretref:database-url-ro" + DB_RO_SECRET_ARG="database-url-ro=${NEON_DATABASE_URL_RO}" + else + echo "::warning::NEON_DATABASE_URL_RO not set — read pool uses DATABASE_URL (add RO role URL when ready)" + DB_RO_SECRET_REF="secretref:database-url" + DB_RO_SECRET_ARG="" + fi + + SECRETS=( + "anthropic-api-key=${ANTHROPIC_API_KEY}" + "jwt-secret-key=${JWT_SECRET_KEY}" + "google-client-id=${GOOGLE_CLIENT_ID}" + "database-url=${NEON_DATABASE_URL}" + ) + if [[ -n "${DB_RO_SECRET_ARG}" ]]; then + SECRETS+=("${DB_RO_SECRET_ARG}") + fi + if [[ -n "${LANGFUSE_SECRET_KEY}" ]]; then + SECRETS+=("langfuse-sk=${LANGFUSE_SECRET_KEY}") + fi + az containerapp secret set \ --name "$BACKEND_APP_NAME" \ --resource-group "$AZURE_RESOURCE_GROUP" \ - --secrets \ - "anthropic-api-key=${{ secrets.ANTHROPIC_API_KEY }}" \ - "jwt-secret-key=${{ secrets.JWT_SECRET_KEY }}" \ - "google-client-id=${{ secrets.GOOGLE_CLIENT_ID }}" \ - "database-url=${{ secrets.NEON_DATABASE_URL }}" \ - "database-url-ro=${{ secrets.NEON_DATABASE_URL_RO }}" \ - "langfuse-sk=${{ secrets.LANGFUSE_SECRET_KEY }}" + --secrets "${SECRETS[@]}" + + if [[ -n "${LANGFUSE_SECRET_KEY}" ]]; then + LANGFUSE_SK_ENV="LANGFUSE_SECRET_KEY=secretref:langfuse-sk" + else + LANGFUSE_SK_ENV="LANGFUSE_SECRET_KEY=" + fi az containerapp update \ --name "$BACKEND_APP_NAME" \ @@ -144,9 +178,9 @@ jobs: "JWT_SECRET_KEY=secretref:jwt-secret-key" \ "GOOGLE_CLIENT_ID=secretref:google-client-id" \ "DATABASE_URL=secretref:database-url" \ - "DATABASE_URL_RO=secretref:database-url-ro" \ - "LANGFUSE_PUBLIC_KEY=${{ secrets.LANGFUSE_PUBLIC_KEY }}" \ - "LANGFUSE_SECRET_KEY=secretref:langfuse-sk" \ + "DATABASE_URL_RO=${DB_RO_SECRET_REF}" \ + "${LANGFUSE_SK_ENV}" \ + "LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY}" \ "LANGFUSE_BASE_URL=https://cloud.langfuse.com" \ "STATEMENT_TIMEOUT_MS=5000" \ "MAX_ROW_LIMIT=1000" \ @@ -154,7 +188,7 @@ jobs: "CLAUDE_INPUT_USD_PER_MTOK=3.0" \ "CLAUDE_OUTPUT_USD_PER_MTOK=15.0" \ "CACHE_TTL_SECONDS=900" \ - "FRONTEND_URL=${{ secrets.FRONTEND_URL }}" \ + "FRONTEND_URL=${FRONTEND_URL}" \ "LOG_LEVEL=INFO" \ "MAX_RETRIES=3" \ "CLAUDE_MODEL=claude-sonnet-4-5" \ diff --git a/scripts/secrets-reference.sh b/scripts/secrets-reference.sh index 43af998..6f1ca5b 100644 --- a/scripts/secrets-reference.sh +++ b/scripts/secrets-reference.sh @@ -43,15 +43,17 @@ Nothing sensitive is stored in the repository. postgresql://user:password@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require Get from: Neon dashboard → your project → Connection string (owner role) - NEON_DATABASE_URL_RO + NEON_DATABASE_URL_RO (optional) postgresql://insightiq_ro:password@ep-xxx.../neondb?sslmode=require Read-only role — SELECT only. Used for user SQL and schema reads. + If omitted, CD reuses NEON_DATABASE_URL (same as app Settings fallback). + Create role via database/migrations/004_readonly_role_grants.sql ── Langfuse (optional — LLM tracing) ───────────────────────── - LANGFUSE_SECRET_KEY + LANGFUSE_SECRET_KEY (optional) sk-lf-... - Injected via secretref:langfuse-sk in Azure Container App + Injected via secretref:langfuse-sk when set; omitted when tracing disabled LANGFUSE_PUBLIC_KEY pk-lf-...