Skip to content

Commit b3a183d

Browse files
NPA-3895: Added GitHub action to run schema validation (#140)
* NPA-3895: Added script to validate schema * NPA-3895: Created make command * NPA-3897: Expanded GH action to run all
1 parent c1007bc commit b3a183d

16 files changed

+1567
-830
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Open API Validate
2+
"on":
3+
pull_request:
4+
branches: [master]
5+
permissions:
6+
contents: read
7+
jobs:
8+
GET_Consent:
9+
name: GET Consent test
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout repository
13+
uses: actions/checkout@v4
14+
15+
- name: Set up Python
16+
uses: actions/setup-python@v5
17+
with:
18+
python-version: 3.9
19+
20+
- name: Install Poetry
21+
shell: bash
22+
run: |
23+
pipx install poetry==1.8.5
24+
25+
- name: Install Script Packages with Poetry
26+
shell: bash
27+
run: |
28+
poetry install --all-extras
29+
30+
- name: Run Python script for all files
31+
run: |
32+
make schema-consent
33+
34+
GET_RelatedPerson:
35+
name: GET Related Person test
36+
runs-on: ubuntu-latest
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v4
40+
41+
- name: Set up Python
42+
uses: actions/setup-python@v5
43+
with:
44+
python-version: 3.9
45+
46+
- name: Install Poetry
47+
shell: bash
48+
run: |
49+
pipx install poetry==1.8.5
50+
51+
- name: Install Script Packages with Poetry
52+
shell: bash
53+
run: |
54+
poetry install --all-extras
55+
56+
- name: Run Python script for all files
57+
run: |
58+
make schema-related-person
59+
60+
POST_Questionnaire:
61+
name: POST questionnaire test
62+
runs-on: ubuntu-latest
63+
steps:
64+
- name: Checkout repository
65+
uses: actions/checkout@v4
66+
67+
- name: Set up Python
68+
uses: actions/setup-python@v5
69+
with:
70+
python-version: 3.9
71+
72+
- name: Install Poetry
73+
shell: bash
74+
run: |
75+
pipx install poetry==1.8.5
76+
77+
- name: Install Script Packages with Poetry
78+
shell: bash
79+
run: |
80+
poetry install --all-extras
81+
82+
- name: Run Python script for all files
83+
run: |
84+
make schema-questionnaire
85+
86+
87+
Errors:
88+
name: Error schema test
89+
runs-on: ubuntu-latest
90+
steps:
91+
- name: Checkout repository
92+
uses: actions/checkout@v4
93+
94+
- name: Set up Python
95+
uses: actions/setup-python@v5
96+
with:
97+
python-version: 3.9
98+
99+
- name: Install Poetry
100+
shell: bash
101+
run: |
102+
pipx install poetry==1.8.5
103+
104+
- name: Install Script Packages with Poetry
105+
shell: bash
106+
run: |
107+
poetry install --all-extras
108+
109+
- name: Run Python script for all files
110+
run: |
111+
make schema-errors

Makefile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,43 @@ smoketest-prod:
8383
test-prod:
8484
$(PROD_CMD) \
8585
--junitxml=test-report.xml \
86+
87+
# Run schema validation check
88+
GREEN := \033[32m
89+
RESET := \033[0m
90+
91+
92+
93+
schema-all:
94+
make schema-consent \
95+
schema-related-person \
96+
schema-questionnaire \
97+
schema-errors
98+
99+
schema-consent:
100+
@for file in specification/examples/responses/GET_Consent/*.yaml; do \
101+
echo "Processing $$file"; \
102+
poetry run python scripts/validate_schema.py consent "$$(realpath $$file)"; \
103+
echo -e "$(GREEN)Success!$(RESET)"; \
104+
done
105+
106+
schema-related-person:
107+
@for file in specification/examples/responses/GET_RelatedPerson/*.yaml; do \
108+
echo "Processing $$file"; \
109+
poetry run python scripts/validate_schema.py relatedperson "$$(realpath $$file)"; \
110+
echo -e "$(GREEN)Success!$(RESET)"; \
111+
done
112+
113+
schema-questionnaire:
114+
@for file in specification/examples/responses/POST_QuestionnaireResponse/*.yaml; do \
115+
echo "Processing $$file"; \
116+
poetry run python scripts/validate_schema.py operationoutcome "$$(realpath $$file)"; \
117+
echo -e "$(GREEN)Success!$(RESET)"; \
118+
done
119+
120+
schema-errors:
121+
@for file in specification/examples/responses/errors/*.yaml; do \
122+
echo "Processing $$file"; \
123+
poetry run python scripts/validate_schema.py operationoutcome "$$(realpath $$file)"; \
124+
echo -e "$(GREEN)Success!$(RESET)"; \
125+
done

poetry.lock

Lines changed: 1298 additions & 813 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ flake8 = "^3.7.9"
2626
black = "^24.3.0"
2727
pip-licenses = "^4.4.0"
2828
jinja2 = "^3.1.3"
29-
pyyaml = "^6.0.1"
29+
PyYAML = "^6.0.1"
3030
docopt = "^0.6.2"
3131
jsonpath-rw = "^1.4.0"
3232
semver = "^3.0.2"
@@ -35,3 +35,4 @@ pytest = "^8.2.0"
3535
coverage = "^7.5"
3636
aiohttp = "^3.10.2"
3737
pytest-asyncio = "^0.14.0"
38+
openapi-schema-validator = "^0.6.2"

scripts/validate_schema.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env python3
2+
"""
3+
validate_schema.py
4+
5+
Validates a given example file against the schema specification
6+
"""
7+
from yaml import safe_load
8+
from os import path
9+
from openapi_schema_validator import OAS30Validator
10+
import json
11+
import datetime
12+
import sys
13+
14+
EXAMPLES_PATH = "../"
15+
SCHEMA_FILE_PATH = "../specification/validated-relationships-service-api.yaml"
16+
SCHEMA_FILE = path.join(path.dirname(path.realpath(__file__)), SCHEMA_FILE_PATH)
17+
openapi_schema = {}
18+
19+
20+
def main(openapi_schema: dict):
21+
"""Main entrypoint"""
22+
args = sys.argv
23+
if len(args) != 3:
24+
print("Require schema reference and file to validate")
25+
exit()
26+
27+
schema = schema_lookup(args[1])
28+
file = args[2]
29+
if len(openapi_schema) == 0:
30+
openapi_schema = safe_load(load_file(SCHEMA_FILE))
31+
validate_consent(openapi_schema, schema, file)
32+
33+
34+
def schema_lookup(schema: str) -> str:
35+
"""Returns the schema reference to use
36+
37+
Args:
38+
schema (str): The type of record being validated
39+
40+
Returns:
41+
str: The schema reference
42+
"""
43+
schema = schema.lower()
44+
if schema == "consent":
45+
return "#/components/schemas/ConsentBundle"
46+
if schema == "relatedperson":
47+
return "#/components/schemas/RelatedPersonBundle"
48+
if schema == "operationoutcome":
49+
return "#/components/schemas/OperationOutcome"
50+
51+
52+
def validate_consent(schema: dict, schema_ref: str, file: str) -> None:
53+
schema["$ref"] = schema_ref
54+
json_contents = load_yaml_file_as_json(file)
55+
OAS30Validator(schema).validate(json_contents)
56+
57+
58+
def load_yaml_file_as_json(file: str) -> dict:
59+
"""Loads the specified yaml file
60+
61+
Args:
62+
file (str): Path to the file
63+
64+
Returns:
65+
dict: File converted as json dict
66+
"""
67+
patch = path.join(path.dirname(path.realpath(__file__)), file)
68+
yamlfile = safe_load(load_file(patch))
69+
jsonstr = json.dumps(
70+
yamlfile[next(iter(yamlfile))]["value"], default=date_converter
71+
)
72+
return json.loads(jsonstr)
73+
74+
75+
def date_converter(obj):
76+
"""Date and datetime converter to correctly render dates in json"""
77+
if isinstance(obj, datetime.datetime):
78+
return obj.replace(tzinfo=datetime.timezone.utc).isoformat()
79+
if isinstance(obj, datetime.date):
80+
return obj.isoformat()
81+
return obj
82+
83+
84+
def load_file(file_path) -> None:
85+
with open(file_path) as file:
86+
return file.read()
87+
88+
89+
if __name__ == "__main__":
90+
main(openapi_schema)

specification/examples/responses/GET_Consent/filtered-relationships-status-active-include-details.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ConsentMultipleRelationshipsStatusActiveIncludeDetailsBundle:
2727
- coding:
2828
- system: "http://terminology.hl7.org/CodeSystem/v3-RoleCode"
2929
code: PRN
30-
display: Parent
30+
display: parent
3131
- system: "http://terminology.hl7.org/CodeSystem/v3-RoleCode"
3232
code: MTH
3333
display: mother

specification/examples/responses/GET_Consent/multiple-relationships-include-performer-patient.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ConsentMultipleRelationshipsIncludePerformerPatientBundle:
2727
- coding:
2828
- system: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode'
2929
code: PRN
30-
display: Parent
30+
display: parent
3131
- system: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode'
3232
code: MTH
3333
display: mother

specification/examples/responses/GET_Consent/multiple-relationships-include-performer.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ConsentMultipleRelationshipsIncludePerformerBundle:
2727
- coding:
2828
- system: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode'
2929
code: PRN
30-
display: Parent
30+
display: parent
3131
- system: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode'
3232
code: MTH
3333
display: mother

specification/examples/responses/GET_Consent/single-mother-child-relationship-include-performer-patient.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ConsentSingleAdultChildRelationshipIncludePerformerPatientBundle:
2727
- coding:
2828
- system: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode'
2929
code: PRN
30-
display: Parent
30+
display: parent
3131
- system: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode'
3232
code: MTH
3333
display: mother

specification/examples/responses/GET_RelatedPerson/list_relationship_9000000017.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ ListRelationship9000000017:
2222
- coding:
2323
- code: MTH
2424
display: mother
25-
system: http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype
25+
system: http://terminology.hl7.org/CodeSystem/v3-RoleCode
2626
resourceType: RelatedPerson
2727
search:
2828
mode: match
@@ -41,7 +41,7 @@ ListRelationship9000000017:
4141
- coding:
4242
- code: MTH
4343
display: mother
44-
system: http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype
44+
system: http://terminology.hl7.org/CodeSystem/v3-RoleCode
4545
resourceType: RelatedPerson
4646
search:
4747
mode: match

0 commit comments

Comments
 (0)