Skip to content

Commit b8ed085

Browse files
authored
Merge pull request #249 from hms-dbmi/development
PPM-766 - Migration to FHIR R4 and GCP Healthcare API
2 parents 3a0c976 + ae11abc commit b8ed085

40 files changed

+7090
-889
lines changed

.github/workflows/release.yml

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Release Build
2+
3+
on:
4+
push:
5+
branches: [ master, development ]
6+
workflow_dispatch:
7+
inputs:
8+
force:
9+
type: boolean
10+
default: false
11+
12+
jobs:
13+
test-image:
14+
uses: hms-dbmi/actions/.github/workflows/test-image-build.yml@main
15+
secrets:
16+
DOCKER_HUB_USERNAME: ${{ secrets.BLHMSDBMI_DOCKERHUB_USERNAME }}
17+
DOCKER_HUB_PASSWORD: ${{ secrets.BLHMSDBMI_DOCKERHUB_PASSWORD }}
18+
with:
19+
repository: ${{ github.repository }}
20+
commit: ${{ github.sha }}
21+
22+
scan-image:
23+
uses: hms-dbmi/actions/.github/workflows/scan.yml@main
24+
secrets:
25+
DOCKER_HUB_USERNAME: ${{ secrets.BLHMSDBMI_DOCKERHUB_USERNAME }}
26+
DOCKER_HUB_PASSWORD: ${{ secrets.BLHMSDBMI_DOCKERHUB_PASSWORD }}
27+
with:
28+
repository: ${{ github.repository }}
29+
commit: ${{ github.sha }}
30+
31+
metadata:
32+
runs-on: "ubuntu-latest"
33+
outputs:
34+
branch: ${{ steps.set_branch.outputs.branch }}
35+
force: ${{ steps.force.outputs.force }}
36+
steps:
37+
- name: Set the current branch name
38+
shell: bash
39+
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
40+
id: set_branch
41+
- name: Manage force input
42+
id: force
43+
env:
44+
FORCE_INPUT: ${{ inputs.force }}
45+
run: echo "force=${FORCE_INPUT:=false}" >> $GITHUB_OUTPUT
46+
47+
deploy:
48+
uses: hms-dbmi/actions/.github/workflows/dbmisvc-app-deploy.yml@main
49+
needs:
50+
- "test-image"
51+
- "metadata"
52+
secrets:
53+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54+
with:
55+
filename: "${{ github.event.repository.name }}-${{ needs.metadata.outputs.branch }}.zip"
56+
app: ${{ github.event.repository.name }}
57+
role: ${{ vars[ format('BLHMSDBMI_PPM_DEPLOYMENT_{0}_ROLE_ARN', needs.metadata.outputs.branch) ] }}
58+
bucket: ${{ vars[ format('BLHMSDBMI_PPM_DEPLOYMENT_{0}_BUCKET', needs.metadata.outputs.branch) ] }}
59+
force: ${{ fromJson(needs.metadata.outputs.force) }}

.github/workflows/scan.yml

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
name: Scan
22

33
on:
4-
push:
5-
branches: [ master, development ]
64
pull_request:
75
branches: [ master, development ]
86
schedule:

.github/workflows/test.yml

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
name: Test Image Build
22

33
on:
4-
push:
5-
branches: [ master, development ]
64
pull_request:
75
branches: [ master, development ]
86
workflow_dispatch:

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -340,5 +340,7 @@ $RECYCLE.BIN/
340340
# Windows shortcuts
341341
*.lnk
342342

343+
# Node modules
344+
node_modules
343345

344346
# End of https://www.gitignore.io/api/osx,linux,django,python,windows,pycharm,pycharm+iml,pycharm+all

.pre-commit-config.yaml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
minimum_pre_commit_version: "2.13.0"
22
repos:
33
- repo: https://github.com/pre-commit/pre-commit-hooks.git
4-
rev: v4.5.0
4+
rev: v4.6.0
55
hooks:
66
- id: trailing-whitespace
77
- id: mixed-line-ending
@@ -11,6 +11,10 @@ repos:
1111
- repo: https://github.com/jazzband/pip-tools
1212
rev: 7.4.1
1313
hooks:
14+
- id: pip-compile
15+
name: pip-compile test-requirements.in
16+
args: [test-requirements.in, --upgrade, --generate-hashes, --allow-unsafe, --output-file, test-requirements.txt]
17+
files: ^test-requirements\.(in|txt)$
1418
- id: pip-compile
1519
name: pip-compile dev-requirements.in
1620
args: [dev-requirements.in, --upgrade, --generate-hashes, --allow-unsafe, --output-file, dev-requirements.txt]

