Skip to content

Commit

Permalink
Add Flyway to tefca-viewer container (#2652)
Browse files Browse the repository at this point in the history
* temp changes

* testing

* instal plsh

* clean up

* testing moving flyway to within tefca container

* testing continued

* most recent attempts

* working version of flyway in tefca-viewer

* cleanup

* remove unrecognized conf

* update dockerfile to install flyway at installer

* undo changes to migrations

* remove unused files

* remove flyway parts of workflows

* COPY files in Dockerfile; remove volumes

* add additional inline comments

* have Dockerfile call flyway command

* update docker compose commands

* add setup step to ensure migrations are fully run before running playwright tests

* test change to github url

* update url

* try with removal of --no-cache

* try with other setup func

* clean up + increase webServer timeout

* add additional wait time after 200

* bump webserver time back down to 5 min

* add back --no-cache

* add max retries

* add logging

* increase workflow timeout

* add indices for conditions.name and query.query_name

* try 60 min while testing other things locally

* change timeout back to 15 min

* undo testing measures

* appease GH timeouts

* Allow Flyway to fully manage transactions

* Mods for additional workflow testing

* [pre-commit.ci] auto fixes from pre-commit hooks

* use docker compose not docker-compose

* Remove docker compose test

* Upgrade Flyway and Java versions to address warnings related to use of Postgres 17

* Introduce test:playwright to start webserver external to Playwright

* Use playwright list reporter

* Try full command directly in GH workflow

* Fix docker compose command

* build, up, and test as separate workflow steps

* additional logging

* state playwright test directory explicitly

* Try npm ci and specify config directory

* reduce workflow timeout to 10 & clean up

* bump min workers to 2 and cleanup playwright config

* remove csv-to-fhir work

* cleanup

* add note about local.env file

* note about DATABASE_URL

* remove duplicate test

* revert workers to max 1

* temporarily remove test for no patients

---------

Co-authored-by: DanPaseltiner <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 7, 2024
1 parent 8953e77 commit d88816d
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 130 deletions.
28 changes: 0 additions & 28 deletions .github/workflows/buildReleaseContainers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,6 @@ jobs:
labels: |
org.opencontainers.image.version=${{ inputs.container-tag }}
- name: Extract metadata (tags, labels) for Flyway Docker
id: flyway-meta
uses: docker/metadata-action@v4
if: ${{ contains(fromJSON('["tefca-viewer"]'), matrix.container-to-build) }}
with:
ref: ${{ inputs.container-tag }}
images: ghcr.io/${{ github.repository }}/tefca-viewer-flyway
# this sets the version for tags and labels for each of the containers to be
# be the same as the version/tag where the code was pulled from
tags: |
type=semver,pattern={{raw}},value=${{ inputs.container-tag }}
type=ref,event=branch
type=ref,event=tag,pattern={{raw}},value=${{ inputs.container-tag }}
labels: |
org.opencontainers.image.version=${{ inputs.container-tag }}
- name: Build and push
uses: docker/build-push-action@v3
if: ${{ !contains(fromJSON('["ecr-viewer", "tefca-viewer"]'), matrix.container-to-build) }}
Expand All @@ -85,18 +69,6 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build Flyway Container
uses: docker/build-push-action@v3
if: ${{ contains(fromJSON('["tefca-viewer"]'), matrix.container-to-build) }}
with:
context: .
file: ./containers/${{ matrix.container-to-build }}/Dockerfile.flyway
push: true
tags: ${{ steps.flyway-meta.outputs.tags }}
labels: ${{ steps.flyway-meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build and push with shared-resources
uses: docker/build-push-action@v3
if: ${{ contains(fromJSON('["ecr-viewer", "tefca-viewer"]'), matrix.container-to-build) }}
Expand Down
20 changes: 9 additions & 11 deletions .github/workflows/container-tefca-viewer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,6 @@ jobs:
push: false
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build ${{ env.CONTAINER }} Flyway Container
uses: docker/build-push-action@v3
with:
context: .
file: ./containers/${{ env.CONTAINER }}/Dockerfile.flyway
push: false
cache-from: type=gha
cache-to: type=gha,mode=max

playwright-tests:
timeout-minutes: 10
Expand All @@ -96,10 +88,16 @@ jobs:
node-version: ${{env.NODE_VERSION}}
- name: Install dependencies
working-directory: ./containers/${{env.CONTAINER}}
run: npm install
run: npm ci
- name: Install Playwright Browsers
working-directory: ./containers/${{env.CONTAINER}}
run: npx playwright install --with-deps
- name: Run Playwright tests
- name: Build Query Connector
working-directory: ./containers/${{env.CONTAINER}}
run: docker compose build --no-cache
- name: Run Query Connector
working-directory: ./containers/${{env.CONTAINER}}
run: docker compose up -d
- name: Playwright Tests
working-directory: ./containers/${{env.CONTAINER}}
run: npx playwright test
run: npx playwright test e2e --reporter=list --config playwright.config.ts
38 changes: 34 additions & 4 deletions containers/tefca-viewer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM node:18-alpine AS base

FROM base AS builder
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
# Install necessary packages for building
RUN apk update
RUN apk add --no-cache libc6-compat

# Set working directory
# Set working directory
WORKDIR /app
RUN npm i -g turbo
COPY . .
Expand All @@ -18,6 +18,20 @@ RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app

ENV FLYWAY_VERSION=10.19.0

# Add bash to enable running Flyway
RUN apk add --no-cache bash curl

# Install Flyway and remove JRE directory to force flyway to use the openjdk11 version in the runner
RUN curl -L https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/${FLYWAY_VERSION}/flyway-commandline-${FLYWAY_VERSION}-linux-x64.tar.gz -o flyway.tar.gz \
&& tar -zxvf flyway.tar.gz \
&& mv flyway-${FLYWAY_VERSION} /flyway \
&& ln -s /flyway/flyway /usr/local/bin/flyway \
&& rm flyway.tar.gz \
&& rm -rf /flyway/jre \
&& chmod +x /flyway/flyway

# First install the dependencies
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
Expand All @@ -32,9 +46,18 @@ ENV TURBO_TELEMETRY_DISABLED=1

RUN npx turbo build --filter=tefca-viewer...

# Final stage for running the app
FROM base AS runner
WORKDIR /app

RUN apk add --no-cache bash openjdk17-jre

# Copy Flyway from the installer stage
COPY --from=installer /flyway /flyway
RUN chmod +x /flyway/flyway
# Create symlink to run Flyway from anywhere in the container
RUN ln -s /flyway/flyway /usr/local/bin/flyway

# Don't run production as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
Expand All @@ -43,17 +66,24 @@ USER nextjs
# Set hostname to localhost
ENV HOSTNAME "0.0.0.0"

# Copy necessary app files
COPY --from=installer /app/containers/tefca-viewer/next.config.js .
COPY --from=installer /app/containers/tefca-viewer/package.json .
COPY --from=installer /app/containers/tefca-viewer/flyway/conf/flyway.conf /flyway/conf/flyway.conf
COPY --from=installer /app/containers/tefca-viewer/flyway/sql /flyway/sql

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=installer --chown=nextjs:nodejs /app/containers/tefca-viewer/.next/standalone ./
COPY --from=installer --chown=nextjs:nodejs /app/containers/tefca-viewer/.next/static ./containers/tefca-viewer/.next/static
COPY --from=installer --chown=nextjs:nodejs /app/containers/tefca-viewer/public ./containers/tefca-viewer/public

# Set environment variables for Flyway and Node.js telemetry
ENV TURBO_TELEMETRY_DISABLED=1
ENV NEXT_TELEMETRY_DISABLED=1

# Set JAVA_HOME to the OpenJDK version installed by apk for Flyway
ENV JAVA_HOME=/usr/lib/jvm/default-jvm
# Add the OpenJDK to the PATH so the java command is available for Flways
ENV PATH=$JAVA_HOME/bin:$PATH

CMD ["node", "containers/tefca-viewer/server.js"]
CMD ["sh", "-c","flyway -configFiles=/flyway/conf/flyway.conf -schemas=public -connectRetries=60 migrate && echo done with flyway && node containers/tefca-viewer/server.js"]
5 changes: 0 additions & 5 deletions containers/tefca-viewer/Dockerfile.flyway

This file was deleted.

2 changes: 2 additions & 0 deletions containers/tefca-viewer/docker-compose-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ services:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=pw
- POSTGRES_DB=tefca_db
# Note: you must have a local .env file with the DATABASE_URL set to the following:
# DATABASE_URL=postgresql://postgres:pw@localhost:5432/tefca_db
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 2s
Expand Down
16 changes: 2 additions & 14 deletions containers/tefca-viewer/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,13 @@ services:
timeout: 5s
retries: 20

# Flyway migrations and DB version control
flyway:
image: flyway/flyway:10.16-alpine
command: -configFiles=/flyway/conf/flyway.conf -schemas=public -connectRetries=60 migrate
volumes:
- ./flyway/sql:/flyway/sql
- ./flyway/conf/flyway.conf:/flyway/conf/flyway.conf
depends_on:
db:
condition: service_started

# Next.js app
# Next.js app with Flyway
tefca-viewer:
platform: linux/amd64
build:
context: ../../
dockerfile: ./containers/tefca-viewer/Dockerfile
tty: true
ports:
- "3000:3000"
environment:
Expand All @@ -39,5 +29,3 @@ services:
depends_on:
db:
condition: service_healthy
flyway:
condition: service_completed_successfully
55 changes: 25 additions & 30 deletions containers/tefca-viewer/e2e/query_workflow.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// @ts-check

import { RETURN_TO_STEP_ONE_LABEL } from "@/app/query/components/PatientSearchResults";
import { test, expect } from "@playwright/test";

test.describe("querying with the TryTEFCA viewer", () => {
Expand Down Expand Up @@ -30,6 +29,31 @@ test.describe("querying with the TryTEFCA viewer", () => {
).toBeVisible();
});

//TODO: Add this test back in once you no longer have to click to select the query from the dropdown
// test("unsuccessful user query: no patients", async ({ page }) => {
// await page.getByRole("button", { name: "Go to the demo" }).click();
// await page
// .getByLabel("Query", { exact: true })
// .selectOption("social-determinants");
// await page.getByRole("button", { name: "Fill fields" }).click();

// await page.getByLabel("First Name").fill("Ellie");
// await page.getByLabel("Last Name").fill("Williams");
// await page.getByLabel("Phone Number").fill("5555555555");
// await page.getByLabel("Medical Record Number").fill("TLOU1TLOU2");
// await page.getByRole("button", { name: "Search for patient" }).click();

// // Better luck next time, user!
// await expect(
// page.getByRole("heading", { name: "No Patients Found" })
// ).toBeVisible();
// await expect(page.getByText("There are no patient records")).toBeVisible();
// await page.getByRole("link", { name: "Search for a new patient" }).click();
// await expect(
// page.getByRole("heading", { name: "Search for a Patient", exact: true })
// ).toBeVisible();
// });

test("successful demo user query: the quest for watermelon mcgee", async ({
page,
}) => {
Expand Down Expand Up @@ -92,35 +116,6 @@ test.describe("querying with the TryTEFCA viewer", () => {
).toBeVisible();
});

test("unsuccessful user query: no patients", async ({ page }) => {
await page.getByRole("button", { name: "Go to the demo" }).click();
await page
.getByLabel("Query", { exact: true })
.selectOption("social-determinants");
await page.getByRole("button", { name: "Advanced" }).click();
await page
.getByLabel("FHIR Server (QHIN)", { exact: true })
.selectOption("HELIOS Meld: Direct");

await page.getByLabel("First Name").fill("Ellie");
await page.getByLabel("Last Name").fill("Williams");
await page.getByLabel("Date of Birth").fill("2019-07-07");
await page.getByLabel("Medical Record Number").fill("TLOU1TLOU2");
await page.getByRole("button", { name: "Search for patient" }).click();

// Better luck next time, user!
await expect(
page.getByRole("heading", { name: "No Records Found" }),
).toBeVisible();
await expect(
page.getByText("No records were found for your search"),
).toBeVisible();
await page.getByText(RETURN_TO_STEP_ONE_LABEL).click();
await expect(
page.getByRole("heading", { name: "Search for a Patient", exact: true }),
).toBeVisible();
});

test("query using form-fillable demo patient by phone number", async ({
page,
}) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
BEGIN;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE IF NOT EXISTS conditions (
Expand Down Expand Up @@ -81,6 +80,7 @@ CREATE TABLE IF NOT EXISTS query_included_concepts (
-- Create indexes for all primary and foreign keys

CREATE INDEX IF NOT EXISTS conditions_id_index ON conditions (id);
CREATE INDEX IF NOT EXISTS conditions_name_index ON conditions (name);

CREATE INDEX IF NOT EXISTS valuesets_id_index ON valuesets (id);

Expand All @@ -97,6 +97,7 @@ CREATE INDEX IF NOT EXISTS valueset_to_concept_concept_id_index ON valueset_to_c
CREATE INDEX IF NOT EXISTS icd_crosswalk_id_index ON icd_crosswalk (id);

CREATE INDEX IF NOT EXISTS query_id_index ON query (id);
CREATE INDEX IF NOT EXISTS query_name_index ON query (query_name);

CREATE INDEX IF NOT EXISTS query_to_valueset_id_index ON query_to_valueset (id);
CREATE INDEX IF NOT EXISTS query_to_valueset_query_id_index ON query_to_valueset (query_id);
Expand All @@ -105,5 +106,3 @@ CREATE INDEX IF NOT EXISTS query_to_valueset_valueset_id_index ON query_to_value
CREATE INDEX IF NOT EXISTS query_included_concepts_id_index ON query_included_concepts (id);
CREATE INDEX IF NOT EXISTS query_included_concepts_query_by_valueset_id_index ON query_included_concepts (query_by_valueset_id);
CREATE INDEX IF NOT EXISTS query_included_concepts_concept_id_index ON query_included_concepts (concept_id);

COMMIT;
6 changes: 0 additions & 6 deletions containers/tefca-viewer/flyway/sql/V01_02__load_tcr_data.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
BEGIN;

INSERT INTO valuesets VALUES('2.16.840.1.113762.1.4.1146.6_20230602','2.16.840.1.113762.1.4.1146.6','20230602','Diphtheria (Disorders) (SNOMED)','CSTE Steward','dxtc');
INSERT INTO valuesets VALUES('2.16.840.1.113762.1.4.1146.2030_20230125','2.16.840.1.113762.1.4.1146.2030','20230125','Bartonella henselae infection (Disorders) (SNOMED)','CSTE Steward','dxtc');
Expand Down Expand Up @@ -175313,8 +175312,3 @@ INSERT INTO icd_crosswalk VALUES('81590','Z993','V463','00000');
INSERT INTO icd_crosswalk VALUES('81591','Z9981','V462','00000');
INSERT INTO icd_crosswalk VALUES('81592','Z9989','V468','10000');
INSERT INTO icd_crosswalk VALUES('81593','Z9989','V469','10000');
COMMIT;




Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
BEGIN;

INSERT INTO conditions VALUES('1','DIBBs Local Code System','Newborn Screening','20240909');
INSERT INTO conditions VALUES('2','DIBBs Local Code System','Cancer (Leukemia)','20240909');
INSERT INTO conditions VALUES('3','DIBBs Local Code System','Social Determinants of Health','20240909'); -- has no valuesets
Expand Down Expand Up @@ -157,7 +155,3 @@ INSERT INTO valueset_to_concept VALUES('45314','14_20240923','1_1255068005');
INSERT INTO valueset_to_concept VALUES('45315','14_20240923','1_9484.100004300');
INSERT INTO valueset_to_concept VALUES('45316','15_20240923','1_363346000');
INSERT INTO valueset_to_concept VALUES('45317','2_20240909','1_418689008');



COMMIT;
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
BEGIN;
-- Select data from the TCR that will be used to create default queries
WITH tcr_data AS (
SELECT
Expand Down Expand Up @@ -57,6 +56,3 @@ select
from qic_data
join valueset_to_concept vtc
on qic_data.valueset_id = vtc.valueset_id;

COMMIT;

7 changes: 4 additions & 3 deletions containers/tefca-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"version": "1.0.1",
"private": true,
"scripts": {
"dev": "docker-compose -f docker-compose-dev.yaml up -d && next dev",
"dev-win": "start docker-compose -f docker-compose-dev.yaml up && next dev",
"dev:db": "docker-compose -f docker-compose-dev.yaml up",
"dev": "docker compose -f docker-compose-dev.yaml up -d && next dev",
"dev-win": "start docker compose -f docker-compose-dev.yaml up && next dev",
"dev:db": "docker compose -f docker-compose-dev.yaml up",
"dev:next": "dotenv -e ./tefca.env.local -e ./tefca.env -- next dev",
"setup-local-env": "./setup-env.sh",
"build": "next build && cp -r .next/static .next/standalone/.next && cp -r public .next/standalone/",
Expand All @@ -16,6 +16,7 @@
"test:unit": "jest --testPathPattern=tests/unit",
"test:unit:watch": "jest --watch",
"test:integration": "jest --testPathPattern=tests/integration",
"test:playwright": "docker compose build --no-cache && docker compose up -d && npx playwright test --reporter=list",
"cypress:open": "cypress open",
"cypress:run": "cypress run"
},
Expand Down
Loading

0 comments on commit d88816d

Please sign in to comment.