Repository navigation
274 lines (243 loc) · 10.1 KB
/
Copy pathci.yml
File metadata and controls
274 lines (243 loc) · 10.1 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
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
name: CI
on:
push:
branches:
- main
- release
- develop
tags:
- v[0-9]+.[0-9]+**
pull_request:
branches:
- main
- release
- develop
env:
TRIVY_VERSION: v0.75.0
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Test Synthea import and roundtrip checks
run: python3 -m unittest discover -s scripts/tests -v
- name: Check Compose profile combinations
run: python3 web/integration/test_compose_profiles.py
- name: Test official availability updater
run: >-
docker run --rm --network none --memory=512m
--entrypoint python
-v "$PWD/web/integration/test_availability_layout.py:/test_layout.py:ro"
ghcr.io/medizininformatik-initiative/dataportal-availability-updater:0.4.2
/test_layout.py
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17
- name: Cache Local Maven Repo
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: maven-repo
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: java
queries: security-and-quality
- name: Build
run: mvn -B package
- name: Check converter option contract
run: |
python3 web/catalog/options/generate_schema.py --check
python3 -m unittest discover -s web/catalog/options/tests -v
java --class-path target/excel2fhir.jar web/catalog/options/tests/CheckJavaBindings.java
- name: Set up Python for workbench tests
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Test workbench queue and API
run: |
python -m pip install -r web/backend/requirements-test.txt
python -m unittest discover -s web/backend -p 'test_*.py' -v
python web/integration/smoke_dataset_variants.py
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Test and build workbench
working-directory: web/frontend
run: |
npm ci
npm test
npm run build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
workbench-inputs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build workbench worker
run: docker build -f web/backend/Dockerfile --target worker -t excel2fhir-workbench:ci .
- name: Verify blazectl uploads on Blaze and HAPI
run: |
trap 'docker compose -f web/compose.yml stop blaze hapi hapi-db' EXIT
docker compose -f web/compose.yml up -d --wait --wait-timeout 180 blaze
docker run --rm --memory=1g --network excel2fhir-web-prototype_default -v "$PWD/web/integration/smoke_fhir_upload.py:/probe.py:ro" excel2fhir-workbench:ci python /probe.py blaze
docker compose -f web/compose.yml stop blaze
docker compose -f web/compose.yml up -d hapi-db hapi
for attempt in $(seq 1 90); do
if curl --fail --silent http://localhost:5191/fhir/metadata >/dev/null; then break; fi
sleep 2
done
docker run --rm --memory=1g --network excel2fhir-web-prototype_default -v "$PWD/web/integration/smoke_fhir_upload.py:/probe.py:ro" excel2fhir-workbench:ci python /probe.py hapi
- name: Generate Synthea sources and compare repeated clinical histories
run: docker run --rm -i --memory=6g --cpus=2 excel2fhir-workbench:ci python - < web/integration/smoke_synthea_generation.py
- name: Import Synthea sources and repeat immutable runs
run: docker run --rm -i --memory=4g --cpus=2 excel2fhir-workbench:ci python - < web/integration/smoke_synthea_inputs.py
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
uses: docker/build-push-action@v4
with:
context: .
file: docker/Dockerfile
tags: security-scan-build:latest
push: false
- name: Run Trivy Vulnerability Scanner and Save to Sarif File
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
version: ${{ env.TRIVY_VERSION }}
image-ref: security-scan-build:latest
format: sarif
output: trivy-results.sarif
severity: 'CRITICAL,HIGH'
timeout: '15m0s'
- name: Upload Trivy Scan Results to GitHub Security Tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif
- name: Run Trivy Vulnerability Scanner
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
version: ${{ env.TRIVY_VERSION }}
image-ref: security-scan-build:latest
exit-code: 1
ignore-unfixed: true
trivyignores: '.trivyignore'
severity: 'CRITICAL,HIGH'
timeout: '15m0s'
synthea-workflow:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build existing Synthea importer image
run: docker build -f docker/synthea.Dockerfile -t excel2fhir-synthea:ci .
- name: Convert and validate actual Synthea regression fixtures
shell: bash
run: |
mkdir -p "$RUNNER_TEMP/synthea-results"
set +e
docker run --rm --user "$(id -u):$(id -g)" -e HOME=/tmp \
-v "$PWD/scripts/tests/fixtures/synthea:/input:ro" \
-v "$RUNNER_TEMP/synthea-results:/output" \
excel2fhir-synthea:ci -v -i /input -o /output
result=$?
set -e
python3 - "$RUNNER_TEMP/synthea-results" "$result" <<'PYTHON'
import json, pathlib, sys
directory = next(pathlib.Path(sys.argv[1]).glob("run-*"))
report = json.loads((directory / "details/reports/summary.json").read_text())
assert not report['failures'], report
assert len(report['results']) == 2, report
assert report['status'] in ('COMPLETE', 'NOT_CHECKED'), report
assert int(sys.argv[2]) == (0 if report['status'] == 'COMPLETE' else 1), report
assert all(r['importStatus'] == 'COMPLETE' for r in report['results']), report
bundles = [json.loads(p.read_text()) for p in sorted((directory / 'fhir').rglob('*.json'))]
lines = [json.loads(line) for p in sorted((directory / 'fhir').rglob('*.ndjson')) for line in p.read_text().splitlines()]
assert bundles == lines, 'JSON and NDJSON differ'
assert not list((directory / 'details').glob('cases/*/run-*/fhir/**/*.json')), 'Duplicate final bundles'
PYTHON
- name: Scan Synthea importer image
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
version: ${{ env.TRIVY_VERSION }}
image-ref: excel2fhir-synthea:ci
exit-code: 1
ignore-unfixed: true
trivyignores: '.trivyignore'
severity: 'CRITICAL,HIGH'
timeout: '15m0s'
- name: Build generator and run the complete workflow offline
shell: bash
run: |
docker compose -p excel2fhir-ci -f compose.synthea.yml build
docker run --rm --network none --entrypoint python3 excel2fhir-ci-synthea:latest \
-m unittest discover -s /app/scripts/tests -p test_container_output.py -v
set +e
docker compose -p excel2fhir-ci -f compose.synthea.yml run --rm synthea
result=$?
set -e
python3 - "$result" <<'PYTHON'
import json, pathlib, sys
runs = list(pathlib.Path('outputGlobal').glob('run-*'))
assert len(runs) == 1, runs
report = json.loads((runs[0] / 'details/reports/workflow.json').read_text())
summary = json.loads((runs[0] / 'details/reports/summary.json').read_text())
assert report['status'] == 'NOT_VALIDATED', report
assert report['validationEnabled'] is False, report
assert int(sys.argv[1]) == 0, report
assert all(r['validationStatus'] == 'NOT_VALIDATED' for r in summary['results']), summary
assert not list(runs[0].rglob('*.validation.json')), 'Unexpected validation reports'
assert summary['results'] and not summary['failures'], summary
bundles = [json.loads(p.read_text()) for p in sorted((runs[0] / 'fhir').rglob('*.json'))]
lines = [json.loads(line) for p in sorted((runs[0] / 'fhir').rglob('*.ndjson')) for line in p.read_text().splitlines()]
assert len(bundles) == len(summary['results'])
assert bundles == lines, 'JSON and NDJSON differ'
PYTHON
- name: Scan complete workflow image
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
version: ${{ env.TRIVY_VERSION }}
image-ref: excel2fhir-ci-synthea:latest
exit-code: 1
ignore-unfixed: true
trivyignores: '.trivyignore'
severity: 'CRITICAL,HIGH'
timeout: '15m0s'
- name: Preserve regression reports and generated workbooks
if: always()
uses: actions/upload-artifact@v4
with:
name: synthea-workflow-results
path: |
${{ runner.temp }}/synthea-results
outputGlobal/
build-excel2fhir:
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
needs: [test, security-scan, synthea-workflow]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to GitHub Docker Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare Version
id: prep
run: |
echo "repository=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
- name: Build and push docker image for excel2fhir
uses: docker/build-push-action@v4
with:
context: .
file: docker/Dockerfile
tags: |
ghcr.io/${{ steps.prep.outputs.repository }}/excel2fhir:latest
ghcr.io/${{ steps.prep.outputs.repository }}/excel2fhir:${{ steps.prep.outputs.version }}
push: true