diff --git a/.github/workflows/deploy-server-dev.yml b/.github/workflows/deploy-server-dev.yml new file mode 100644 index 00000000000..cee10bfb848 --- /dev/null +++ b/.github/workflows/deploy-server-dev.yml @@ -0,0 +1,18 @@ +name: Deploy API to Development + +on: + push: + branches: ["infoway"] + workflow_dispatch: # Allows manual triggering + +jobs: + call-template: + name: Development Environment + uses: deploy-server-template.yml + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.GLOBAL_DEV_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.GLOBAL_DEV_AWS_SECRET_ACCESS_KEY }} + AWS_ACCOUNT_ID: ${{ secrets.GLOBAL_DEV_AWS_ACCOUNT_ID }} + with: + environment: dev + AWS_REGION: ${{ vars.GLOBAL_DEV_AWS_REGION }} diff --git a/.github/workflows/deploy-server-prod.yml b/.github/workflows/deploy-server-prod.yml new file mode 100644 index 00000000000..8fdfdb62af6 --- /dev/null +++ b/.github/workflows/deploy-server-prod.yml @@ -0,0 +1,16 @@ +name: Deploy API to Production + +on: + workflow_dispatch: # Allows manual triggering + +jobs: + call-template: + name: Production Environment + uses: deploy-server-template.yml + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.GLOBAL_PROD_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.GLOBAL_PROD_AWS_SECRET_ACCESS_KEY }} + AWS_ACCOUNT_ID: ${{ secrets.GLOBAL_PROD_AWS_ACCOUNT_ID }} + with: + environment: prod + AWS_REGION: ${{ vars.GLOBAL_PROD_AWS_REGION }} diff --git a/.github/workflows/deploy-server-template.yml b/.github/workflows/deploy-server-template.yml new file mode 100644 index 00000000000..315feb4c047 --- /dev/null +++ b/.github/workflows/deploy-server-template.yml @@ -0,0 +1,145 @@ +name: Deployment Template + +on: + workflow_call: + inputs: + environment: + required: true + type: string + description: 'Deployment to Environment?' + default: dev + AWS_REGION: + required: true + type: string + default: "ca-central-1" + secrets: + AWS_ACCOUNT_ID: + required: true + AWS_ACCESS_KEY_ID: + required: true + AWS_SECRET_ACCESS_KEY: + required: true + +jobs: + Deploy: + name: Deploy ${{ inputs.environment }} + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + env: + EB_APP_NAME: matchbox + EB_ENV_NAME: matchbox-server-${{ inputs.environment }}-env + ECR_REPOSITORY: infoway/matchbox-server +# AWS_ACCESS_KEY_ID: ${{ secrets.GLOBAL_DEV_AWS_ACCESS_KEY_ID }} +# AWS_REGION: ca-central-1 +# AWS_SECRET_ACCESS_KEY: ${{ secrets.GLOBAL_DEV_AWS_SECRET_ACCESS_KEY }} + BUCKET_NAME: infoway-${{ inputs.environment }}-github-deployment + ECR_URL: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com + MAVEN_CACHE_FOLDER: ~/.m2/repository + + steps: + - name: Print environment variable + run: | + echo "EB_APP_NAME is $EB_APP_NAME" + echo "EB_ENV_NAME is $EB_ENV_NAME" + echo "ECR_REPOSITORY is $ECR_REPOSITORY" + echo "AWS_REGION is $AWS_REGION" + echo "ECR_URL is $ECR_URL" + + - name: Checkout Code + uses: actions/checkout@v5 + with: + fetch-depth: 1 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: "21" + distribution: "temurin" + + - name: Generate Today's Date + run: | + echo "TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%S.%3NZ')" >> $GITHUB_ENV + + - name: Get GIT Short Hash + run: | + echo "SHORT_HASH=${GITHUB_SHA:0:8}" >> $GITHUB_ENV + + - name: Set short commit hash + run: echo "Short Hash ${{ env.SHORT_HASH }}" + + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: ${{ env.MAVEN_CACHE_FOLDER }} + key: maven-${{ runner.os }}-${{ env.EB_ENV_NAME }} + restore-keys: | + maven-${{ runner.os }}-${{ env.EB_ENV_NAME }} + + - name: Build EB Version + run: | + echo "EB_APP_VERSION=${{ env.EB_APP_NAME }}-${{ env.SHORT_HASH }}" >> $GITHUB_ENV + + - name: Generate Dockerrun.aws.json + run: | + echo '{ + "AWSEBDockerrunVersion": "1", + "Image": { + "Name": "${{ env.ECR_URL }}/${{ env.ECR_REPOSITORY }}:${{ env.SHORT_HASH }}", + "Update": "true" + }, + "Ports": [ + { "ContainerPort": 8080 } + ] + }' > Dockerrun.aws.json + + - name: Build ZIP Filename + run: | + echo "ZIP_FILE=${{ env.EB_APP_VERSION }}.zip" >> $GITHUB_ENV + + - name: Zip deployment bundle + run: | + cat Dockerrun.aws.json + zip -r "${{ env.ZIP_FILE }}" Dockerrun.aws.json + + - name: Build with Maven without tests + run: mvn package -DskipTests -Dmaven.repo.local="${{ env.MAVEN_CACHE_FOLDER }}" + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ inputs.AWS_REGION }} + + - name: Login to Amazon ECR + run: | + aws ecr get-login-password | docker login --username AWS --password-stdin "${{ env.ECR_URL }}" + + - name: Build Docker image + run: | + docker build --build-arg ENVIRONMENT=${{ inputs.environment }} --build-arg VERSION=${{ env.SHORT_HASH }} --build-arg TIMESTAMP=${{ env.TIMESTAMP }} -t ${{ env.ECR_REPOSITORY }}:latest . + docker tag ${{ env.ECR_REPOSITORY }}:latest "${{ env.ECR_URL }}/${{ env.ECR_REPOSITORY }}:${{ inputs.environment }}" + docker tag ${{ env.ECR_REPOSITORY }}:latest "${{ env.ECR_URL }}/${{ env.ECR_REPOSITORY }}:${{ env.SHORT_HASH }}" + + - name: Push to Amazon ECR + run: | + docker push "${{ env.ECR_URL }}/${{ env.ECR_REPOSITORY }}:${{ inputs.environment }}" + docker push "${{ env.ECR_URL }}/${{ env.ECR_REPOSITORY }}:${{ env.SHORT_HASH }}" + + - name: Upload deploy.zip to S3 + run: | + aws s3 cp "${{ env.ZIP_FILE }}" "s3://${{ env.BUCKET_NAME }}/${{ env.ZIP_FILE }}" + + - name: Create EB application version + continue-on-error: true + run: | + aws elasticbeanstalk create-application-version \ + --application-name ${{ env.EB_APP_NAME }} \ + --version-label ${{ env.EB_APP_VERSION }} \ + --source-bundle S3Bucket="${{ env.BUCKET_NAME }}",S3Key="${{ env.ZIP_FILE }}" + + - name: Update EB environment + run: | + aws elasticbeanstalk update-environment \ + --environment-name ${{ env.EB_ENV_NAME }} \ + --version-label ${{ env.EB_APP_VERSION }} diff --git a/matchbox-engine/pom.xml b/matchbox-engine/pom.xml index 18307308c11..2e9d55f235f 100644 --- a/matchbox-engine/pom.xml +++ b/matchbox-engine/pom.xml @@ -6,7 +6,7 @@ matchbox health.matchbox - 4.0.15 + 4.0.15-Infoway matchbox-engine diff --git a/matchbox-server/pom.xml b/matchbox-server/pom.xml index 8cb757cb9cc..ac8b311c586 100644 --- a/matchbox-server/pom.xml +++ b/matchbox-server/pom.xml @@ -5,7 +5,7 @@ matchbox health.matchbox - 4.0.15 + 4.0.15-Infoway matchbox-server @@ -28,11 +28,6 @@ postgresql - - org.postgresql - postgresql - - ca.uhn.hapi.fhir @@ -46,7 +41,7 @@ org.slf4j jcl-over-slf4j - + @@ -240,7 +235,7 @@ dev.langchain4j langchain4j-anthropic 1.0.0-beta1 - + dev.langchain4j langchain4j-google-ai-gemini diff --git a/matchbox-server/start.sh b/matchbox-server/start.sh new file mode 100755 index 00000000000..95d467bd0e1 --- /dev/null +++ b/matchbox-server/start.sh @@ -0,0 +1 @@ +java -Xms1024m -Xmx24576m -Dspring.config.additional-location=file:with-ca/application.yaml -jar target/matchbox.jar diff --git a/matchbox-server/with-ca-conformance/application.yaml b/matchbox-server/with-ca-conformance/application.yaml new file mode 100644 index 00000000000..bbdd9712942 --- /dev/null +++ b/matchbox-server/with-ca-conformance/application.yaml @@ -0,0 +1,48 @@ +server: + servlet: + context-path: /matchboxv3 +spring: + datasource: + url: "" + username: + password: + driverClassName: org.postgresql.Driver + + # database connection pool size + hikari: + maximum-pool-size: 10 + jpa: + properties: + hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect +matchbox: + fhir: + context: + fhirVersion: 4.0.1 + txServer: http://tx.fhir.org + onlyOneEngine: false + httpReadOnly: true +hapi: + fhir: + # server_address: https://matchbox.apibox.ca/matchboxv3/fhir + implementationguides: + fhir_r4_core: + name: hl7.fhir.r4.core + version: 4.0.1 + fhir_terminology: + name: hl7.terminology + version: 5.4.0 + fhir_extensions: + name: hl7.fhir.uv.extensions.r4 + version: 1.0.0 + fhir-baseline-1-1-8: + name: hl7.fhir.ca.baseline + version: 1.1.8 + hl7-fhir-extension-r4: + name: hl7.fhir.uv.extensions.r4 + version: 5.1.0 + hl7-terminology-r4: + name: hl7.terminology.r4 + version: 6.0.2 + psca-2-0-0-DFT-Ballot: + name: ca.infoway.io.psca + version: 2.0.0-DFT-Ballot diff --git a/matchbox-server/with-ca-conformance/fhir-settings.json b/matchbox-server/with-ca-conformance/fhir-settings.json new file mode 100644 index 00000000000..45c26ec4c96 --- /dev/null +++ b/matchbox-server/with-ca-conformance/fhir-settings.json @@ -0,0 +1,10 @@ +{ + "servers": [ + { + "url": "https://terminologystandardsservice.ca/tx/fhir", + "type": "fhir", + "authenticationType": "apikey", + "apikey": "request from https://infocentral.infoway-inforoute.ca/en/system-account-requisition-process" + } + ] +} \ No newline at end of file diff --git a/matchbox-server/with-ca/Procfile b/matchbox-server/with-ca/Procfile new file mode 100644 index 00000000000..e4c95306613 --- /dev/null +++ b/matchbox-server/with-ca/Procfile @@ -0,0 +1 @@ +web: java -Dspring.config.additional-location=file:with-ca/application.yaml -jar matchbox.jar \ No newline at end of file diff --git a/matchbox-server/with-ca/application-shared.yaml b/matchbox-server/with-ca/application-shared.yaml new file mode 100644 index 00000000000..5f411ff155b --- /dev/null +++ b/matchbox-server/with-ca/application-shared.yaml @@ -0,0 +1,18 @@ +server: + servlet: + context-path: /matchboxv3 +matchbox: + fhir: + context: + fhirVersion: 4.0.1 + txServer: http://tx.fhir.org + onlyOneEngine: false + httpReadOnly: true +hapi: + fhir: + server_address: https://matchbox.apibox.ca/matchboxv3/fhir + implementationguides: + psca: + name: ca.infoway.io.psca + version: 2.0.1-DFT-Ballot + url: file:///home/echiu/Downloads/package.tgz diff --git a/matchbox-server/with-ca/application.yaml b/matchbox-server/with-ca/application.yaml index 0a08d58a485..e1be7b028a0 100644 --- a/matchbox-server/with-ca/application.yaml +++ b/matchbox-server/with-ca/application.yaml @@ -1,29 +1,170 @@ server: servlet: context-path: /matchboxv3 +# spring: +# datasource: +# url: '' +# username: +# password: +# driverClassName: org.postgresql.Driver + +# # database connection pool size +# hikari: +# maximum-pool-size: 10 + jpa: + properties: + hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect +matchbox: + fhir: + context: + fhirVersion: 4.0.1 + txServer: http://tx.fhir.org + onlyOneEngine: false + suppressWarnInfo: + ca.infoway.io.erec: + - "Constraint failed: dom-6:" + - "regex:URL value '(.+)' does not resolve" + - "regex:ValueSet '(.+)' not found" + - "regex:This element does not match any known slice defined in the profile (.*)" + - "regex:Reference to draft CodeSystem (.+)" + ca.infoway.io.psca: + - "Constraint failed: dom-6:" + - "regex:URL value '(.+)' does not resolve" + - "regex:ValueSet '(.+)' not found" + - "regex:This element does not match any known slice defined in the profile (.*)" + - "regex:Reference to draft CodeSystem (.+)" + - "regex:A definition for CodeSystem '(.+)' could not be found, so the code cannot be validated" + - "Best Practice Recommendation: In general, all observations should have a performer" + - "Best Practice Recommendation: In general, all observations should have an effective[x] ()" + - "regex:Validate Observation against (.+)" + - "regex:Can't find '(.+)' in the bundle" + - "regex:UCUM Codes that contain human readable annotations like (.+) can be misleading (.e.g. they are ignored when comparing units).(.+)" + - "regex:A definition for the value Set '(.+)' could not be found" + - "UNABLE_TO_CHECK_IF_THE_PROVIDED_CODES_ARE_IN_THE_VALUE_SET" + ca.ab.fhir.psab: + - "Constraint failed: dom-6:" + - "regex:URL value '(.+)' does not resolve" + - "regex:ValueSet '(.+)' not found" + - "regex:This element does not match any known slice defined in the profile (.*)" + - "regex:Reference to draft CodeSystem (.+)" + - "regex:A definition for CodeSystem '(.+)' could not be found, so the code cannot be validated" + - "Best Practice Recommendation: In general, all observations should have a performer" + - "Best Practice Recommendation: In general, all observations should have an effective[x] ()" + - "regex:Validate Observation against (.+)" + - "regex:Can't find '(.+)' in the bundle" + - "regex:UCUM Codes that contain human readable annotations like (.+) can be misleading (.e.g. they are ignored when comparing units).(.+)" + - "regex:A definition for the value Set '(.+)' could not be found" + - "UNABLE_TO_CHECK_IF_THE_PROVIDED_CODES_ARE_IN_THE_VALUE_SET" + ca.on.oh.patient-summary: + - "Constraint failed: dom-6:" + - "regex:URL value '(.+)' does not resolve" + - "regex:ValueSet '(.+)' not found" + - "regex:This element does not match any known slice defined in the profile (.*)" + - "regex:Reference to draft CodeSystem (.+)" + - "regex:A definition for CodeSystem '(.+)' could not be found, so the code cannot be validated" + - "Best Practice Recommendation: In general, all observations should have a performer" + - "Best Practice Recommendation: In general, all observations should have an effective[x] ()" + - "regex:Validate Observation against (.+)" + - "regex:Can't find '(.+)' in the bundle" + - "regex:UCUM Codes that contain human readable annotations like (.+) can be misleading (.e.g. they are ignored when comparing units).(.+)" + - "regex:A definition for the value Set '(.+)' could not be found" + - "UNABLE_TO_CHECK_IF_THE_PROVIDED_CODES_ARE_IN_THE_VALUE_SET" + httpReadOnly: true hapi: fhir: - server_address: http://localhost:8080/matchboxv3/fhir + server_address: https://matchbox.apibox.ca/matchboxv3/fhir implementationguides: fhir_r4_core: name: hl7.fhir.r4.core version: 4.0.1 - url: classpath:/hl7.fhir.r4.core.tgz + fhir_terminology: + name: hl7.terminology + version: 5.4.0 fhir_extensions: name: hl7.fhir.uv.extensions.r4 - version: 5.2.0 - url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz - fhir_terminology: + version: 1.0.0 + fhir-baseline-1-1-8: + name: hl7.fhir.ca.baseline + version: 1.1.8 + hl7-fhir-extension-r4: + name: hl7.fhir.uv.extensions.r4 + version: 5.1.0 + hl7-terminology-r4: name: hl7.terminology.r4 - version: 6.3.0 - url: classpath:/hl7.terminology.r4#6.3.0.tgz - cda: + version: 6.0.2 + ips110: + name: hl7.fhir.uv.ips + version: 1.1.0 + ips200bt: + name: hl7.fhir.uv.ips + version: 2.0.0-ballot + mhd422: + name: ihe.iti.mhd + version: 4.2.2 + mhd410: + name: ihe.iti.mhd + version: 4.1.0 + pixm300: + name: ihe.iti.pixm + version: 3.0.0 + pdqm300: + name: ihe.iti.pdqm + version: 3.0.0 + pmir150: + name: ihe.iti.pmir + version: 1.5.0 + psca: name: ca.infoway.io.psca - version: 2.0.0-DFT-Ballot - staticLocation: file:/apps/ -matchbox: - fhir: - context: - txServer: http://tx.fhir.org - txServerCache: false - txLog: /tmp/testlog.txt + version: 2.0.3-DFT-Ballot + psca-211-dft: + name: ca.infoway.io.psca + version: 2.1.1-DFT + psab: + name: ca.ab.fhir.psab + version: 1.1.0 + pson: + name: ca.on.oh.patient-summary + version: 0.11.0 + erec: + name: ca.infoway.io.erec + version: 1.0.3-dft-projectathon + erec-on: + name: ca.on.oh-eReferral-eConsult + version: 0.12.0-alpha1.0.7 + url: file:///home/webapp/igs/ca.on.oh-ereferral-econsult-0.12.0-alpha1.0.7-snapshots.tgz + cafex210: + name: ca.infoway.io.cafex + version: 2.1.0-DFT-preBallot + cabase118: + name: hl7.fhir.ca.baseline + version: 1.1.8 + uscore610: + name: hl7.fhir.us.core + version: 6.1.0 + bulkdata200: + name: hl7.fhir.uv.bulkdata + version: 2.0.0 + ipa100: + name: hl7.fhir.uv.ipa + version: 1.0.0 + sdc300: + name: hl7.fhir.uv.sdc + version: 3.0.0 + smart210: + name: hl7.fhir.uv.smart-app-launch + version: 2.1.0 + term540: + name: hl7.terminology + version: 5.4.0 + format120: + name: ihe.formatcode.fhir + version: 1.2.0 + balp113: + name: ihe.iti.balp + version: 1.1.3 + phinvads0120: + name: us.cdc.phinvads + version: 0.12.0 + vsac0110: + name: us.nlm.vsac + version: 0.11.0 diff --git a/pom.xml b/pom.xml index e74c9c0c091..1729e9128a7 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ health.matchbox matchbox - 4.0.15 + 4.0.15-Infoway pom matchbox An open-source implementation to support testing and implementation of FHIR based solutions and map or @@ -154,7 +154,7 @@ commons-io commons-io - + ca.uhn.hapi.fhir @@ -506,6 +506,21 @@ ${tomcat_embed_version} + + + + + + + + + + + + + + + com.squareup.okhttp3 okhttp