-
Notifications
You must be signed in to change notification settings - Fork 5
/
action.yml
437 lines (390 loc) · 19.3 KB
/
action.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
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
name: Firely.Terminal (GitHub Actions)
description: Run Firely.Terminal and the offical FHIR Java Validator in a GitHub Actions pipeline
inputs:
PATH_TO_CONFORMANCE_RESOURCES:
description: 'Relative paths of the folder(s) containing FHIR Conformance resources (StructureDefinition, ValueSet, CodeSystem)'
required: true
PATH_TO_EXAMPLES:
description: 'Relative paths of the folder(s) containing examples for the FHIR Conformance resources defined by the project'
required: false
PATH_TO_QUALITY_CONTROL_RULES:
description: 'Relative path pointing to Quality Control rules. Path MUST not include the .rules.yaml part of the file. Runs minimal.rules.yaml by default.'
required: false
DOTNET_VALIDATION_ENABLED:
description: 'Boolean flag to run the .NET validator to validate conformance resources and examples'
required: false
default: true
JAVA_VALIDATION_ENABLED:
description: 'Boolean flag to run the offical HL7 Java validator to validate conformance resources and examples'
required: false
default: false
EXPECTED_FAILS:
description: 'Specify which steps in your validation workflow are expected to fail due to possible bugs in the validator(s). Allowed values: VALIDATION_CONFORMANCE_JAVA, VALIDATION_CONFORMANCE_DOTNET, VALIDATION_EXAMPLES_JAVA, VALIDATION_EXAMPLES_DOTNET'
required: false
OUTPUT_FORMAT:
description: 'Specify the format of the validation output: Allowed values: RAW, SUMMARY (produces a markdown compatible overview of all validation issues)'
default: 'RAW'
required: false
JAVA_VALIDATION_OPTIONS:
description: 'Custom options passed to the Java validator. See https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Validator'
required: false
SIMPLIFIER_USERNAME:
description: 'Simplifier email address (not username), needed for running Quality Control checks. Please use GitHub Secrets for this variable.'
required: true
SIMPLIFIER_PASSWORD:
description: 'Simplifier password, needed for running Quality Control checks. Please use GitHub Secrets for this variable.'
required: true
SUSHI_ENABLED:
description: 'Boolean flag to run fsh-sushi on the current repository to generated conformance resources based on FHIR shorthand'
required: false
default: false
SUSHI_OPTIONS:
description: 'Custom options passed to SUSHI. See https://www.npmjs.com/package/fsh-sushi'
required: false
FIRELY_TERMINAL_VERSION:
description: 'Version of Firely Terminal used for .NET-based validation'
default: '3.3.2'
required: true
JAVA_VALIDATOR_VERSION:
description: 'Version of org.hl7.fhir.core library used for Java-based validation'
default: '6.5.0'
required: true
SUSHI_VERSION:
description: 'Version of SUSHI used for compiling the FSH files'
default: '3.12.1'
required: true
# Validate all resources using Firely Terminal
runs:
using: "composite"
steps:
# --------------------------------------------------------------------------------------------------- #
# FIRELY TERMINAL RESTORE #
# --------------------------------------------------------------------------------------------------- #
# Firely.Terminal steps
- name: Check if .NET is installed
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED || $INPUT_SUSHI_ENABLED; then
if ! command -v dotnet &> /dev/null
then
echo "dotnet could not be found. Please see actions/setup-dotnet to set it up before running this action."
exit 1
fi
fi
shell: bash
env:
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
# Test Firely SDK version
- name: Check .NET SDK Version
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED || $INPUT_SUSHI_ENABLED; then
CHECK_DOTNET_VERSION=$(dotnet --version)
echo "DOTNET_VERSION: $CHECK_DOTNET_VERSION"
fi
shell: bash
env:
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
# Install Firely.Terminal
- name: Install Firely.Terminal
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED || $INPUT_SUSHI_ENABLED; then
if ! command -v fhir &> /dev/null
then
dotnet tool install --global Firely.Terminal --version $FIRELY_TERMINAL_VERSION > /dev/null
fi
fi
shell: bash
env:
FIRELY_TERMINAL_VERSION: ${{ inputs.FIRELY_TERMINAL_VERSION }}
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
# Test Firely.Terminal install
- name: Check Firely Terminal Version
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED || $INPUT_SUSHI_ENABLED; then
CHECK_FIRELY_TERMINAL_VERSION=$(fhir -v | tr '\n' ' ') # Print everything in a single line
echo "FIRELY_TERMINAL_VERSION: $CHECK_FIRELY_TERMINAL_VERSION"
fi
shell: bash
env:
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
# Simplifier Login
- name: Simplifier login
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED || $INPUT_SUSHI_ENABLED; then
fhir login email=$INPUT_SIMPLIFIER_USERNAME password=$INPUT_SIMPLIFIER_PASSWORD
fi
shell: bash
env:
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
INPUT_SIMPLIFIER_USERNAME: ${{ inputs.SIMPLIFIER_USERNAME }}
INPUT_SIMPLIFIER_PASSWORD: ${{ inputs.SIMPLIFIER_PASSWORD }}
# Restore all dependencies listed in the package.json file (need to be on the root level)
- name: FHIR Dependency restore
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED || $INPUT_SUSHI_ENABLED; then
if [ ! -f "package.json" ]; then
echo "package.json does not exist. Please add it to the root folder and add all project dependencies."
exit 1
fi
fhirVersions=("3.0.2" "4.0.1" "4.1.0" "4.6.0")
for fhirVersion in ${fhirVersions[@]}; do
fhirVersionFoundInPackageJson=$(cat package.json | jq '.fhirVersions | index('\"$fhirVersion\"')')
if [[ ! "$fhirVersionFoundInPackageJson" = null ]]; then
echo "Found FHIR version $fhirVersion in package.json"
if [[ "$fhirVersion" = "3.0.2" ]]; then
fhir spec R3
break
elif [[ "$fhirVersion" = "4.0.1" ]]; then
fhir spec R4
break
elif [[ "$fhirVersion" = "4.1.0" ]]; then
fhir spec R4B
break
elif [[ "$fhirVersion" = "4.6.0" ]]; then
fhir spec R5
break
else
echo "This FHIR version is currently not supported.";
exit 1
fi
fi
done
echo "Attempting to restore package dependencies based on package.json ..."
FHIR_RESTORE=$((fhir restore | tr '\n' ' ')|| true) # Print everything in a single line
if [[ "$FHIR_RESTORE" == *"Cannot restore"* ]]; then
echo $FHIR_RESTORE
exit 1
fi
echo "Restore of package.json was successful: $FHIR_RESTORE"
fi
shell: bash
env:
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
# --------------------------------------------------------------------------------------------------- #
# SUSHI #
# --------------------------------------------------------------------------------------------------- #
- name: Check if npm is installed
run: |
if $INPUT_SUSHI_ENABLED; then
if ! command -v npm &> /dev/null
then
echo "npm could not be found. Please see actions/setup-node to set it up before running this action."
exit 1
fi
fi
shell: bash
env:
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
- name: Check npm Version
run: |
if $INPUT_SUSHI_ENABLED; then
CHECK_NPM_VERSION=$(npm --version)
echo "NPM_VERSION: $CHECK_NPM_VERSION"
fi
shell: bash
env:
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
- name: Install fsh-sushi
run: |
if $INPUT_SUSHI_ENABLED; then
sudo chown -R $USER /usr/local/lib/node_modules
sudo npm install -g fsh-sushi@$SUSHI_VERSION
fi
shell: bash
env:
SUSHI_VERSION: ${{ inputs.SUSHI_VERSION }}
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
- name: Check SUSHI version
run: |
if $INPUT_SUSHI_ENABLED; then
sushi -v
fi
shell: bash
env:
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
- name: Generate conformance resources with SUSHI
run: |
if $INPUT_SUSHI_ENABLED; then
sushi $INPUT_SUSHI_OPTIONS
fi
shell: bash
env:
INPUT_SUSHI_ENABLED: ${{ inputs.SUSHI_ENABLED }}
INPUT_SUSHI_OPTIONS: ${{ inputs.SUSHI_OPTIONS }}
# --------------------------------------------------------------------------------------------------- #
# .NET VALIDATOR #
# --------------------------------------------------------------------------------------------------- #
# Run Quality Control checks incl. validation
- name: Run Quality Control checks
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED; then
echo "Running quality control checks incl. validation based on Firely Terminal ..."
fhir check $INPUT_PATH_TO_QUALITY_CONTROL_RULES
fi
shell: bash
env:
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
INPUT_PATH_TO_QUALITY_CONTROL_RULES: ${{ inputs.PATH_TO_QUALITY_CONTROL_RULES }}
- name: Report Success - .NET Validator
run: |
if $INPUT_DOTNET_VALIDATION_ENABLED; then
echo "Finished validation using .NET validator (Conformance resources) ..."
fi
shell: bash
env:
INPUT_DOTNET_VALIDATION_ENABLED: ${{ inputs.DOTNET_VALIDATION_ENABLED }}
#Examples are currently not used as Firely Terminal can't differentiate between these two in QC checks.
# --------------------------------------------------------------------------------------------------- #
# JAVA Validator #
# --------------------------------------------------------------------------------------------------- #
# Offical HL7 Java validator steps
- name: Check if Java is installed
run: |
if $INPUT_JAVA_VALIDATION_ENABLED; then
if ! command -v java &> /dev/null
then
echo "java could not be found. Please see actions/setup-java to set it up before running this action."
exit 1
fi
fi
shell: bash
env:
INPUT_JAVA_VALIDATION_ENABLED: ${{ inputs.JAVA_VALIDATION_ENABLED }}
- name: Download Java Validator
run: |
if $INPUT_JAVA_VALIDATION_ENABLED; then
CHECK_JAVA_VERSION=$(java -version 2>&1 | head -1 | cut -d'"' -f2)
echo "JAVA_VERSION: $CHECK_JAVA_VERSION"
wget -q https://github.com/hapifhir/org.hl7.fhir.core/releases/download/$JAVA_VALIDATOR_VERSION/validator_cli.jar
echo "JAVA_VALIDATOR_VERSION: $JAVA_VALIDATOR_VERSION"
fi
shell: bash
env:
JAVA_VALIDATOR_VERSION: ${{ inputs.JAVA_VALIDATOR_VERSION }}
INPUT_JAVA_VALIDATION_ENABLED: ${{ inputs.JAVA_VALIDATION_ENABLED }}
- name: Install jq
run: |
if $INPUT_JAVA_VALIDATION_ENABLED; then
sudo apt-get update > /dev/null
sudo apt-get install --no-install-recommends -y jq findutils curl ca-certificates > /dev/null
fi
shell: bash
env:
INPUT_JAVA_VALIDATION_ENABLED: ${{ inputs.JAVA_VALIDATION_ENABLED }}
- name: Validate all conformance resources in scope of the repository
run: |
print_output_details () {
levels=($(echo "$1" | grep -P '(Error|Warning|Information)'| grep -oP '(?<=\s)[^\s]+(?=\s@)'))
locations=($(echo "$1" | grep -oP '(?<=@\s)[^:]*(?=\s)'))
messages=($(echo "$1" | grep -oP '(?<=\s:\s).*'))
for i in "${!levels[@]}"; do
echo "Level: ${levels[$i]}"
echo "Location: ${locations[$i]}"
echo "Message: ${messages[$i]}"
echo -e ""
done
}
if $INPUT_JAVA_VALIDATION_ENABLED; then
echo "Starting validation using Java validator (Conformance resources) ..."
IG_DEPENDENCIES=$(jq '.dependencies | to_entries | map("-ig " + .key + "#" + .value) | join(" ")' package.json)
for p in $INPUT_PATH_TO_CONFORMANCE_RESOURCES; # Get combined path to conformance resources, we want to provide all other directories as context for the current validation
do
LOCAL_IG_PARAMETERS+="-ig $GITHUB_WORKSPACE/$p "
done
for p in $INPUT_PATH_TO_CONFORMANCE_RESOURCES;
do
# Ensure directory ends with "/"
if [[ ! "$p" =~ .*/$ ]]; then
p="$p/"
fi
UNESCPAED_IG_DEPENDENCIES=$(echo $IG_DEPENDENCIES | tr -d '"')
if echo $INPUT_EXPECTED_FAILS | grep -w -q VALIDATION_CONFORMANCE_JAVA; then
javaValidatorOutput=$(java -jar validator_cli.jar $GITHUB_WORKSPACE/$p*.xml $GITHUB_WORKSPACE/$p*.json -version $FHIR_VERSION $INPUT_JAVA_VALIDATION_OPTIONS $UNESCPAED_IG_DEPENDENCIES $LOCAL_IG_PARAMETERS|| true)
else
javaValidatorOutput=$(java -jar validator_cli.jar $GITHUB_WORKSPACE/$p*.xml $GITHUB_WORKSPACE/$p*.json -version $FHIR_VERSION $INPUT_JAVA_VALIDATION_OPTIONS $UNESCPAED_IG_DEPENDENCIES $LOCAL_IG_PARAMETERS)
fi
if echo $INPUT_OUTPUT_FORMAT | grep -w -q RAW; then
echo "$javaValidatorOutput"
else
SAVEIFS=$IFS
IFS=$'\n'
pathToValidatedResource=$(echo "$javaValidatorOutput" | grep -P '\-\-\s' || true)
pathToValidatedResource=($(echo "$pathToValidatedResource" | grep -oP '(?<=--\s).+(?=\s--)' || true))
if [ ${#pathToValidatedResource[@]} -eq 0 ]; then # Single resource validation only, no section header with resource path will be printed by the Java validator
echo "----"
pathToValidatedResource=$(echo "$javaValidatorOutput" | grep -oP '(?<=Validate\s).+(?=\s[0-9][0-9]:[0-9][0-9].[0-9]{0,})')
echo "Path to valiated resource: ${pathToValidatedResource}"
echo "----"
print_output_details "$javaValidatorOutput"
else # We encountered a directory with more than a single resource in it, Java validator output will differ (each resource will be printed with its own section)
resourceBoundaries=$(echo "$javaValidatorOutput" | grep -b -oP '(?<!-)-{2}\s' || true)
resourceBoundaries=($(echo "$resourceBoundaries" | cut -d: -f1))
for i in "${!resourceBoundaries[@]}"; do
echo "----"
echo "Path to valiated resource: ${pathToValidatedResource[$i]}"
echo "----"
if [[ ! -z "${resourceBoundaries[$i+1]:-}" ]]; then
offsetDiff=$(expr ${resourceBoundaries[$i+1]} - ${resourceBoundaries[$i]})
resourceOutput=$(echo "$javaValidatorOutput" | tail -c+${resourceBoundaries[$i]} | head -c+${offsetDiff})
else
resourceOutput=$(echo "$javaValidatorOutput" | tail -c+${resourceBoundaries[$i]})
fi
levels=($(echo "$resourceOutput" | grep -P '(Error|Warning|Information)'| grep -oP '(?<=\s)[^\s]+(?=\s@)'))
locations=($(echo "$resourceOutput" | grep -oP '(?<=@\s)[^:]*(?=\s)'))
messages=($(echo "$resourceOutput" | grep -oP '(?<=\s:\s).*'))
for i in "${!levels[@]}"; do
echo "Level: ${levels[$i]}"
echo "Location: ${locations[$i]}"
echo "Message: ${messages[$i]}"
echo -e ""
done
done
fi
IFS=$SAVEIFS
fi
done
fi
echo "Finished validation using Java validator (Conformance resources) ..."
shell: bash
env:
FHIR_VERSION: "4.0"
INPUT_PATH_TO_CONFORMANCE_RESOURCES: ${{ inputs.PATH_TO_CONFORMANCE_RESOURCES }}
INPUT_JAVA_VALIDATION_ENABLED: ${{ inputs.JAVA_VALIDATION_ENABLED }}
INPUT_EXPECTED_FAILS: ${{ inputs.EXPECTED_FAILS }}
INPUT_OUTPUT_FORMAT: ${{ inputs.OUTPUT_FORMAT }}
INPUT_JAVA_VALIDATION_OPTIONS: ${{ inputs.JAVA_VALIDATION_OPTIONS }}
- name: Validate all example resources in scope of the repository
run: |
if $INPUT_JAVA_VALIDATION_ENABLED; then
IG_DEPENDENCIES=$(jq '.dependencies | to_entries | map("-ig " + .key + "#" + .value) | join(" ")' package.json)
for p in $INPUT_PATH_TO_CONFORMANCE_RESOURCES; # Get combined path to conformance resources, we want to validate against the current version of the conformance resources
do
COMBINED_IG_PARAMETERS+="-ig $GITHUB_WORKSPACE/$p "
done
for p in $PATH_TO_EXAMPLES;
do
# Ensure directory ends with "/"
if [[ ! "$p" =~ .*/$ ]]; then
p="$p/"
fi
UNESCPAED_IG_DEPENDENCIES=$(echo $IG_DEPENDENCIES | tr -d '"')
if echo $INPUT_EXPECTED_FAILS | grep -w -q VALIDATION_EXAMPLES_JAVA; then
java -jar validator_cli.jar $GITHUB_WORKSPACE/$p*.xml $GITHUB_WORKSPACE/$p*.json -version $FHIR_VERSION $INPUT_JAVA_VALIDATION_OPTIONS $UNESCPAED_IG_DEPENDENCIES $COMBINED_IG_PARAMETERS || true
else
java -jar validator_cli.jar $GITHUB_WORKSPACE/$p*.xml $GITHUB_WORKSPACE/$p*.json -version $FHIR_VERSION $INPUT_JAVA_VALIDATION_OPTIONS $UNESCPAED_IG_DEPENDENCIES $COMBINED_IG_PARAMETERS
fi
done
fi
shell: bash
env:
INPUT_PATH_TO_CONFORMANCE_RESOURCES: ${{ inputs.PATH_TO_CONFORMANCE_RESOURCES }}
PATH_TO_EXAMPLES: ${{ inputs.PATH_TO_EXAMPLES }}
FHIR_VERSION: "4.0"
INPUT_JAVA_VALIDATION_ENABLED: ${{ inputs.JAVA_VALIDATION_ENABLED }}
INPUT_EXPECTED_FAILS: ${{ inputs.EXPECTED_FAILS }}
INPUT_JAVA_VALIDATION_OPTIONS: ${{ inputs.JAVA_VALIDATION_OPTIONS }}