-
Notifications
You must be signed in to change notification settings - Fork 2
196 lines (169 loc) · 6.39 KB
/
Copy pathrelease.yml
File metadata and controls
196 lines (169 loc) · 6.39 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
name: Release
# Triggered when a GitHub Release is published.
# Flow:
# 1. scan-app — npm audit (HIGH+) + govulncheck on go-web-proxy
# 2. build-pwa — npm run build, upload dist/ as a workflow artifact
# 3. build-image — buildx + Trivy (HIGH/CRITICAL) + push to GHCR
# 4. deploy-pages — sync dist/ into the `dist` branch (preserving committed
# vendor JS files); Pages auto-redeploys from that branch
#
# Any HIGH/CRITICAL finding in scan-app or build-image blocks the release —
# image is not pushed, Pages is not updated.
#
# Pages source must be set to: Settings → Pages → Source: Deploy from a branch
# → Branch: dist → Folder: / (root). The `dist` branch is expected to already
# exist and contain the vendor files (solclient.js, jszip.min.js) plus an
# empty .nojekyll file so Pages skips Jekyll processing.
on:
release:
types: [published]
permissions:
contents: read
env:
IMAGE_NAME: ghcr.io/${{ github.repository }}
NODE_VERSION: '22'
GO_VERSION: '1.26'
# Opt into Node.js 24 for all JavaScript actions ahead of the June 2026
# default flip. Drops the "Node.js 20 actions are deprecated" warnings.
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
concurrency:
group: release-${{ github.event.release.tag_name }}
cancel-in-progress: false
jobs:
scan-app:
name: Scan source (npm audit + govulncheck)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- run: npm ci --no-audit --no-fund
- name: npm audit (fail on HIGH/CRITICAL)
run: npm run scan:npm
# govulncheck-action installs Go itself via go-version-input — no separate
# setup-go step. go-web-proxy has stdlib-only deps, so there is no go.sum
# to cache and no benefit from setup-go's caching layer.
- name: govulncheck (fail on any finding)
uses: golang/govulncheck-action@v1
with:
go-version-input: ${{ env.GO_VERSION }}
work-dir: go-web-proxy
build-pwa:
name: Build PWA bundle
needs: scan-app
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- run: npm ci --no-audit --no-fund
# Produces dist/index.html (prod), dist/mock.html (demo), dist/min.html (minimal).
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: pwa-bundle
path: dist
retention-days: 7
if-no-files-found: error
build-image:
name: Build, scan, and push image
needs: scan-app
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
# OCI image references must be all-lowercase. `${{ github.repository }}`
# preserves the org's original casing (e.g. SolaceLabs), which GHCR's push
# endpoint accepts but the strict OCI reference parser (used by Trivy and
# other tools) rejects. Lowercase IMAGE_NAME once, here, so every
# downstream step sees a valid reference.
- name: Lowercase image name
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> "$GITHUB_ENV"
- uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Compute image tags
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
# Release tag format vX.Y.Z (e.g. v3.3.0) → produces tags 3.3.0, 3.3, 3, latest
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest
# Load the image into the local daemon so Trivy can scan it before we push.
- name: Build image (load into local daemon)
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
load: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Trivy scan (HIGH/CRITICAL, fail on findings)
uses: aquasecurity/trivy-action@v0.36.0
with:
image-ref: ${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
severity: HIGH,CRITICAL
exit-code: '1'
ignore-unfixed: true
vuln-type: os,library
- name: Push image (all computed tags)
run: |
echo "${{ steps.meta.outputs.tags }}" | while IFS= read -r tag; do
[ -z "$tag" ] && continue
docker push "$tag"
done
deploy-pages:
name: Deploy PWA to `dist` branch
needs: [build-pwa, build-image]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
# Check out the dist branch itself — vendor files (solclient.js, jszip.min.js)
# and Pages-control files (.nojekyll, CNAME) are expected to already be
# committed here. We overlay the freshly-built bundle on top.
- name: Check out dist branch
uses: actions/checkout@v4
with:
ref: dist
fetch-depth: 0
- name: Download PWA bundle
uses: actions/download-artifact@v4
with:
name: pwa-bundle
path: _bundle
# Only index.html is published. mock.html and min.html stay as workflow
# artifacts (downloadable from the run page) but are not pushed to dist.
# Anything else already present on the dist branch (vendor files,
# .nojekyll, CNAME, etc.) is left untouched.
- name: Copy index.html into dist branch
run: |
cp _bundle/index.html ./index.html
rm -rf _bundle
- name: Commit and push to dist branch
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
if git diff --staged --quiet; then
echo "No changes to deploy."
exit 0
fi
git commit -m "Deploy ${{ github.event.release.tag_name }}"
git push origin dist