-
Notifications
You must be signed in to change notification settings - Fork 1
351 lines (328 loc) · 12.6 KB
/
pipeline.yml
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
name: Pipeline
on:
# run on any branch receiving a push (not only on main)
push:
branches:
- main
pull_request:
branches:
- main
# also: allow to run this workflow manually
workflow_dispatch:
jobs:
#############################################
# jobs dispatched to a separate workflow file
#############################################
backend-jobs:
permissions:
security-events: write # upload-sarif
packages: write
id-token: write
contents: read
uses: ./.github/workflows/backend-jobs.yml
with:
container-registry: ghcr.io
container-image-name: ${{ github.repository }}
container-image-version: ${{ github.event.pull_request.head.sha || github.sha }}
secrets: inherit # e.g. sonar token
frontend-jobs:
permissions:
security-events: write # upload-sarif
packages: write
id-token: write
contents: read
uses: ./.github/workflows/frontend-jobs.yml
with:
# It would be nicer if we used the env vars defined above (as not to duplicate information),
# however, env vars cannot be passed over to a reuseable workflow using "with"
# cf. https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations
# and the workaround is horrible
# cf. https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-outputs-from-a-reusable-workflow
container-registry: ghcr.io
container-image-name: ${{ github.repository }}
container-image-version: ${{ github.event.pull_request.head.sha || github.sha }}
secrets: inherit # e.g. sonar token
ldml-extension-jobs:
uses: ./.github/workflows/ldml-extension-jobs.yml
secrets: inherit # e.g. sonar token
create-docker-image-job:
permissions:
security-events: write # upload-sarif
packages: write
id-token: write
contents: read
uses: ./.github/workflows/create-docker-image-job.yml
with:
container-registry: ghcr.io
container-image-name: ${{ github.repository }}
container-image-version: ${{ github.event.pull_request.head.sha || github.sha }}
secrets: inherit # e.g. sonar token
push-docker-image-job:
if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'dev-env') || contains(github.event.labeled.labels.*.name, 'dev-env') }}
needs:
- backend-jobs
- frontend-jobs
- create-docker-image-job
- e2e-tests
permissions:
security-events: write # upload-sarif
packages: write
id-token: write
contents: read
uses: ./.github/workflows/push-docker-image-job.yml
with:
container-registry: ghcr.io
container-image-name: ${{ github.repository }}
container-image-version: ${{ github.event.pull_request.head.sha || github.sha }}
secrets: inherit # e.g. sonar token
# ######################
# # Check time for automatic deployments
# # Should only deploy automatically outside the hours when migration job (1:00AM UTC) and publishing job run (2:00AM UTC),
# # meaning not between 0:30 AM UTC and 4:00AM UTC
# ######################
check-auto-deploy:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
outputs:
should-auto-deploy: ${{ steps.check-time.outputs.should-auto-deploy }}
steps:
- id: check-time
run: |
current_time=$(TZ=UTC date "+%H:%M")
if [[ "$current_time" > "00:30" && "$current_time" < "04:00" ]]; then
echo "Should not deploy automatically. Current time is $current_time"
echo "should-auto-deploy=false" >> "$GITHUB_OUTPUT"
else
echo "Should deploy automatically. Current time is $current_time"
echo "should-auto-deploy=true" >> "$GITHUB_OUTPUT"
fi
# ######################
# # Deploy new versions to staging
# ######################
deploy-staging-job:
if: ${{ github.ref == 'refs/heads/main' && needs.check-auto-deploy.outputs.should-auto-deploy == 'true' }}
needs:
- check-auto-deploy
- frontend-jobs
- backend-jobs
- push-docker-image-job
- e2e-tests
permissions:
id-token: write
uses: ./.github/workflows/deploy-staging-job.yml
secrets: inherit
# ######################
# # Deploy new versions to uat
# ######################
deploy-uat-job:
if: ${{ github.ref == 'refs/heads/main' }}
needs:
- deploy-staging-job
permissions:
id-token: write
uses: ./.github/workflows/deploy-uat-job.yml
secrets: inherit
# ######################
# # Deploy new versions to production
# ######################
deploy-production-job:
if: ${{ github.ref == 'refs/heads/main' }}
needs:
- deploy-uat-job
permissions:
id-token: write
uses: ./.github/workflows/deploy-production-job.yml
secrets: inherit
# ########################
# # system test jobs
# ########################
e2e-tests:
strategy:
fail-fast: false
matrix:
browser: [chromium, firefox, msedge]
uses: ./.github/workflows/end-to-end-tests.yml
with:
browser: ${{ matrix.browser }}
secrets: inherit
################
# Security jobs
################
trivy-scan:
runs-on: ubuntu-latest
permissions:
security-events: write # upload-sarif
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@18f2510ee396bbf400402947b394f2dd8c87dbb0
env:
ACTIONS_RUNTIME_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db
TRIVY_JAVA_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-java-db,public.ecr.aws/aquasecurity/trivy-java-db
with:
scan-type: "fs"
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH" #ignored by sarif report
- name: Check trivy results
run: |
if grep -qE 'HIGH|CRITICAL' trivy-results.sarif; then
echo "Vulnerabilities found"
exit 1
else
echo "No significant vulnerabilities found"
exit 0
fi
- name: Upload Trivy scan results to GitHub Security tab
if: ${{ always() && github.ref == 'refs/heads/main' }} # Bypass non-zero exit code..
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: "trivy-results.sarif"
- name: Send status to Slack
# Third-party action, pin to commit SHA!
# See https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions
uses: digitalservicebund/notify-on-failure-gha@814d0c4b2ad6a3443e89c991f8657b10126510bf # v1.5.0
if: ${{ failure() && github.ref == 'refs/heads/main' }}
with:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
talisman-check:
runs-on: ubuntu-latest
# Running on main only https://digitalservicebund.slack.com/archives/C046VD44ZEH/p1706516240974409
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Detect secrets in incoming commits with Talisman
uses: digitalservicebund/talisman-secrets-scan-action@9a4cb85589e29a62b4546eb566119753a5680aeb
- name: Send status to Slack
# only on failure and if on "main" branch
if: ${{ failure() && github.ref == 'refs/heads/main' }}
uses: digitalservicebund/notify-on-failure-gha@814d0c4b2ad6a3443e89c991f8657b10126510bf # v1.5.0
with:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
###################
# Generate reports
###################
generate-test-reports:
if: ${{ !cancelled() && github.ref == 'refs/heads/main' }}
needs:
- e2e-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: ./frontend/.node-version
cache: npm
cache-dependency-path: ./frontend/package-lock.json
- name: Cache node_modules
uses: actions/cache@v4
id: cache-npm-cache
with:
# The docs discourage caching `node-modules`, cf. https://github.com/actions/cache/blob/main/examples.md#node---npm
path: /home/runner/.npm
key: npm-cache-${{ hashFiles('./frontend/package-lock.json') }}
- name: Install node modules
run: npm ci
working-directory: ./frontend
- name: Download blob reports from artifacts
uses: actions/download-artifact@v4
with:
path: ./frontend/all-blob-reports
pattern: test-results-blob-*
- name: Prepare test reports for merge
working-directory: ./frontend/all-blob-reports
run: |
for DIR in test-results-blob-*; do
unzip -o "$DIR/test-report.zip" -d "$DIR"
rm "$DIR/test-report.zip"
ZIP_FILE="../$(basename "$DIR").zip"
(cd "$DIR" && zip -r "$ZIP_FILE" ./*.jsonl)
rm -rf "$DIR"
done
shell: bash
- name: Merge into html report
run: npx playwright merge-reports --reporter html ./all-blob-reports
working-directory: ./frontend
- name: Upload html report to artifacts
uses: actions/upload-artifact@v4
with:
name: html-test-report
path: ./frontend/playwright-report
push-reports:
runs-on: ubuntu-latest
env:
reports-repo: digitalservicebund/ris-reports
needs:
- generate-test-reports
- backend-jobs
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v4
with:
repository: ${{ env.reports-repo }}
ssh-key: ${{ secrets.REPORTS_DEPLOY_KEY }}
- name: Setup git config
run: |
git config user.name "${{ github.repository }}"
# This email identifies the commit as GitHub Actions - see https://github.com/orgs/community/discussions/26560
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
# Backend code documentation
- name: Backend Code Documentation - Download
uses: actions/download-artifact@v4
with:
name: backend-code-documentation
path: tmp/backend-code-documentation/
- name: Java - git add report
uses: digitalservicebund/add-ris-report@c6c8735d23295c36a271c75e7dedc9b6b9a9ef5e
with:
filePath: tmp/backend-code-documentation
destinationDir: norms-code-documentation/java
reportIsDirectory: true
# e2e test report
- name: E2E test reports - Download
uses: actions/download-artifact@v4
with:
name: html-test-report
path: tmp/html-test-report/
- name: E2E test reports - git add report
uses: digitalservicebund/add-ris-report@c6c8735d23295c36a271c75e7dedc9b6b9a9ef5e
with:
filePath: tmp/html-test-report/
destinationDir: test-reports/ris-norms
reportIsDirectory: true
# Licence reports
- name: Licence reports - Download
uses: actions/download-artifact@v4
with:
pattern: licence-reports-*
path: tmp/licence-reports/
merge-multiple: true
- name: Frontend licence report - git add report
uses: digitalservicebund/add-ris-report@c6c8735d23295c36a271c75e7dedc9b6b9a9ef5e
with:
filePath: tmp/licence-reports/frontend-licence-report.csv
destinationDir: licence-reports/frontend/ris-norms
- name: Backend licence report - git add report
uses: digitalservicebund/add-ris-report@c6c8735d23295c36a271c75e7dedc9b6b9a9ef5e
with:
filePath: tmp/licence-reports/backend-licence-report.csv
destinationDir: licence-reports/backend/ris-norms
# Push reports
- name: Push reports
run: |
git diff-index --cached --quiet HEAD ||
git commit \
-m ${{ toJSON(github.event.head_commit.message) }} \
-m "From commit: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}" &&
git push origin main &&
echo "Pushed reports to ${{ github.server_url }}/${{ env.reports-repo }}" >> $GITHUB_STEP_SUMMARY
- name: Send status to Slack
uses: digitalservicebund/notify-on-failure-gha@66c485757701f8d5dbee32f24df38d904ca693ba
if: ${{ failure() && github.ref == 'refs/heads/main' }}
with:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}