Skip to content

Commit 2029836

Browse files
Add cloudbuild.yaml for Google Cloud Build configuration (#4432)
* Add cloudbuild.yaml for Google Cloud Build configuration * Enhance Cloud Build pipeline with detailed steps for installation, testing, and deployment * clean * Update cloudbuild.yaml Co-authored-by: Barry Pollard <barrypollard@google.com> * Update cloudbuild.yaml Co-authored-by: Barry Pollard <barrypollard@google.com> * keep main push triggers * bring back predeploy --------- Co-authored-by: Barry Pollard <barrypollard@google.com>
1 parent b88d11e commit 2029836

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

cloudbuild.yaml

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
######################################
2+
## Cloud Build Deployment Pipeline ##
3+
######################################
4+
#
5+
# Triggered on every push to main (i.e. when a PR is merged).
6+
# Update the trigger at:
7+
# https://console.cloud.google.com/cloud-build/triggers;region=us-central1/edit/2bd8fcc6-6319-455d-88f2-38d564fe2db8?project=httparchive
8+
#
9+
# $SHORT_SHA is set automatically by Cloud Build on a branch-push trigger.
10+
11+
substitutions:
12+
# Update when a new Prince version is released: https://www.princexml.com/latest/
13+
# python:3.12 is based on Debian Bookworm (12), so use the debian12 package.
14+
_PRINCE_PACKAGE: 'prince_16.1-1_debian12_amd64.deb'
15+
16+
steps:
17+
# ─────────────────────────────────────────────────────────────────────────
18+
# Step 1: Install dependencies, generate all chapters, run full test suite.
19+
# Uses python:3.12 (Debian Bookworm) and installs Node 24 at runtime.
20+
# node_modules persist in /workspace and are reused by later steps;
21+
# Python packages are re-installed per step.
22+
# ─────────────────────────────────────────────────────────────────────────
23+
- name: 'python:3.12'
24+
id: 'build-and-test'
25+
entrypoint: 'bash'
26+
dir: 'src'
27+
args:
28+
- '-c'
29+
- |
30+
set -e
31+
# Install Node.js 24 (nodesource setup script also runs apt-get update)
32+
curl -fsSL https://deb.nodesource.com/setup_24.x | bash -
33+
apt-get install -y nodejs
34+
35+
# Install Python dependencies
36+
pip install --quiet -r requirements.txt
37+
38+
# Install Node dependencies (uses package-lock.json for reproducibility)
39+
npm ci
40+
41+
# Start the web server in the background (required for URL tests)
42+
python main.py background &
43+
sleep 3
44+
45+
# Generate all chapters
46+
npm run generate
47+
48+
# Run Python unit tests
49+
npm run pytest
50+
51+
# Run full URL test suite against the running server
52+
npm run test
53+
54+
# ─────────────────────────────────────────────────────────────────────────
55+
# Step 2: Update timestamps then generate PDF ebooks.
56+
# Prince fetches pages from a running localhost server, so the Python server
57+
# is re-started here. Chapters written to /workspace/src in step 1 are
58+
# served directly; npm install is skipped (node_modules already present).
59+
# ─────────────────────────────────────────────────────────────────────────
60+
- name: 'python:3.12'
61+
id: 'generate-ebooks'
62+
entrypoint: 'bash'
63+
dir: 'src'
64+
args:
65+
- '-c'
66+
- |
67+
set -e
68+
apt-get update -qq
69+
70+
# Install Node.js 20
71+
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
72+
apt-get install -y nodejs
73+
74+
# Update static-asset cache-busting hashes before deploying
75+
npm run timestamps
76+
77+
# Install CJK fonts for multilingual ebooks
78+
apt-get install -y fonts-ipafont-gothic fonts-arphic-uming fonts-unfonts-core wget
79+
80+
# Install pdftk (ebook post-processing)
81+
apt-get install -y pdftk
82+
83+
# Download and install Prince PDF generator
84+
wget -q "https://www.princexml.com/download/${_PRINCE_PACKAGE}" -P /tmp
85+
apt-get install -y "/tmp/${_PRINCE_PACKAGE}"
86+
87+
# Install Python dependencies (needed to run the web server)
88+
pip install --quiet -r requirements.txt
89+
90+
# Re-start the web server so Prince can fetch pages from localhost
91+
python main.py background &
92+
sleep 3
93+
94+
# Generate PDF ebooks
95+
mkdir -p static/pdfs
96+
npm run ebooks
97+
98+
# ─────────────────────────────────────────────────────────────────────────
99+
# Step 3: Deploy to Google App Engine.
100+
# app.yaml is read from /workspace/src (dir: src).
101+
# App Engine version labels must start with a letter, so SHORT_SHA is
102+
# prefixed: e.g. a1b2c3d → deploy-a1b2c3d.
103+
# ─────────────────────────────────────────────────────────────────────────
104+
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
105+
id: 'deploy'
106+
entrypoint: 'bash'
107+
dir: 'src'
108+
args:
109+
- '-c'
110+
- |
111+
set -e
112+
VERSION="deploy-${SHORT_SHA}"
113+
echo "Deploying version: ${VERSION}"
114+
gcloud app deploy \
115+
--project webalmanac \
116+
--version="${VERSION}" \
117+
--stop-previous-version \
118+
--quiet
119+
120+
# ─────────────────────────────────────────────────────────────────────────
121+
# Step 4: Upload generated ebooks to GCS.
122+
# Uses nullglob so missing PDFs produce a warning rather than an error.
123+
# ─────────────────────────────────────────────────────────────────────────
124+
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
125+
id: 'upload-ebooks'
126+
entrypoint: 'bash'
127+
args:
128+
- '-c'
129+
- |
130+
set -e
131+
shopt -s nullglob
132+
pdfs=(/workspace/src/static/pdfs/web_almanac_*.pdf)
133+
if [[ ${#pdfs[@]} -gt 0 ]]; then
134+
gsutil -m cp "${pdfs[@]}" gs://httparchive/almanac/ebooks/
135+
echo "Uploaded ${#pdfs[@]} PDF(s) to GCS"
136+
else
137+
echo "Warning: no ebooks found to upload"
138+
fi
139+
140+
# Total timeout covers: ~10 min build/test + ~30 min ebook generation +
141+
# ~10 min deploy + ~5 min GCS upload.
142+
timeout: '3600s'

0 commit comments

Comments
 (0)