From a420932539f9aa9262793d23108c6397fd42f4a3 Mon Sep 17 00:00:00 2001 From: Amr Gaber Date: Tue, 16 Jun 2026 16:15:47 -0500 Subject: [PATCH 1/2] docs: reflect live CI/CD now that Phase D shipped Auto-deploy (GitHub Actions + Workload Identity Federation) has been live since #15; update the docs that still described it as pending. - README: replace the "CI/CD tracked in #5" stub with a Continuous deployment section (WIF auth, runner-side docker build instead of Cloud Build, migrations not run in CI); label the manual deploy path a fallback. - deploy.sh: header now frames the script as the manual fallback rather than a stand-in until Phase D. --- README.md | 13 ++++++++++--- scripts/deploy.sh | 8 +++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9ca0317..09b916c 100644 --- a/README.md +++ b/README.md @@ -231,9 +231,9 @@ uv run alembic revision --autogenerate -m "description" The API runs on Cloud Run in GCP project `treepolitics-prod` (region `us-east1`), backed by a Cloud SQL Postgres instance and Secret Manager. -### Deploy a new revision +### Deploy a new revision (manual fallback) -From a clean working tree on `main` (set `GCP_ACCOUNT` to your gcloud deploy account): +Merges to `main` auto-deploy (see [Continuous deployment](#continuous-deployment) below); use this manual path only for out-of-band pushes. From a clean working tree on `main` (set `GCP_ACCOUNT` to your gcloud deploy account): ```bash GCP_ACCOUNT=you@example.com ./scripts/deploy.sh @@ -265,7 +265,14 @@ The DB user password is in Secret Manager (not committed). - **Secrets** in Secret Manager: `DATABASE_URL`, `SECRET_KEY`. - **Custom domain** `api.treepolitics.net` via Cloud Run domain mapping. -CI/CD (auto-deploy on merge to `main`) is tracked in [issue #5](https://github.com/ag-tech-group/treepolitics-api/issues/5). +### Continuous deployment + +Every merge to `main` auto-deploys to Cloud Run via GitHub Actions ([`.github/workflows/deploy.yml`](.github/workflows/deploy.yml)), so `scripts/deploy.sh` is only needed for out-of-band pushes. + +- **Auth — Workload Identity Federation, no stored keys.** The workflow mints a short-lived OIDC token that impersonates `github-deployer@treepolitics-prod.iam.gserviceaccount.com` (pool `github-pool`, provider `github-provider`, locked to this repo). +- **Build on the runner, not Cloud Build.** The image is built with `docker build` on the runner and `docker push`ed to Artifact Registry. Cloud Build is intentionally avoided here: its log streaming requires a project-level Viewer role that the scoped deploy SA deliberately lacks. +- **Deploy.** `gcloud run deploy` with the same flags as `scripts/deploy.sh`. +- **Migrations are not run in CI.** Apply them first (see [Run migrations against prod](#run-migrations-against-prod)) before merging a schema-changing revision. ## Testing diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 51ba4bd..4d561a0 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,9 +1,11 @@ #!/usr/bin/env bash # Manual deploy of the Treepolitics API to Cloud Run. # -# Until Phase D (#5) wires up GitHub Actions auto-deploy, run this from a clean -# working tree to ship a new revision. Migrations are NOT applied here — run -# them separately via cloud-sql-proxy (see README "Production Deployment"). +# Auto-deploy is live: GitHub Actions ships every merge to `main` to Cloud Run +# via Workload Identity Federation (see .github/workflows/deploy.yml). This +# script is the manual fallback — run it from a clean working tree to push a +# revision out-of-band. Migrations are NOT applied here — run them separately +# via cloud-sql-proxy (see README "Production Deployment"). set -euo pipefail From d7111e7a85c991c31f449b43bbc51afd3d445a5e Mon Sep 17 00:00:00 2001 From: Amr Gaber Date: Tue, 16 Jun 2026 16:30:42 -0500 Subject: [PATCH 2/2] ci: bump deploy actions to Node 24 runtime GitHub is deprecating the Node 20 action runtime; the deploy workflow emitted a deprecation warning on every run. Bump the three actions to the first major version that ships on Node 24: - actions/checkout v4 -> v5 - google-github-actions/auth v2 -> v3 - google-github-actions/setup-gcloud v2 -> v3 Verified each v* declares `runs.using: node24` and still exposes the inputs we pass (auth keeps workload_identity_provider + service_account; the other two take none from us). No workflow-logic change. --- .github/workflows/deploy.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9ab4c0a..d74b8ea 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,15 +25,15 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Authenticate to GCP (Workload Identity Federation) - uses: google-github-actions/auth@v2 + uses: google-github-actions/auth@v3 with: workload_identity_provider: projects/825485923973/locations/global/workloadIdentityPools/github-pool/providers/github-provider service_account: github-deployer@treepolitics-prod.iam.gserviceaccount.com - - uses: google-github-actions/setup-gcloud@v2 + - uses: google-github-actions/setup-gcloud@v3 - name: Build & push image run: |