-
Notifications
You must be signed in to change notification settings - Fork 71
221 lines (205 loc) · 7.88 KB
/
Copy pathmain.yml
File metadata and controls
221 lines (205 loc) · 7.88 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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
name: CI
on:
push:
branches:
- main
# Release flavor is derived from the tag suffix in the deploy job. Convention: prefix tags
# with "v" (bare X.Y.Z is still accepted for backward compatibility).
tags:
- '*.*.*' # stable semver (e.g. v1.2.3): published and marked "Latest"
- '*-preview' # pre-release (e.g. v1.2.3-preview): published, never "Latest"
- '*-draft' # draft (e.g. v1.2.3-draft): unpublished for review, never "Latest"
pull_request:
branches:
- main
workflow_dispatch: # Allow manual trigger
# Least privilege by default; the deploy job elevates it explicitly.
permissions:
contents: read
# Cancel superseded runs on the same ref, but only for pull requests — never abort an in-flight
# push to main or a tag (which may be mid-release).
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
- run: npm ci
- name: Lint sources
run: |
make lint
npm run lint
test:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0 # SonarCloud needs the full history for blame/coverage
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
- run: npm ci
- name: Execute tests
run: |
make test
make test-integration
npm test
make coverage
- name: SonarCloud Scan
uses: SonarSource/sonarqube-scan-action@22918119ff8e1ca75a623e15c8296b6ea4fbe28f # v8.2.1
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
e2e:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
- run: npm ci
- name: Install Playwright browser
run: npx playwright install --with-deps chromium
- name: Run Playwright non-regression suite
run: make test-e2e
security:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
# Audit only the dependencies that ship in the client bundle (dev tooling isn't served), and
# fail only on high/critical advisories.
- name: Audit frontend dependencies (npm)
run: npm audit --omit=dev --audit-level=high
# govulncheck reports only vulnerabilities actually reachable from the code, so it's low-noise
# and safe to gate on.
- name: Scan backend dependencies (govulncheck)
run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...
build:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
cache: npm
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
# Every run assembles the native image and smoke-tests it (proves the Dockerfile + embedded
# UI still work). Only tag builds also cross-compile the release binaries + tarball, which the
# deploy job packages into the multi-arch image and the GitHub release.
- name: Build image (+ release binaries on tags) and smoke-test
env:
VERSION: ${{ github.ref_name }}
run: |
targets="build-docker start-docker smoke-docker"
[[ "$GITHUB_REF" == refs/tags/* ]] && targets="release $targets"
make VERSION="$VERSION" RELEASE=1 $targets
- name: Upload release artifacts
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: smocker-dist
path: |
build/smocker.tar.gz
build/smocker-*
deploy:
needs: [lint, test, build, e2e, security]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
timeout-minutes: 10
# Elevated only here: push the image to GHCR and publish the GitHub release.
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- id: release_flags
name: Derive the release flavor from the tag suffix
env:
REF: ${{ github.ref_name }}
run: |
draft=false
prerelease=false
make_latest=true
if [[ "$REF" == *-draft ]]; then
draft=true # unpublished, editable on GitHub before release
make_latest=false
elif [[ "$REF" == *-* ]]; then
prerelease=true # e.g. -preview / -rc: published but never "Latest"
make_latest=false
fi
{
echo "draft=$draft"
echo "prerelease=$prerelease"
echo "make_latest=$make_latest"
} >> "$GITHUB_OUTPUT"
# The pre-built binaries (+ tarball) from the build job; the image is assembled from them.
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: smocker-dist
path: ./build
- name: Docker login
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# No QEMU: the image only packages the pre-built binaries (COPY-only target stages).
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Deploy on Docker registry
env:
VERSION: ${{ github.ref_name }}
run: make VERSION="$VERSION" deploy-docker
- name: Deploy on GitHub releases
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
files: |
build/smocker.tar.gz
build/smocker-*
token: ${{ secrets.GITHUB_TOKEN }}
draft: ${{ steps.release_flags.outputs.draft }}
prerelease: ${{ steps.release_flags.outputs.prerelease }}
make_latest: ${{ steps.release_flags.outputs.make_latest }}