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: | 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