Skip to content

Commit d178f12

Browse files
Merge pull request #89 from richardthe3rd/claude/preview-domain-cicd-01NfxMDkhnoKRY97S2r5tX2U
Setup staging domain for main branch merges
2 parents 9c0202a + 9fa42f0 commit d178f12

5 files changed

Lines changed: 107 additions & 42 deletions

File tree

.github/workflows/build-deploy.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,20 +257,22 @@ jobs:
257257
name: web-build
258258
path: build/web
259259

260-
- name: Deploy Preview to Cloudflare Pages
260+
- name: Deploy to Cloudflare Pages (Staging/PR Previews)
261261
id: deploy
262262
uses: cloudflare/wrangler-action@v3
263263
with:
264264
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
265265
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
266-
command: pages deploy build/web --project-name=cambeerfestival --branch=${{ github.head_ref || github.ref_name }}
266+
command: pages deploy build/web --project-name=staging-cambeerfestival --branch=${{ github.head_ref || github.ref_name }}
267267

268268
- name: Comment PR with Preview URL
269269
if: github.event_name == 'pull_request'
270270
uses: actions/github-script@v7
271271
with:
272272
script: |
273-
const previewUrl = '${{ steps.deploy.outputs.deployment-url }}';
273+
const aliasUrl = '${{ steps.deploy.outputs.pages-deployment-alias-url }}';
274+
const deployUrl = '${{ steps.deploy.outputs.deployment-url }}';
275+
const previewUrl = aliasUrl || deployUrl;
274276
const comment = `## 🚀 Cloudflare Pages Preview
275277
276278
Your preview deployment is ready!

.github/workflows/release-web.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,4 @@ jobs:
8282
with:
8383
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
8484
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
85-
command: pages deploy build/web --project-name=cambeerfestival --branch=main
85+
command: pages deploy build/web --project-name=cambeerfestival --branch=release

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
A Flutter app for browsing beers, ciders, meads, and more at the Cambridge Beer Festival.
77

88
**Production**: [https://cambeerfestival.app](https://cambeerfestival.app)
9-
**Staging**: [https://richardthe3rd.github.io/cambridge-beer-festival-app/](https://richardthe3rd.github.io/cambridge-beer-festival-app/)
9+
**Staging**: [https://staging.cambeerfestival.app](https://staging.cambeerfestival.app)
10+
**Development**: [https://richardthe3rd.github.io/cambridge-beer-festival-app/](https://richardthe3rd.github.io/cambridge-beer-festival-app/)
1011

1112
## Features
1213

@@ -140,17 +141,19 @@ The app is deployed to multiple environments:
140141

141142
- **Production** (Cloudflare Pages): [cambeerfestival.app](https://cambeerfestival.app)
142143
- Deployed on version tags (e.g., `v2025.12.0`)
144+
- Uses Cloudflare Pages project `cambeerfestival`, branch `release`
143145
- Workflow: `.github/workflows/release-web.yml`
144-
- **Staging** (Cloudflare Pages): `main.cambeerfestival.pages.dev`
145-
- Stable preview environment
146+
- **Staging** (Cloudflare Pages): [staging.cambeerfestival.app](https://staging.cambeerfestival.app)
147+
- Stable staging environment
146148
- Deployed automatically on push to `main`
149+
- Uses Cloudflare Pages project `cambeerfestival-staging`, branch `main`
147150
- Workflow: `.github/workflows/build-deploy.yml` (deploy-web-preview job)
148151
- **Development** (GitHub Pages): [richardthe3rd.github.io/cambridge-beer-festival-app](https://richardthe3rd.github.io/cambridge-beer-festival-app/)
149152
- Alternative development environment
150153
- Deployed automatically on push to `main`
151154
- Workflow: `.github/workflows/build-deploy.yml` (deploy-web job)
152155
- **PR Previews** (Cloudflare Pages): Unique URL per pull request
153-
- Each PR gets its own preview environment
156+
- Each PR gets its own preview environment (e.g., `<branch>.cambeerfestival-staging.pages.dev`)
154157
- Preview URL posted as comment on the PR
155158
- Workflow: `.github/workflows/build-deploy.yml` (deploy-web-preview job)
156159

cloudflare-worker/worker.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const FESTIVALS_CACHE_CONTROL = 'no-cache, must-revalidate';
2222
const ALLOWED_ORIGINS = [
2323
'https://richardthe3rd.github.io',
2424
'https://cambeerfestival.app',
25+
'https://staging.cambeerfestival.app',
2526
'http://localhost:8080',
2627
'http://localhost:3000',
2728
'http://127.0.0.1:8080',

docs/CLOUDFLARE_PAGES_SETUP.md

Lines changed: 93 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,29 @@ This document explains how to set up Cloudflare Pages deployment for the Cambrid
88
99
## Overview
1010

11-
The app has two deployment targets:
11+
The app uses **two separate Cloudflare Pages projects** for clean separation between production and staging:
1212

13-
1. **GitHub Pages** (Development/Staging): `richardthe3rd.github.io/cambridge-beer-festival-app/`
14-
2. **Cloudflare Pages** (Production): `cambeerfestival.app`
13+
### Cloudflare Pages Projects
14+
15+
**Project 1: `cambeerfestival`** (Production only)
16+
- Production branch: `release`
17+
- Deploys: Git tags (e.g., `v2025.12.0`)
18+
- Custom domain: `cambeerfestival.app`
19+
20+
**Project 2: `cambeerfestival-staging`** (Staging + PR previews)
21+
- Production branch: `main` (serves staging)
22+
- Preview branches: PR branches (serve PR previews)
23+
- Deploys: Git main + all PRs
24+
- Custom domain: `staging.cambeerfestival.app`
25+
26+
### Deployment Architecture
27+
28+
| Git Event | CF Project | CF Branch | URL | Purpose |
29+
|-----------|------------|-----------|-----|---------|
30+
| Version tag | `cambeerfestival` | `release` | `cambeerfestival.app` | Production |
31+
| Push to `main` | `cambeerfestival-staging` | `main` | `staging.cambeerfestival.app` | Staging |
32+
| Pull Request | `cambeerfestival-staging` | `<branch>` | `<branch>.cambeerfestival-staging.pages.dev` | PR previews |
33+
| Push to `main` | GitHub Pages | N/A | `richardthe3rd.github.io/...` | Development |
1534

1635
## Prerequisites
1736

@@ -21,32 +40,36 @@ The app has two deployment targets:
2140

2241
## Cloudflare Configuration
2342

24-
### 1. Create Cloudflare Pages Project
43+
### 1. Create Cloudflare Pages Projects
44+
45+
You need **two separate Cloudflare Pages projects**:
46+
- `cambeerfestival` (production)
47+
- `cambeerfestival-staging` (staging/previews)
2548

26-
**Option A: Let GitHub Actions Create the Project (Easiest)**
49+
**Option A: Let GitHub Actions Create the Projects (Easiest)**
2750

28-
The GitHub Actions workflow will automatically create the Cloudflare Pages project on the first deployment. You can skip this step and jump to step 2 (Get Account ID) and step 3 (Create API Token).
51+
Both projects will be automatically created on their first deployment. You can skip this step and jump to step 2 (Get Account ID) and step 3 (Create API Token).
2952

30-
When the workflow runs, it will create a project named `cambeerfestival` automatically.
53+
- First push to `main` will create `cambeerfestival-staging`
54+
- First git tag will create `cambeerfestival`
3155

32-
**Option B: Create Project Manually**
56+
**Option B: Create Projects Manually**
3357

34-
If you prefer to create the project manually first:
58+
If you prefer to create the projects manually first:
3559

60+
**For Production Project:**
3661
1. Log in to [Cloudflare Dashboard](https://dash.cloudflare.com/)
3762
2. Navigate to **Workers & Pages**
38-
3. Click **Create application** or **Create**
39-
4. Choose **Pages** tab
40-
5. Click **Connect to Git** (you can set this up or skip automatic deployments)
41-
- OR use **Upload assets** if available
42-
6. If using Connect to Git:
43-
- You can connect to your repository but disable automatic deployments
44-
- GitHub Actions will handle deployments instead
45-
7. Set **Project name**: `cambeerfestival`
63+
3. Click **Create application****Pages**
64+
4. Set **Project name**: `cambeerfestival`
65+
5. Disable automatic deployments (GitHub Actions will handle deployments)
4666

47-
**Important**: The project name must be `cambeerfestival` to match the workflow configuration.
67+
**For Staging Project:**
68+
1. In **Workers & Pages**, click **Create application****Pages**
69+
2. Set **Project name**: `cambeerfestival-staging`
70+
3. Disable automatic deployments
4871

49-
**Note**: With GitHub Actions using `cloudflare/pages-action@v1`, the project will be created automatically on first deployment if it doesn't exist. Manual creation is optional.
72+
**Important**: Project names must match the workflow configuration (`cambeerfestival` and `cambeerfestival-staging`).
5073

5174
### 2. Get Cloudflare Account ID
5275

@@ -92,24 +115,51 @@ You can reuse the same token by adding Pages permissions to it:
92115

93116
**Note**: Using a single token with both Workers and Pages permissions is simpler and follows the principle of consolidating CI/CD credentials for the same application.
94117

95-
### 4. Configure Custom Domain
118+
### 4. Configure Custom Domains
119+
120+
You need to configure **one custom domain per project**:
121+
122+
#### 4a. Production Project Domain
96123

97124
1. In Cloudflare Dashboard, go to **Workers & Pages****Pages**
98-
2. Select your `cambeerfestival` project
99-
3. Go to **Custom domains** tab
100-
4. Click **Set up a custom domain**
101-
5. Enter: `cambeerfestival.app`
102-
6. Click **Continue**
103-
7. Cloudflare will automatically configure the DNS records
104-
8. Optionally add `www.cambeerfestival.app` as well
125+
2. Select the **`cambeerfestival`** project
126+
3. Go to **Settings****Builds & deployments**
127+
4. Set **Production branch** to: `release`
128+
5. Go to **Custom domains** tab
129+
6. Click **Set up a custom domain**
130+
7. Enter: `cambeerfestival.app`
131+
8. Click **Continue**
132+
9. Cloudflare will automatically configure the DNS records
133+
134+
#### 4b. Staging Project Domain
135+
136+
1. In Cloudflare Dashboard, go to **Workers & Pages****Pages**
137+
2. Create or select the **`cambeerfestival-staging`** project
138+
3. Go to **Settings****Builds & deployments**
139+
4. Set **Production branch** to: `main`
140+
5. Go to **Custom domains** tab
141+
6. Click **Set up a custom domain**
142+
7. Enter: `staging.cambeerfestival.app`
143+
8. Click **Continue**
144+
9. Cloudflare will automatically configure the DNS records
145+
146+
**Note**: The `cambeerfestival-staging` project will be automatically created by GitHub Actions on the first deployment if it doesn't exist.
147+
148+
#### 4c. Optional: WWW Redirect
149+
150+
If you want `www.cambeerfestival.app` to redirect to the apex domain:
151+
1. In the `cambeerfestival` project, add `www.cambeerfestival.app` as a custom domain
105152

106153
**DNS Records Created** (automatic):
107154
- `CNAME cambeerfestival.app``cambeerfestival.pages.dev`
108-
- `CNAME www.cambeerfestival.app``cambeerfestival.pages.dev` (if www added)
155+
- `CNAME staging.cambeerfestival.app``cambeerfestival-staging.pages.dev`
156+
- `CNAME www.cambeerfestival.app``cambeerfestival.pages.dev` (optional)
109157

110158
### 5. Update Cloudflare Worker
111159

112-
The Cloudflare Worker for API proxy has already been updated to allow `https://cambeerfestival.app` in CORS origins.
160+
The Cloudflare Worker for API proxy has already been updated to allow both custom domains in CORS origins:
161+
- `https://cambeerfestival.app` (production)
162+
- `https://staging.cambeerfestival.app` (staging)
113163

