-
Notifications
You must be signed in to change notification settings - Fork 0
203 lines (186 loc) · 7.5 KB
/
Copy pathci.yml
File metadata and controls
203 lines (186 loc) · 7.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
name: CI
on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
backend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: server
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: server/go.mod
cache-dependency-path: server/go.sum
- name: Test
run: go test ./...
- name: Race test
run: go test -race ./...
- name: Vet
run: go vet ./...
frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: Clean install
run: npm ci
- name: Lint
run: npm run lint
- name: Test
run: npm test
- name: Build
run: npm run build
# The Docker build regenerates the Swagger docs from the handler annotations,
# so the binary always serves a current spec, but server/docs is also
# committed, and the Pages site publishes that committed copy. Nothing forced
# the two to agree, so annotations could change without a follow-up
# `swag init` and the published reference would drift from the real API with
# no signal. Regenerate here and fail on any diff.
swagger-docs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: server
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: server/go.mod
cache-dependency-path: server/go.sum
# Pinned to the same version server/Dockerfile installs. A different
# version would report drift the real build never produces.
- name: Install swag
run: go install github.com/swaggo/swag/cmd/swag@v1.16.6
- name: Regenerate docs
run: swag init --parseDependency --parseInternal
- name: Committed docs are current
run: |
if ! git diff --exit-code -- docs; then
echo "::error file=server/docs/swagger.json::server/docs is stale. Run 'swag init --parseDependency --parseInternal' in server/ and commit the result."
exit 1
fi
docker-builds:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Build backend image
uses: docker/build-push-action@v6
with:
context: ./server
file: ./server/Dockerfile
push: false
tags: triangle-cms-backend:${{ github.sha }}
cache-from: type=gha,scope=backend
cache-to: type=gha,mode=max,scope=backend
- name: Build frontend image
uses: docker/build-push-action@v6
with:
context: ./frontend
file: ./frontend/Dockerfile
push: false
tags: triangle-cms-frontend:${{ github.sha }}
cache-from: type=gha,scope=frontend
cache-to: type=gha,mode=max,scope=frontend
# The deployment scripts are the least reversible code in the repo, so their
# test suite runs on every PR. It stubs docker/curl/nginx on PATH and needs no
# daemon, database, or privileges.
deploy-scripts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy script tests
run: deploy/scripts/deploy_scripts_test.sh
# The Python in scripts/ was previously untested. A full reseed cannot run
# here: it needs the WordPress export zip, which is not in the repo, and a
# local Docker stack. This covers the parts that can fail silently: the
# scripts compiling at all, the seed generator's id=0 guarantee, and the
# reseed script's refusal to destroy data unattended.
scripts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Compile
run: python -m compileall -q scripts/
- name: Reseed script help
run: python ./scripts/reseed_from_etl.py --help
# The non-TTY guard is the only thing standing between an automated
# context and a destroyed database, so assert it stays a guard: this must
# FAIL to proceed. Without a Docker daemon the run would abort in
# preflight anyway, so accept either refusal. What is not acceptable is
# a clean exit, which would mean it sailed past the confirmation.
- name: Refuses to destroy data unattended
run: |
if python ./scripts/reseed_from_etl.py --skip-etl < /dev/null; then
echo "::error file=scripts/reseed_from_etl.py::reseed script exited 0 without a TTY and without --yes"
exit 1
fi
# articles has a real row with id = 0, which survives a load only under
# NO_AUTO_VALUE_ON_ZERO. Nothing else in CI covers this, and a renumbered
# id=0 orphans every articles_authors and seo row that references it.
- name: Seed generator preserves the id=0 row
run: |
set -euo pipefail
etl=$(mktemp -d); out=$(mktemp -d)
printf "INSERT INTO authors (\`login\`) VALUES ('x');\n" > "$etl/authors.sql"
printf "INSERT INTO articles (\`author_ids\`, \`comment_status\`) VALUES ('x','open');\n" > "$etl/articles.sql"
printf "INSERT INTO articles_authors (\`author_id\`) VALUES (1);\n" > "$etl/articles_authors.sql"
printf "INSERT INTO seo (\`yoast_tag_data\`) VALUES ('{}');\n" > "$etl/seo.sql"
python ./scripts/generate_wordpress_sql.py "$etl" "$out"
if ! head -1 "$out/02-articles.sql" | grep -q 'NO_AUTO_VALUE_ON_ZERO'; then
echo "::error file=scripts/generate_wordpress_sql.py::02-articles.sql lacks the NO_AUTO_VALUE_ON_ZERO preamble; the id=0 article would be renumbered on load"
exit 1
fi
# A mention of the mode in a comment must not be mistaken for setting
# it; that regression would silently skip the preamble.
printf -- "-- NO_AUTO_VALUE_ON_ZERO handled upstream\nINSERT INTO articles (\`author_ids\`, \`comment_status\`) VALUES ('y','open');\n" > "$etl/articles.sql"
python ./scripts/generate_wordpress_sql.py "$etl" "$out"
if ! head -1 "$out/02-articles.sql" | grep -q '^SET sql_mode'; then
echo "::error file=scripts/generate_wordpress_sql.py::a commented mention of NO_AUTO_VALUE_ON_ZERO suppressed the preamble"
exit 1
fi
compose-validation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate Delta Compose config
env:
CMS_IMAGE_TAG: ${{ github.sha }}
DB_NAME: triangle
DB_USER: triangle_user
DB_PASSWORD: ci-placeholder
DB_HOST: db-host-placeholder
DB_PORT: "3306"
OIDC_ISSUER_URL: http://oidc-placeholder.invalid
OIDC_CLIENT_ID: ci-placeholder
OIDC_CLIENT_SECRET: ci-placeholder
FRONTEND_ORIGIN: http://delta-placeholder
OIDC_REDIRECT_URI: http://delta-placeholder/auth/callback
# CMS_EMBEDDINGS_TAG is derived rather than hardcoded, so this also
# checks that the derivation deploy.sh uses still resolves.
run: |
CMS_EMBEDDINGS_TAG="$(git rev-parse HEAD:embeddings)" \
docker compose -f deploy/compose.cms.yml config >/dev/null