From cc6271eabed98f70e921200ff844e5fdafa28dd2 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:33:39 +0100 Subject: [PATCH 1/9] feat(backend): add Cloud Run deployment workflow Hardcoded values: - GCP Project: atomify-ee7b5 - Region: europe-west1 - Database: SQLite at /data/atomify.db - GCS Bucket: atomify-user-files - CORS: localhost:3000, andeplane.github.io Only 2 secrets needed: - GCP_SA_KEY - GCP_SERVICE_ACCOUNT_EMAIL --- .github/workflows/backend.yaml | 57 ++++++++++- backend/DEPLOYMENT.md | 179 +++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 backend/DEPLOYMENT.md diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml index 8759c60c..aef7ae7a 100644 --- a/.github/workflows/backend.yaml +++ b/.github/workflows/backend.yaml @@ -14,6 +14,17 @@ on: - "backend/**" - ".github/workflows/backend.yaml" +env: + GCP_PROJECT_ID: atomify-ee7b5 + GCP_PROJECT_NUMBER: "917312770790" + FIREBASE_PROJECT_ID: atomify-ee7b5 + REGION: europe-west1 + SERVICE_NAME: atomify-api + IMAGE_NAME: atomify-api + DATABASE_URL: sqlite+aiosqlite:////data/atomify.db + GCS_BUCKET_NAME: atomify-user-files + CORS_ORIGINS: http://localhost:3000,https://andeplane.github.io + jobs: test: runs-on: ubuntu-latest @@ -52,5 +63,49 @@ jobs: - uses: actions/checkout@v4 - name: Build Docker image - run: docker build -t atomify-api:test ./backend + run: docker build -t ${{ env.IMAGE_NAME }}:test ./backend + + deploy: + needs: [test, docker] + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + + steps: + - uses: actions/checkout@v4 + + - name: Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.GCP_SA_KEY }} + + - name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v2 + + - name: Configure Docker for GCR + run: gcloud auth configure-docker + + - name: Build and push Docker image + run: | + IMAGE_TAG="gcr.io/${{ env.GCP_PROJECT_ID }}/${{ env.IMAGE_NAME }}:${{ github.sha }}" + docker build -t $IMAGE_TAG ./backend + docker push $IMAGE_TAG + echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV + - name: Deploy to Cloud Run + run: | + gcloud run deploy ${{ env.SERVICE_NAME }} \ + --image=${{ env.IMAGE_TAG }} \ + --region=${{ env.REGION }} \ + --platform=managed \ + --allow-unauthenticated \ + --service-account=${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }} \ + --set-env-vars="DATABASE_URL=${{ env.DATABASE_URL }},FIREBASE_PROJECT_ID=${{ env.FIREBASE_PROJECT_ID }},GCS_BUCKET_NAME=${{ env.GCS_BUCKET_NAME }},CORS_ORIGINS=${{ env.CORS_ORIGINS }}" \ + --memory=512Mi \ + --cpu=1 \ + --min-instances=0 \ + --max-instances=10 \ + --timeout=300 \ + --port=8000 diff --git a/backend/DEPLOYMENT.md b/backend/DEPLOYMENT.md new file mode 100644 index 00000000..7f856db6 --- /dev/null +++ b/backend/DEPLOYMENT.md @@ -0,0 +1,179 @@ +# Backend Deployment Guide + +## Overview + +The backend is deployed to Google Cloud Run automatically via GitHub Actions when changes are pushed to `main`. + +## Hardcoded Values (in workflow) + +- **GCP Project ID**: `atomify-ee7b5` +- **Firebase Project ID**: `atomify-ee7b5` (same as GCP) +- **Region**: `europe-west1` +- **Service Name**: `atomify-api` +- **Database URL**: `sqlite+aiosqlite:////data/atomify.db` (SQLite file path) +- **GCS Bucket Name**: `atomify-user-files` +- **CORS Origins**: `http://localhost:3000,https://andeplane.github.io` + +## Required GitHub Secrets + +Set these in your GitHub repository: **Settings → Secrets and variables → Actions** + +### 1. `GCP_SA_KEY` +- **Description**: Service account JSON key with Cloud Run Admin permissions +- **How to create**: + 1. Google Cloud Console → IAM & Admin → Service Accounts + 2. Create service account (e.g., `github-actions`) + 3. Grant roles: + - `Cloud Run Admin` + - `Service Account User` + - `Storage Admin` (for GCR/Artifact Registry) + 4. Create JSON key → Download → Copy entire JSON content + 5. Paste into GitHub secret + +### 2. `GCP_SERVICE_ACCOUNT_EMAIL` +- **Description**: Email of the service account that Cloud Run will use +- **Example**: `atomify-api@atomify-ee7b5.iam.gserviceaccount.com` +- **How to create**: + 1. Create service account for Cloud Run (e.g., `atomify-api`) + 2. Grant roles: + - `Storage Object Admin` (for GCS) + - `Firebase Admin SDK Administrator Service Agent` (for Firebase Auth) + 3. Copy the email address + +## Cloud Run Setup + +### 1. Enable APIs + +```bash +gcloud services enable \ + run.googleapis.com \ + cloudbuild.googleapis.com \ + containerregistry.googleapis.com \ + storage-api.googleapis.com +``` + +### 2. Create Service Account for Cloud Run + +```bash +gcloud iam service-accounts create atomify-api \ + --display-name="Atomify API Service Account" + +gcloud projects add-iam-policy-binding $PROJECT_ID \ + --member="serviceAccount:atomify-api@$PROJECT_ID.iam.gserviceaccount.com" \ + --role="roles/storage.objectAdmin" + +gcloud projects add-iam-policy-binding $PROJECT_ID \ + --member="serviceAccount:atomify-api@$PROJECT_ID.iam.gserviceaccount.com" \ + --role="roles/firebase.admin" +``` + +### 3. Create GCS Bucket + +**Note**: Billing must be enabled for the project first. + +```bash +gcloud storage buckets create gs://atomify-user-files \ + --project=atomify-ee7b5 \ + --location=europe-west1 + +gcloud storage buckets add-iam-policy-binding gs://atomify-user-files \ + --member="serviceAccount:atomify-api@atomify-ee7b5.iam.gserviceaccount.com" \ + --role="roles/storage.objectAdmin" +``` + +### 4. Set Up Cloud Run Volume (for SQLite) + +If using SQLite with a persistent volume: + +```bash +# Create a Cloud Storage bucket for the volume +gsutil mb -p $PROJECT_ID -l us-central1 gs://atomify-db-volume + +# Mount as volume in Cloud Run (done via gcloud run deploy or console) +``` + +**Note**: For production, consider using Cloud SQL (PostgreSQL) instead of SQLite. + +## Database Migrations + +Migrations are **NOT** run automatically in the container startup to avoid race conditions. + +### Option 1: Manual Migration (Recommended) + +Before deploying, run migrations manually: + +```bash +# Build and run migration container +docker build -t atomify-api:migrate ./backend +docker run --rm \ + -e DATABASE_URL="$DATABASE_URL" \ + atomify-api:migrate \ + alembic upgrade head +``` + +### Option 2: Cloud Run Job + +Create a Cloud Run Job for migrations: + +```bash +gcloud run jobs create atomify-api-migrate \ + --image=gcr.io/$PROJECT_ID/atomify-api:latest \ + --region=us-central1 \ + --set-env-vars="DATABASE_URL=$DATABASE_URL" \ + --command="alembic" \ + --args="upgrade,head" + +# Run before each deployment +gcloud run jobs execute atomify-api-migrate --region=us-central1 --wait +``` + +## Manual Deployment + +If you need to deploy manually: + +```bash +# Build and push +docker build -t gcr.io/atomify-ee7b5/atomify-api:latest ./backend +docker push gcr.io/atomify-ee7b5/atomify-api:latest + +# Deploy +gcloud run deploy atomify-api \ + --image=gcr.io/atomify-ee7b5/atomify-api:latest \ + --region=europe-west1 \ + --platform=managed \ + --allow-unauthenticated \ + --service-account=atomify-api@atomify-ee7b5.iam.gserviceaccount.com \ + --set-env-vars="DATABASE_URL=sqlite+aiosqlite:////data/atomify.db,FIREBASE_PROJECT_ID=atomify-ee7b5,GCS_BUCKET_NAME=atomify-user-files,CORS_ORIGINS=http://localhost:3000,https://andeplane.github.io" \ + --memory=512Mi \ + --cpu=1 \ + --port=8000 +``` + +## Monitoring + +- **Logs**: `gcloud run services logs read atomify-api --region=europe-west1` +- **Metrics**: Google Cloud Console → Cloud Run → atomify-api +- **Health Check**: `https://atomify-api-xxx.run.app/health` + +## Troubleshooting + +### Service won't start +- Check logs: `gcloud run services logs read atomify-api --region=us-central1` +- Verify environment variables are set correctly +- Check service account permissions + +### Database connection fails +- Verify `DATABASE_URL` is correct +- For Cloud SQL: Ensure Cloud SQL Admin API is enabled +- For SQLite volume: Ensure volume is mounted at `/data` + +### Firebase Auth fails +- Verify `FIREBASE_PROJECT_ID` matches your Firebase project +- Check service account has Firebase Admin permissions +- Ensure Firebase Admin SDK is initialized correctly + +### GCS access fails +- Verify `GCS_BUCKET_NAME` exists +- Check service account has `Storage Object Admin` role +- Verify bucket IAM allows the service account + From f7384c0d1df9063bbec9c8051d8b91ced441a717 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:36:42 +0100 Subject: [PATCH 2/9] fix(backend): move app env vars out of workflow-level scope CORS_ORIGINS was causing pydantic-settings to fail during tests because it tried to parse the comma-separated string as JSON. --- .github/workflows/backend.yaml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml index aef7ae7a..1df8f078 100644 --- a/.github/workflows/backend.yaml +++ b/.github/workflows/backend.yaml @@ -15,15 +15,11 @@ on: - ".github/workflows/backend.yaml" env: + # GCP/Deploy settings (used by deploy job) GCP_PROJECT_ID: atomify-ee7b5 - GCP_PROJECT_NUMBER: "917312770790" - FIREBASE_PROJECT_ID: atomify-ee7b5 REGION: europe-west1 SERVICE_NAME: atomify-api IMAGE_NAME: atomify-api - DATABASE_URL: sqlite+aiosqlite:////data/atomify.db - GCS_BUCKET_NAME: atomify-user-files - CORS_ORIGINS: http://localhost:3000,https://andeplane.github.io jobs: test: @@ -102,7 +98,7 @@ jobs: --platform=managed \ --allow-unauthenticated \ --service-account=${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }} \ - --set-env-vars="DATABASE_URL=${{ env.DATABASE_URL }},FIREBASE_PROJECT_ID=${{ env.FIREBASE_PROJECT_ID }},GCS_BUCKET_NAME=${{ env.GCS_BUCKET_NAME }},CORS_ORIGINS=${{ env.CORS_ORIGINS }}" \ + --set-env-vars="DATABASE_URL=sqlite+aiosqlite:////data/atomify.db,FIREBASE_PROJECT_ID=atomify-ee7b5,GCS_BUCKET_NAME=atomify-user-files,CORS_ORIGINS=http://localhost:3000,https://andeplane.github.io" \ --memory=512Mi \ --cpu=1 \ --min-instances=0 \ From f017005237a40bf0c5edc4d7f85bf443281a16e6 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:38:42 +0100 Subject: [PATCH 3/9] chore(backend): add .env config file Contains non-secret configuration values. Service account keys are gitignored. --- backend/.env | 21 +++++++++++++++++++++ backend/.gitignore | 6 +++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 backend/.env diff --git a/backend/.env b/backend/.env new file mode 100644 index 00000000..e6b008c8 --- /dev/null +++ b/backend/.env @@ -0,0 +1,21 @@ +# API Settings +API_HOST=0.0.0.0 +API_PORT=8000 +DEBUG=true + +# Database (SQLite) +DATABASE_URL=sqlite+aiosqlite:///./atomify.db + +# Firebase +FIREBASE_PROJECT_ID=atomify-ee7b5 + +# Google Cloud credentials (for GCS and Firebase Admin) +# Option 1: Use gcloud auth application-default login (no file needed) +# Option 2: Point to a service account key file +# GOOGLE_APPLICATION_CREDENTIALS=./service-account.json + +# Google Cloud Storage +GCS_BUCKET_NAME=atomify-user-files + +# CORS (comma-separated origins) +CORS_ORIGINS=http://localhost:3000,http://localhost:5173,https://andeplane.github.io diff --git a/backend/.gitignore b/backend/.gitignore index e0b75752..336968d5 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -12,7 +12,11 @@ venv/ *.sqlite # Environment -.env +# .env.local # Use for local overrides if needed + +# Service account keys (NEVER commit these) +*-key.json +service-account.json # IDE .idea/ From 233bdf50692e2fe70a799acada5a423c65d29fb9 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:39:29 +0100 Subject: [PATCH 4/9] Update backend/DEPLOYMENT.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- backend/DEPLOYMENT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/DEPLOYMENT.md b/backend/DEPLOYMENT.md index 7f856db6..c604726d 100644 --- a/backend/DEPLOYMENT.md +++ b/backend/DEPLOYMENT.md @@ -87,7 +87,7 @@ If using SQLite with a persistent volume: ```bash # Create a Cloud Storage bucket for the volume -gsutil mb -p $PROJECT_ID -l us-central1 gs://atomify-db-volume +gsutil mb -p $PROJECT_ID -l europe-west1 gs://atomify-db-volume # Mount as volume in Cloud Run (done via gcloud run deploy or console) ``` From 661a662d5e3abea4789c50e35b38765f59928fe7 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:43:16 +0100 Subject: [PATCH 5/9] feat(backend): mount GCS bucket for SQLite persistence Uses Cloud Storage FUSE to mount gs://atomify-db at /data for persistent SQLite storage on Cloud Run. --- .github/workflows/backend.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml index 1df8f078..6ba77c5b 100644 --- a/.github/workflows/backend.yaml +++ b/.github/workflows/backend.yaml @@ -96,9 +96,12 @@ jobs: --image=${{ env.IMAGE_TAG }} \ --region=${{ env.REGION }} \ --platform=managed \ + --execution-environment=gen2 \ --allow-unauthenticated \ --service-account=${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }} \ --set-env-vars="DATABASE_URL=sqlite+aiosqlite:////data/atomify.db,FIREBASE_PROJECT_ID=atomify-ee7b5,GCS_BUCKET_NAME=atomify-user-files,CORS_ORIGINS=http://localhost:3000,https://andeplane.github.io" \ + --add-volume=name=db-volume,type=cloud-storage,bucket=atomify-db \ + --add-volume-mount=volume=db-volume,mount-path=/data \ --memory=512Mi \ --cpu=1 \ --min-instances=0 \ From 2a1f01d3f6af25f3c3da64d7ddf51672e1a8adef Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:51:12 +0100 Subject: [PATCH 6/9] docs(backend): fix DEPLOYMENT.md issues from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix region inconsistencies (us-central1 → europe-west1) - Update service account roles (Storage Admin → Storage Object Admin) - Remove unnecessary Firebase role (token verification uses public keys) - Document GCS FUSE mount for SQLite persistence - Add volume mount flags to manual deploy command --- backend/DEPLOYMENT.md | 67 +++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/backend/DEPLOYMENT.md b/backend/DEPLOYMENT.md index c604726d..f3024e83 100644 --- a/backend/DEPLOYMENT.md +++ b/backend/DEPLOYMENT.md @@ -19,26 +19,19 @@ The backend is deployed to Google Cloud Run automatically via GitHub Actions whe Set these in your GitHub repository: **Settings → Secrets and variables → Actions** ### 1. `GCP_SA_KEY` -- **Description**: Service account JSON key with Cloud Run Admin permissions -- **How to create**: - 1. Google Cloud Console → IAM & Admin → Service Accounts - 2. Create service account (e.g., `github-actions`) - 3. Grant roles: - - `Cloud Run Admin` - - `Service Account User` - - `Storage Admin` (for GCR/Artifact Registry) - 4. Create JSON key → Download → Copy entire JSON content - 5. Paste into GitHub secret +- **Description**: Service account JSON key for CI/CD deployment +- **Service account**: `github-actions@atomify-ee7b5.iam.gserviceaccount.com` +- **Roles**: + - `Cloud Run Admin` — deploy services + - `Service Account User` — impersonate runtime SA + - `Storage Object Admin` — push Docker images to GCR ### 2. `GCP_SERVICE_ACCOUNT_EMAIL` -- **Description**: Email of the service account that Cloud Run will use -- **Example**: `atomify-api@atomify-ee7b5.iam.gserviceaccount.com` -- **How to create**: - 1. Create service account for Cloud Run (e.g., `atomify-api`) - 2. Grant roles: - - `Storage Object Admin` (for GCS) - - `Firebase Admin SDK Administrator Service Agent` (for Firebase Auth) - 3. Copy the email address +- **Description**: Email of the service account that Cloud Run uses at runtime +- **Value**: `atomify-api@atomify-ee7b5.iam.gserviceaccount.com` +- **Roles**: + - `Storage Object Admin` — access GCS buckets +- **Note**: No Firebase role needed — token verification uses public keys ## Cloud Run Setup @@ -58,13 +51,9 @@ gcloud services enable \ gcloud iam service-accounts create atomify-api \ --display-name="Atomify API Service Account" -gcloud projects add-iam-policy-binding $PROJECT_ID \ - --member="serviceAccount:atomify-api@$PROJECT_ID.iam.gserviceaccount.com" \ +gcloud projects add-iam-policy-binding atomify-ee7b5 \ + --member="serviceAccount:atomify-api@atomify-ee7b5.iam.gserviceaccount.com" \ --role="roles/storage.objectAdmin" - -gcloud projects add-iam-policy-binding $PROJECT_ID \ - --member="serviceAccount:atomify-api@$PROJECT_ID.iam.gserviceaccount.com" \ - --role="roles/firebase.admin" ``` ### 3. Create GCS Bucket @@ -81,18 +70,23 @@ gcloud storage buckets add-iam-policy-binding gs://atomify-user-files \ --role="roles/storage.objectAdmin" ``` -### 4. Set Up Cloud Run Volume (for SQLite) +### 4. Create Database Bucket (for SQLite persistence) -If using SQLite with a persistent volume: +SQLite is persisted via GCS FUSE mount: ```bash -# Create a Cloud Storage bucket for the volume -gsutil mb -p $PROJECT_ID -l europe-west1 gs://atomify-db-volume +# Create bucket for SQLite database +gcloud storage buckets create gs://atomify-db \ + --project=atomify-ee7b5 \ + --location=europe-west1 -# Mount as volume in Cloud Run (done via gcloud run deploy or console) +# Grant runtime service account access +gcloud storage buckets add-iam-policy-binding gs://atomify-db \ + --member="serviceAccount:atomify-api@atomify-ee7b5.iam.gserviceaccount.com" \ + --role="roles/storage.objectAdmin" ``` -**Note**: For production, consider using Cloud SQL (PostgreSQL) instead of SQLite. +The deploy command mounts this bucket at `/data` using Cloud Storage FUSE. ## Database Migrations @@ -117,14 +111,14 @@ Create a Cloud Run Job for migrations: ```bash gcloud run jobs create atomify-api-migrate \ - --image=gcr.io/$PROJECT_ID/atomify-api:latest \ - --region=us-central1 \ + --image=gcr.io/atomify-ee7b5/atomify-api:latest \ + --region=europe-west1 \ --set-env-vars="DATABASE_URL=$DATABASE_URL" \ --command="alembic" \ --args="upgrade,head" # Run before each deployment -gcloud run jobs execute atomify-api-migrate --region=us-central1 --wait +gcloud run jobs execute atomify-api-migrate --region=europe-west1 --wait ``` ## Manual Deployment @@ -141,9 +135,12 @@ gcloud run deploy atomify-api \ --image=gcr.io/atomify-ee7b5/atomify-api:latest \ --region=europe-west1 \ --platform=managed \ + --execution-environment=gen2 \ --allow-unauthenticated \ --service-account=atomify-api@atomify-ee7b5.iam.gserviceaccount.com \ --set-env-vars="DATABASE_URL=sqlite+aiosqlite:////data/atomify.db,FIREBASE_PROJECT_ID=atomify-ee7b5,GCS_BUCKET_NAME=atomify-user-files,CORS_ORIGINS=http://localhost:3000,https://andeplane.github.io" \ + --add-volume=name=db-volume,type=cloud-storage,bucket=atomify-db \ + --add-volume-mount=volume=db-volume,mount-path=/data \ --memory=512Mi \ --cpu=1 \ --port=8000 @@ -158,7 +155,7 @@ gcloud run deploy atomify-api \ ## Troubleshooting ### Service won't start -- Check logs: `gcloud run services logs read atomify-api --region=us-central1` +- Check logs: `gcloud run services logs read atomify-api --region=europe-west1` - Verify environment variables are set correctly - Check service account permissions @@ -169,7 +166,7 @@ gcloud run deploy atomify-api \ ### Firebase Auth fails - Verify `FIREBASE_PROJECT_ID` matches your Firebase project -- Check service account has Firebase Admin permissions +- Token verification uses public keys (no special permissions needed) - Ensure Firebase Admin SDK is initialized correctly ### GCS access fails From 81ba1a5d9fdb8e3f594c1a9549d9f81c79225c60 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:56:33 +0100 Subject: [PATCH 7/9] fix(backend): use JSON format for CORS_ORIGINS in .env pydantic-settings parses list fields as JSON, not comma-separated. --- backend/.env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/.env b/backend/.env index e6b008c8..8cdadc8e 100644 --- a/backend/.env +++ b/backend/.env @@ -17,5 +17,5 @@ FIREBASE_PROJECT_ID=atomify-ee7b5 # Google Cloud Storage GCS_BUCKET_NAME=atomify-user-files -# CORS (comma-separated origins) -CORS_ORIGINS=http://localhost:3000,http://localhost:5173,https://andeplane.github.io +# CORS (JSON array format) +CORS_ORIGINS=["http://localhost:3000","http://localhost:5173","https://andeplane.github.io"] From 5573495030738af0d906e8459b13aaeeca56bc18 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:57:07 +0100 Subject: [PATCH 8/9] fix(backend): use env-vars-file for CORS_ORIGINS in deploy CORS_ORIGINS needs JSON array format for pydantic-settings. --- .github/workflows/backend.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml index 6ba77c5b..48803b05 100644 --- a/.github/workflows/backend.yaml +++ b/.github/workflows/backend.yaml @@ -90,6 +90,15 @@ jobs: docker push $IMAGE_TAG echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV + - name: Create env vars file + run: | + cat > /tmp/env-vars.yaml << 'EOF' + DATABASE_URL: "sqlite+aiosqlite:////data/atomify.db" + FIREBASE_PROJECT_ID: "atomify-ee7b5" + GCS_BUCKET_NAME: "atomify-user-files" + CORS_ORIGINS: '["http://localhost:3000","https://andeplane.github.io"]' + EOF + - name: Deploy to Cloud Run run: | gcloud run deploy ${{ env.SERVICE_NAME }} \ @@ -99,7 +108,7 @@ jobs: --execution-environment=gen2 \ --allow-unauthenticated \ --service-account=${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }} \ - --set-env-vars="DATABASE_URL=sqlite+aiosqlite:////data/atomify.db,FIREBASE_PROJECT_ID=atomify-ee7b5,GCS_BUCKET_NAME=atomify-user-files,CORS_ORIGINS=http://localhost:3000,https://andeplane.github.io" \ + --env-vars-file=/tmp/env-vars.yaml \ --add-volume=name=db-volume,type=cloud-storage,bucket=atomify-db \ --add-volume-mount=volume=db-volume,mount-path=/data \ --memory=512Mi \ From cdac78fd508099bafa17774d0d786e1181fe1ce0 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Mon, 22 Dec 2025 10:58:52 +0100 Subject: [PATCH 9/9] fix(backend): fix env-vars.yaml generation in workflow Remove leading spaces from heredoc that made YAML invalid. --- .github/workflows/backend.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml index 48803b05..4a6e1dce 100644 --- a/.github/workflows/backend.yaml +++ b/.github/workflows/backend.yaml @@ -92,12 +92,7 @@ jobs: - name: Create env vars file run: | - cat > /tmp/env-vars.yaml << 'EOF' - DATABASE_URL: "sqlite+aiosqlite:////data/atomify.db" - FIREBASE_PROJECT_ID: "atomify-ee7b5" - GCS_BUCKET_NAME: "atomify-user-files" - CORS_ORIGINS: '["http://localhost:3000","https://andeplane.github.io"]' - EOF + printf 'DATABASE_URL: "sqlite+aiosqlite:////data/atomify.db"\nFIREBASE_PROJECT_ID: "atomify-ee7b5"\nGCS_BUCKET_NAME: "atomify-user-files"\nCORS_ORIGINS: '\''["http://localhost:3000","https://andeplane.github.io"]'\''\n' > /tmp/env-vars.yaml - name: Deploy to Cloud Run run: |