114164
When you deploy worker changes:
115165

@@ -404,16 +454,25 @@ Both should remain in free tier unless app sees very high traffic.
404454

405455
## Summary Checklist
406456

407-
- [ ] Cloudflare Pages project `cambeerfestival` created
457+
**Cloudflare Setup:**
458+
- [ ] Cloudflare Pages project `cambeerfestival` created (production)
459+
- [ ] Cloudflare Pages project `cambeerfestival-staging` created (staging/previews)
460+
- [ ] Production project `cambeerfestival` → Production branch set to `release`
461+
- [ ] Staging project `cambeerfestival-staging` → Production branch set to `main`
462+
- [ ] Custom domain `cambeerfestival.app` configured on `cambeerfestival` project
463+
- [ ] Custom domain `staging.cambeerfestival.app` configured on `cambeerfestival-staging` project
464+
- [ ] DNS records configured (automatic via Cloudflare)
408465
- [ ] Cloudflare Account ID obtained
409466
- [ ] Cloudflare API Token updated with **both** Workers Scripts + Pages permissions
410-
- [ ] Custom domain `cambeerfestival.app` configured in Cloudflare Pages
411-
- [ ] DNS records configured (automatic via Cloudflare)
467+
468+
**GitHub Setup:**
412469
- [ ] GitHub Secret `CLOUDFLARE_API_TOKEN` verified (should work for both Workers and Pages)
413470
- [ ] GitHub Secret `CLOUDFLARE_ACCOUNT_ID` added
414471
- [ ] GitHub Secret `GOOGLE_SERVICES_JSON` verified
415472
- [ ] Workflow files committed (`.github/workflows/release-web.yml` and `build-deploy.yml`)
416-
- [ ] Cloudflare Worker updated with `cambeerfestival.app` CORS origin and wildcard for Pages previews
417-
- [ ] Push to `main` triggers successful deployment to staging
473+
474+
**Verification:**
475+
- [ ] Cloudflare Worker updated with both custom domains in CORS origins
476+
- [ ] Push to `main` triggers successful deployment to `https://staging.cambeerfestival.app`
418477
- [ ] Create tag triggers production deployment to `https://cambeerfestival.app`
419478
- [ ] API calls work without CORS errors on all environments

0 commit comments

Comments
 (0)