-
Notifications
You must be signed in to change notification settings - Fork 0
96 lines (87 loc) · 4.25 KB
/
Copy pathdeploy.yml
File metadata and controls
96 lines (87 loc) · 4.25 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
# (c) 2026 William Li
name: Deploy to Lightsail
# Auto-deploy on push to main, and on any v* tag push. The tag trigger
# matters because vite.config.js resolves the build-time __APP_VERSION__
# via `git describe --tags --abbrev=0`; pushing a fresh `v1.2.3` should
# redeploy without needing a separate trigger commit.
on:
push:
branches: [main]
tags: ['v*']
# Concurrent deploys race over the same rsync target. Serialize and
# cancel any in-flight run when a newer push arrives.
concurrency:
group: deploy-lightsail
cancel-in-progress: true
# Required GitHub secrets (configure under repo Settings → Secrets and
# variables → Actions — values stay in GitHub's encrypted vault, never
# in this file):
# SSH_HOST — Lightsail host (same value chardata uses)
# SSH_USER — SSH username on Lightsail (admin)
# SSH_PRIVATE_KEY — private half of a keypair whose public half is
# in /home/admin/.ssh/authorized_keys on Lightsail
#
# The build runs on the GitHub-hosted runner because Vite 8 requires
# Node ≥ 20.19 and Lightsail's system Node is 18.20.4 (locked there by
# chardata's PM2 process). Committed WASM artifacts in
# frontend/public/wasm/ ship as-is — Vite copies them straight into
# dist/wasm/, so the runner doesn't need Emscripten or iccDEV.
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Check out source
# Actions are pinned to commit SHAs (not mutable tags): this job holds
# the deploy key, so a hijacked upstream tag must not be able to run
# here. The trailing comment tracks which release each SHA corresponds
# to; bump both together when updating.
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
# Full history so `git describe --tags --abbrev=0` in
# vite.config.js can resolve the version label.
fetch-depth: 0
- name: Set up Node 20
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
# The committed WASM artifacts ship verbatim (the runner has no Emscripten/iccDEV),
# so at minimum verify each one still matches the checksum recorded beside it before
# it goes to production. NOTE the honest limit of this gate: SHA256SUMS is produced
# by the same build that produced the binaries and is committed alongside them, so
# this detects corruption, a partial commit, or artifact/manifest drift — it is NOT
# an integrity control against a malicious commit, which would simply update both.
# Proving the binary matches the C++ source still requires `scripts/build-wasm.sh
# --verify` in an Emscripten+iccDEV environment.
- name: Verify committed WASM checksums
working-directory: frontend/public/wasm
run: sha256sum -c SHA256SUMS
- name: Build SPA
working-directory: frontend
run: |
npm ci
npm run build
test -f dist/index.html
- name: Load deploy key
uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Trust Lightsail host
# Prefer a pinned host key from the SSH_KNOWN_HOSTS secret (set it to the
# output of `ssh-keyscan <host>` once, verified out-of-band). Falls back
# to per-run keyscan (trust-on-first-use) only if that secret is unset,
# so deploys keep working until the secret is added. Add the secret to
# close the TOFU/MITM window on the rsync target.
run: |
mkdir -p ~/.ssh
if [ -n "${{ secrets.SSH_KNOWN_HOSTS }}" ]; then
printf '%s\n' "${{ secrets.SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
else
echo "::warning::SSH_KNOWN_HOSTS secret not set — falling back to ssh-keyscan (TOFU). Set it to pin the host key."
ssh-keyscan -H "${{ secrets.SSH_HOST }}" >> ~/.ssh/known_hosts
fi
- name: Rsync dist to Lightsail
run: |
rsync -avz --delete frontend/dist/ \
"${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/profiletool/"