Skip to content

Commit cc62213

Browse files
committed
fix: CD to sandbox/live GitOps, remove .env.production, SPA catch-all, manual deploy
- Deploy: Downstream: add permissions (contents, actions, pull-requests), add workflow_dispatch target (both|sandbox|live) for manual deploy; CD to sandbox on develop, live on release; manual run opens PRs to cluster repos - Remove frontend/.env.production and VITE_API_BASE_URL from .env (relative URLs) - SPA catch-all: always register, serve index.html at request time or 404 - Docs: README/CLAUDE/MIGRATION/DEPLOY_RESOLUTION_STEPS and PR body
1 parent 38f61eb commit cc62213

9 files changed

Lines changed: 65 additions & 20 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
## Description
2+
3+
Single PR that fixes deploy/API/CI for sandbox + live.
4+
5+
**Included:**
6+
- Deploy/API/CI for sandbox and live: relative API URLs, frontend lint CI, resolution steps doc
7+
- **Closes #450** – fix/local-compose (README, Docker Compose healthchecks, backend STATICFILES) is fully included in this branch
8+
- **Closes #452** – removed `.env.production` (not needed; frontend uses relative API URLs for sandbox/live)
9+
10+
**Frontend and environment:** The frontend uses relative API URLs (`baseURL = ""`), so one image works for both environments: when running on **sandbox** (balancer.sandbox.k8s.phl.io) it calls that host; when running on **live** (balancerproject.org) it calls that host. No env-specific build or config required.
11+
12+
**Not closed:** #451 (sanitizer) – unrelated; left open.
13+
14+
## Related
15+
16+
- Closes #450
17+
- Closes #452
18+
19+
## Reviewers
20+
21+
@chris (for deploy/secrets follow-up; see docs/DEPLOY_RESOLUTION_STEPS.md)

.github/workflows/deploy-downstream.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: "Deploy: Downstream Clusters"
22

3+
# CD: push to develop -> Containers: Publish -> this workflow -> PR to cfp-sandbox-cluster.
4+
# Live: publish release -> Containers: Publish -> this workflow -> PR to cfp-live-cluster.
5+
# Manual: Run workflow_dispatch with tag (and optional target) to open deploy PRs.
6+
# Requires BOT_GITHUB_TOKEN with write access to CodeForPhilly/cfp-sandbox-cluster and cfp-live-cluster.
37
on:
48
workflow_run:
59
workflows: ["Containers: Publish"]
@@ -8,15 +12,29 @@ on:
812
workflow_dispatch:
913
inputs:
1014
tag:
11-
description: 'Image tag to deploy (e.g. 1.1.0)'
15+
description: 'Image tag to deploy (e.g. 1.1.0 or dev-abc1234)'
1216
required: true
1317
default: 'latest'
18+
target:
19+
description: 'Which cluster(s) to open deploy PRs for'
20+
required: false
21+
default: 'both'
22+
type: choice
23+
options:
24+
- both
25+
- sandbox
26+
- live
27+
28+
permissions:
29+
contents: read
30+
actions: read
31+
pull-requests: write
1432

1533
jobs:
1634
update-sandbox:
1735
name: Update Sandbox Cluster
1836
runs-on: ubuntu-latest
19-
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'develop') }}
37+
if: ${{ (github.event_name == 'workflow_dispatch' && (inputs.target == 'both' || inputs.target == 'sandbox')) || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'develop') }}
2038
outputs:
2139
tag: ${{ steps.get_tag.outputs.TAG }}
2240
steps:
@@ -65,7 +83,7 @@ jobs:
6583
update-live:
6684
name: Update Live Cluster
6785
runs-on: ubuntu-latest
68-
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'release') }}
86+
if: ${{ (github.event_name == 'workflow_dispatch' && (inputs.target == 'both' || inputs.target == 'live')) || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'release') }}
6987
steps:
7088
- name: Checkout App
7189
uses: actions/checkout@v4

CLAUDE.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,7 @@ Routes defined in `src/routes/routes.tsx`:
210210