.releaserc

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"branches": [
3+
"master",
4+
"main",
5+
"+([0-9])?(.{+([0-9]),x}).x",
6+
{"name": "development", "channel": "pre/rc", "prerelease": "rc"},
7+
{"name": "beta", "prerelease": true},
8+
{"name": "alpha", "prerelease": true}
9+
],
10+
"plugins": [
11+
"@semantic-release/commit-analyzer",
12+
"@semantic-release/release-notes-generator",
13+
["@semantic-release/changelog", {
14+
"changelogFile": "CHANGELOG.md"
15+
}],
16+
["@semantic-release/exec", {
17+
"prepareCmd": "sed -ie \"s/^version.*/version = \\x22${nextRelease.version}\\x22/g\" pyproject.toml"
18+
}],
19+
["@semantic-release/git", {
20+
"assets": ["pyproject.toml", "CHANGELOG.md"]
21+
}],
22+
["@semantic-release/github", {
23+
"successComment": false,
24+
"failComment": false,
25+
"failTitle": false
26+
}]
27+
],
28+
"preset": "angular"
29+
}

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# 1.0.0-rc.1 (2024-07-25)
2+
3+
4+
### Bug Fixes
5+
6+
* **ci:** Refactored deployment; added versioning; passes app version to Sentry initialization ([76f3c2e](https://github.com/hms-dbmi/fhirquestionnaire/commit/76f3c2ed11d28f02abf10547710c7165bb5aebc3))
7+
* **dockerfile:** Fixed incorrect phantomjs library being used ([ea4414a](https://github.com/hms-dbmi/fhirquestionnaire/commit/ea4414a613f4265209029853c1b21d44edf9092b))
8+
* **requirements:** Updated Python requirements ([f3b1ab4](https://github.com/hms-dbmi/fhirquestionnaire/commit/f3b1ab48bdfccd5885ea60d43a3a1b83c66bba52))
9+
* **requirements:** Updated Python requirements ([a02bbd5](https://github.com/hms-dbmi/fhirquestionnaire/commit/a02bbd53a4423fd7de71f9d992cf545740f5928c))
10+
* **requirements:** Updated Python requirements ([11cca88](https://github.com/hms-dbmi/fhirquestionnaire/commit/11cca88467a621a7e85dd8f2ff1455cfef461e5b))
11+
* **requirements:** Updated Python requirements ([ef1a121](https://github.com/hms-dbmi/fhirquestionnaire/commit/ef1a121db605d937b8139826d88f972cefeaf087))
12+
* **requirements:** Updated Python requirements ([3713378](https://github.com/hms-dbmi/fhirquestionnaire/commit/37133781b68e6688cb20e74d8ef6e4437bed7467))
13+
* **requirements:** Updated Python requirements ([638cc84](https://github.com/hms-dbmi/fhirquestionnaire/commit/638cc84be3b3ce04e1ad6beaefaa344fff3e6746))
14+
* **requirements:** Updated Python requirements ([3154ba8](https://github.com/hms-dbmi/fhirquestionnaire/commit/3154ba8c7932d5787578d1c7d10090ea3ecc6552))
15+
* **requirements:** Updated Python requirements ([6a7e453](https://github.com/hms-dbmi/fhirquestionnaire/commit/6a7e45327346c36359d9787c30b5911e478b783f))
16+
* **requirements:** Updated Python requirements ([9351a10](https://github.com/hms-dbmi/fhirquestionnaire/commit/9351a10cac12580dd1d6c55593e4e5ed6cdec2b3))
17+
* **requirements:** Updated Python requirements ([b391c77](https://github.com/hms-dbmi/fhirquestionnaire/commit/b391c77ea9cadd67a99f0e6cd29a0eceab8d86ec))
18+
* **requirements:** Updated Python requirements ([68281b6](https://github.com/hms-dbmi/fhirquestionnaire/commit/68281b689de4d2b70141e924905f3b07c9bf6008))
19+
* **requirements:** Updated Python requirements ([7d4e6d9](https://github.com/hms-dbmi/fhirquestionnaire/commit/7d4e6d9fd1f7355c627b7364a98c4de17c476792))

Dockerfile

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM hmsdbmitc/dbmisvc:debian12-slim-python3.11-0.6.1 AS builder
1+
FROM hmsdbmitc/dbmisvc:debian12-slim-python3.11-0.6.2 AS builder
22

33
# Install requirements
44
RUN apt-get update \
@@ -22,7 +22,23 @@ RUN pip install -U wheel \
2222
&& pip wheel -r /requirements.txt \
2323
--wheel-dir=/root/wheels
2424

25-
FROM hmsdbmitc/dbmisvc:debian12-slim-python3.11-0.6.1
25+
FROM hmsdbmitc/dbmisvc:debian12-slim-python3.11-0.6.2
26+
27+
ARG APP_NAME="ppm-questionnaire"
28+
ARG APP_CODENAME="fhirquestionnaire"
29+
ARG VERSION
30+
ARG COMMIT
31+
ARG DATE
32+
33+
LABEL org.label-schema.schema-version=1.0 \
34+
org.label-schema.vendor="HMS-DBMI" \
35+
org.label-schema.version=${VERSION} \
36+
org.label-schema.name=${APP_NAME} \
37+
org.label-schema.build-date=${DATE} \
38+
org.label-schema.description="PPM questionnaire service" \
39+
org.label-schema.url="https://github.com/hms-dbmi/fhirquestionnaire" \
40+
org.label-schema.vcs-url="https://github.com/hms-dbmi/fhirquestionnaire" \
41+
org.label-schema.vcf-ref=${COMMIT}
2642

2743
# Copy PhantomJS binary
2844
COPY --from=builder /tmp/phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs
@@ -62,6 +78,10 @@ ENV DBMI_PARAMETER_STORE_PREFIX=ppm.questionnaire.${DBMI_ENV}
6278
ENV DBMI_PARAMETER_STORE_PRIORITY=true
6379
ENV DBMI_AWS_REGION=us-east-1
6480

81+
ENV DBMI_APP_NAME=${APP_NAME}
82+
ENV DBMI_APP_CODENAME=${APP_CODENAME}
83+
ENV DBMI_APP_VERSION=${VERSION}
84+
ENV DBMI_APP_COMMIT=${COMMIT}
6585
ENV DBMI_APP_WSGI=fhirquestionnaire
6686
ENV DBMI_APP_ROOT=/app
6787
ENV DBMI_APP_DOMAIN=p2m2.dbmi.hms.harvard.edu

app/api/urls.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# Wire up our API using automatic URL routing.
1010
# Additionally, we include login URLs for the browsable API.
1111
urlpatterns = [
12-
re_path(r'^consent/(?P<study>[\w\d-]+)/(?P<ppm_id>[\d]+)/?$', views.ConsentView.as_view(), name='consent'),
12+
re_path(r'^consent/(?P<study>[\w\d-]+)/(?P<ppm_id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[\d]+)/?$', views.ConsentView.as_view(), name='consent'),
1313
re_path(r'^consent/(?P<study>[\w\d-]+)/?$', views.ConsentsView.as_view(), name='consents'),
1414
re_path(r'^questionnaire/?$', views.QuestionnaireView.as_view(), name='questionnaire'),
1515
re_path(r'^questionnaire/(?P<questionnaire_id>[\w\d-]+)/?$', views.QuestionnaireView.as_view(), name='questionnaire'),

app/api/views.py

+9-19
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def get(self, request, study, ppm_id, format=None):
4949

5050
try:
5151
# Check patient
52-
if not FHIR.query_patient(patient=ppm_id):
52+
if not FHIR.get_patient(patient=ppm_id):
5353
return Response(f'Participant {ppm_id} does not exist', status=status.HTTP_404_NOT_FOUND)
5454

5555
# Check FHIR
@@ -82,7 +82,7 @@ def post(self, request, study, ppm_id=None, format=None):
8282

8383
try:
8484
# Check patient
85-
if not FHIR.query_patient(patient=ppm_id):
85+
if not FHIR.get_patient(patient=ppm_id):
8686
return Response(f'Participant {ppm_id} does not exist', status=status.HTTP_404_NOT_FOUND)
8787

8888
# Check if we should overwrite
@@ -140,18 +140,8 @@ def delete_consent_document_reference(request, study, ppm_id, document_reference
140140
# Get their consent composition
141141
composition = FHIR.get_consent_composition(patient=ppm_id, study=study)
142142
if not composition:
143-
compositions = FHIR.query_consent_compositions(patient=ppm_id)
144-
if not compositions:
145-
logger.error(f'PPM/{study}/{ppm_id}: No consent compositions')
146-
return False
147-
148-
elif len(compositions) > 1:
149-
logger.error(f'PPM/{study}/{ppm_id}: Too many generic consent '
150-
f'compositions: {[r["resource"]["id"] for r in compositions]}')
151-
return False
152-
153-
else:
154-
composition = compositions[0]
143+
logger.error(f'PPM/{study}/{ppm_id}: No consent compositions')
144+
return False
155145

156146
# Update it
157147
if FHIR.update_consent_composition(patient=ppm_id, study=study, composition=composition):
@@ -189,7 +179,7 @@ def create_consent_document_reference(request, study, ppm_id=None):
189179
ppm_id = FHIR.query_patient_id(get_jwt_email(request=request, verify=False))
190180

191181
# Pull their record
192-
bundle = FHIR.query_participant(patient=ppm_id, flatten_return=True)
182+
participant = FHIR.get_participant(patient=ppm_id, flatten_return=True)
193183

194184
# Get study title
195185
study_title = PPM.Study.title(study)
@@ -204,7 +194,7 @@ def create_consent_document_reference(request, study, ppm_id=None):
204194
# Submit consent PDF
205195
logger.debug(f"PPM/{study}: Rendering consent with template: {template_name}")
206196
response = render_pdf(f'People-Powered Medicine {study_title} Consent', request, template_name,
207-
context=bundle.get('composition'), options={})
197+
context=participant.get('composition'), options={})
208198

209199
# Hash the content
210200
hash = hashlib.md5(response.content).hexdigest()
@@ -409,9 +399,9 @@ def get(self, request, questionnaire_id=None, format=None):
409399
if questionnaire_id:
410400

411401
# Try to fetch it
412-
questionnaire = FHIR.get_questionnaire(
413-
questionnaire_id=questionnaire_id,
414-
flatten_return=False
402+
questionnaire = FHIR.fhir_read(
403+
resource_type="Questionnaire",
404+
resource_id=questionnaire_id,
415405
)
416406

417407
# Return it or 404

app/consent/fhir/example-signature.json

+27
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,33 @@
66
"subjectType": [
77
"patient"
88
],
9+
"useContext": [
10+
{
11+
"code": {
12+
"system": "http://terminology.hl7.org/CodeSystem/usage-context-type",
13+
"code": "program",
14+
"display": "Program"
15+
},
16+
"valueReference": {"reference": "ResearchStudy/ppm-example"}
17+
},
18+
{
19+
"code": {
20+
"system": "http://terminology.hl7.org/CodeSystem/usage-context-type",
21+
"code": "task",
22+
"display": "Workflow Task"
23+
},
24+
"valueCodeableConcept": {
25+
"coding": [
26+
{
27+
"system": "https://peoplepoweredmedicine.org/fhir/questionnaire/context",
28+
"code": "ppm-example",
29+
"display": "ppm-example"
30+
}
31+
],
32+
"text": "ppm-example"
33+
}
34+
}
35+
],
936
"item": [
1037
{
1138
"linkId": "display-1",

app/consent/fhir/guardian-signature-part-1.json

+27
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,33 @@
1414
"subjectType": [
1515
"patient"
1616
],
17+
"useContext": [
18+
{
19+
"code": {
20+
"system": "http://terminology.hl7.org/CodeSystem/usage-context-type",
21+
"code": "program",
22+
"display": "Program"
23+
},
24+
"valueReference": {"reference": "ResearchStudy/ppm-asd"}
25+
},
26+
{
27+
"code": {
28+
"system": "http://terminology.hl7.org/CodeSystem/usage-context-type",
29+
"code": "task",
30+
"display": "Workflow Task"
31+
},
32+
"valueCodeableConcept": {
33+
"coding": [
34+
{
35+
"system": "https://peoplepoweredmedicine.org/fhir/questionnaire/context",
36+
"code": "ppm-asd",
37+
"display": "ppm-asd"
38+
}
39+
],
40+
"text": "ppm-asd"
41+
}
42+
}
43+
],
1744
"item": [
1845
{
1946
"linkId": "display-1",

0 commit comments

Comments
 (0)