211211
### Environment Configuration
212212
- **Development**: `config/env/dev.env` (used by Docker Compose)
213-
- **Frontend Production**: `frontend/.env.production`
214-
- Contains `VITE_API_BASE_URL` for production API endpoint
213+
- **Frontend**: Production uses relative API URLs (no `.env.production`); local dev uses `frontend/.env` (e.g. `VITE_API_BASE_URL` for proxy).
215214
- **Never commit** actual API keys - use `.env.example` as template
216215
- Django `SECRET_KEY` should be a long random string in production (not "foo")
217216

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ To run the application, you need to configure your environment variables.
7676
> **⚠️ SECURITY WARNING**: Never commit `config/env/dev.env` to version control. It is already ignored by `.gitignore`.
7777
7878
2. **Frontend Config**:
79-
* The frontend uses `frontend/.env` (or `.env.production` for builds).
80-
* Key variable: `VITE_API_BASE_URL` (Defaults to `http://localhost:8000` for local dev).
79+
* The frontend uses `frontend/.env` for local dev only (e.g. `VITE_API_BASE_URL=http://localhost:8000` for the Vite proxy).
80+
* Production builds use relative API URLs (no `.env.production` or API base URL needed); the same image works for sandbox and live.
8181

8282
---
8383

docs/DEPLOY_RESOLUTION_STEPS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ Deploy Downstream will open a PR in **CodeForPhilly/cfp-sandbox-cluster** to upd
3333

3434
## Step 4 – Live (production)
3535

36-
Live deploys only on **release** (see `.github/workflows/deploy-downstream.yml`: `workflow_run.event == 'release'`).
36+
Live deploys automatically when a **release** is published (Containers: Publish runs, then Deploy: Downstream opens a PR to cfp-live-cluster). You can also **manually** open deploy PRs after merging to main:
3737

38-
- **Action**: Create a release from `main` (or the intended tag) so **Deploy: Downstream** runs for live and opens a PR in **CodeForPhilly/cfp-live-cluster**. Merge that PR. Verify **https://balancerproject.org** and that API calls go to `https://balancerproject.org/api/...`.
38+
- **Action**: In **Actions → Deploy: Downstream → Run workflow**, choose **workflow_dispatch**, enter the image tag (e.g. `v1.2.0` or `dev-abc1234`), and set **target** to `live` (or `both` for sandbox + live). This opens the deploy PR(s) in the GitOps repos. Then create a release from `main` if you want the usual release flow, or just merge the opened deploy PR. Verify **https://balancerproject.org** and that API calls go to `https://balancerproject.org/api/...`.
3939
- **Ping**: @chris or release manager for creating the release and merging the live deploy PR.
4040

4141
---

docs/MIGRATION_PDF_AUTH.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,7 @@ If issues occur:
278278

279279
## Environment Variables
280280

281-
No new environment variables required. Uses existing:
282-
- `VITE_API_BASE_URL` - Frontend API base URL
281+
No new environment variables required. Production uses relative API URLs (no env needed). Local dev may use `VITE_API_BASE_URL` in `frontend/.env` for the Vite proxy.
283282

284283
## Known Issues / Limitations
285284

frontend/.env

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
# VITE_API_BASE_URL=https://balancertestsite.com/
2-
VITE_API_BASE_URL=http://localhost:8000
1+
# Optional: add VITE_* vars here if needed. None required for docker-compose;
2+
# the app uses relative API URLs and vite.config.ts proxies /api to the backend.

frontend/.env.production

Lines changed: 0 additions & 1 deletion
This file was deleted.

server/balancer_backend/urls.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,19 @@
5353

5454
import os
5555
from django.conf import settings
56+
from django.http import HttpResponseNotFound
5657

57-
# Add a catch-all URL pattern for handling SPA (Single Page Application) routing
58-
# Serve 'index.html' for any unmatched URL (must come after /api/ routes)
59-
if os.path.exists(os.path.join(settings.BASE_DIR, "build", "index.html")):
60-
urlpatterns += [
61-
re_path(r"^(?!api|admin|static).*$", TemplateView.as_view(template_name="index.html")),
62-
]
58+
59+
def spa_fallback(request):
60+
"""Serve index.html for SPA routing when build is present; otherwise 404."""
61+
index_path = os.path.join(settings.BASE_DIR, "build", "index.html")
62+
if os.path.exists(index_path):
63+
return TemplateView.as_view(template_name="index.html")(request)
64+
return HttpResponseNotFound()
65+
66+
67+
# Always register SPA catch-all so production serves the frontend regardless of
68+
# URL config load order. At request time we serve index.html if build exists, else 404.
69+
urlpatterns += [
70+
re_path(r"^(?!api|admin|static).*$", spa_fallback),
71+
]

0 commit comments

Comments
 (0)