Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup e2e tests actions to test MSF server and latest OpenMRS release depending on the served server url #110

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
231 changes: 231 additions & 0 deletions .github/workflows/run-e2e-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
name: Run E2E Tests on PRs

on:
workflow_dispatch:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]

jobs:
build:
runs-on: ubuntu-latest
outputs:
patient_management_ref: ${{steps.refs.outputs.patient_management}}
patient_chart_ref: ${{steps.refs.outputs.patient_chart}}
esm_core_ref: ${{steps.refs.outputs.esm_core}}

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Extract branch name
shell: bash
run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_ENV

- name: Extract version numbers from the spa-build-config.json file
id: refs
run: bash distro/e2e_test_support_files/extract_tag_numbers.sh

- name: Build and Run Containers
run: docker-compose -f distro/e2e_test_support_files/docker-compose-build.yml up -d

- name: Wait for the backend to start
run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost/openmrs/login.htm)" != "200" ]]; do sleep 10; done

- name: Commit and export Containers
run: sh distro/e2e_test_support_files/commit_and_export_images.sh

- name: cache docker images
uses: actions/cache@v4
with:
path: e2e_release_env_images.tar.gz
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}

run-patient-management-e2e-tests:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4

- name: Create Temporary Directory to Download Docker Images
id: tempdir
run: echo "tmpdir=$(mktemp -d)" >> "$GITHUB_OUTPUT"

- name: Get cached Docker Images
uses: actions/cache/restore@v3
with:
path: e2e_release_env_images.tar.gz
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}

- name: Load Docker Images
run: |
cp e2e_release_env_images.tar.gz ${{ steps.tempdir.outputs.tmpdir }}
gzip -d ${{ steps.tempdir.outputs.tmpdir }}/e2e_release_env_images.tar.gz
docker load --input ${{ steps.tempdir.outputs.tmpdir }}/e2e_release_env_images.tar
docker image ls -a

- name: Spin up an OpenMRS Instance
run: docker-compose up -d
working-directory: distro/e2e_test_support_files

- name: Checkout to the Repo's Tag
uses: actions/checkout@v4
with:
repository: openmrs/openmrs-esm-patient-management
ref: ${{ needs.build.outputs.patient_management_ref }}
path: e2e_repo

- name: Copy test environment variables
run: cp example.env .env
working-directory: e2e_repo

- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: yarn install --immutable
working-directory: e2e_repo

- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: e2e_repo

- name: Wait for the OpenMRS instance to start
run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:8080/openmrs/login.htm)" != "200" ]]; do sleep 10; done

- name: Run E2E tests
run: yarn playwright test
working-directory: e2e_repo

- name: Upload Report
uses: actions/upload-artifact@v3
if: always()
with:
name: report-patient-management
path: e2e_repo/playwright-report/
retention-days: 30

run-patient-chart-e2e-tests:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4

- name: Create Temporary Directory to Download Docker Images
id: tempdir
run: echo "tmpdir=$(mktemp -d)" >> "$GITHUB_OUTPUT"

- name: Get cached Docker Images
uses: actions/cache/restore@v3
with:
path: e2e_release_env_images.tar.gz
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}

- name: Load Docker Images
run: |
cp e2e_release_env_images.tar.gz ${{ steps.tempdir.outputs.tmpdir }}
gzip -d ${{ steps.tempdir.outputs.tmpdir }}/e2e_release_env_images.tar.gz
docker load --input ${{ steps.tempdir.outputs.tmpdir }}/e2e_release_env_images.tar
docker image ls -a

- name: Spin up an OpenMRS Instance
run: docker-compose up -d
working-directory: distro/e2e_test_support_files

- name: Checkout to the Repo's Tag
uses: actions/checkout@v4
with:
repository: openmrs/openmrs-esm-patient-chart
ref: ${{ needs.build.outputs.patient_chart_ref }}
path: e2e_repo

- name: Copy test environment variables
run: cp example.env .env
working-directory: e2e_repo

- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: yarn install --immutable
working-directory: e2e_repo

- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: e2e_repo

- name: Wait for the OpenMRS instance to start
run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:8080/openmrs/login.htm)" != "200" ]]; do sleep 10; done

- name: Run E2E tests
run: yarn playwright test
working-directory: e2e_repo

- name: Upload Report
uses: actions/upload-artifact@v3
if: always()
with:
name: report-patient-chart
path: e2e_repo/playwright-report/
retention-days: 30


run-esm-core-e2e-tests:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4

- name: Create Temporary Directory to Download Docker Images
id: tempdir
run: echo "tmpdir=$(mktemp -d)" >> "$GITHUB_OUTPUT"

- name: Get cached Docker Images
uses: actions/cache/restore@v3
with:
path: e2e_release_env_images.tar.gz
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}

- name: Load Docker Images
run: |
cp e2e_release_env_images.tar.gz ${{ steps.tempdir.outputs.tmpdir }}
gzip -d ${{ steps.tempdir.outputs.tmpdir }}/e2e_release_env_images.tar.gz
docker load --input ${{ steps.tempdir.outputs.tmpdir }}/e2e_release_env_images.tar
docker image ls -a

- name: Spin up an OpenMRS Instance
run: docker-compose up -d
working-directory: distro/e2e_test_support_files

- name: Checkout to the Repo's Tag
uses: actions/checkout@v4
with:
repository: openmrs/openmrs-esm-core
ref: ${{ needs.build.outputs.esm_core_ref }}
path: e2e_repo

- name: Copy test environment variables
run: cp example.env .env
working-directory: e2e_repo

- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: yarn install --immutable
working-directory: e2e_repo

- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: e2e_repo

- name: Wait for the OpenMRS instance to start
run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:8080/openmrs/login.htm)" != "200" ]]; do sleep 10; done

- name: Run E2E tests
run: yarn playwright test
working-directory: e2e_repo

- name: Upload Report
uses: actions/upload-artifact@v3
if: always()
with:
name: report-esm-core
path: e2e_repo/playwright-report/
retention-days: 30
52 changes: 52 additions & 0 deletions distro/e2e_test_support_files/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Run E2E Tests on Release PRs

This GitHub Actions workflow, named "Run E2E Tests on Release PRs," serves as Quality Gate #4 in the slide
deck [O3 Release QA pipeline](https://docs.google.com/presentation/d/1k3DH74Mz1Afnrgy2MpwR5HQK5vMpVx0pTfN1na62lvI/edit#slide=id.g165af5ac0be_0_24).

The workflow is designed to automate the end-to-end (E2E) testing process for release pull requests (PRs)
that opened in the format described in
here: [How to Release the O3 RefApp](https://wiki.openmrs.org/display/projects/How+to+Release+the+O3+RefApp)

The workflow is conditional and **only runs if the pull request title starts with "(release)"**.

Below is an overview of the key components of the workflow:
<a href="https://ibb.co/g9GmpHL"><img src="https://i.ibb.co/MSbZ4Wx/Screenshot-2023-10-24-at-18-13-19.png" border="0"></a>

## Job: build

This job prepares the test environment, extracts version numbers, builds and runs Docker containers, and uploads
artifacts for use in subsequent E2E testing jobs.

### Checking out to the release commit

The reason for the step:

```yaml
- name: Checkout to the release commit
run: git checkout 'HEAD^{/\(release\)}'
```

is to ensure that the workflow checks out to the specific release commit associated with the pull request. This is
necessary because the pull request contain both release commits and revert commits, and the goal is to specifically
target the release commit for further processing.

## End-to-End Test Jobs

The workflow includes several end-to-end test jobs, each corresponding to a specific components of O3 (frontend
mono-repos). These jobs are structured similarly and are listed below:

* `run-patient-management-e2e-tests`
* `run-patient-chart-e2e-tests`
* `run-form-builder-e2e-tests`
* `run-esm-core-e2e-tests`
* `run-cohort-builder-e2e-tests`

In each "End-to-End Test Job," the workflow first checks out the repository associated with a specific OpenMRS
component. It then downloads Docker images from a previous "build" job, loads these images, and starts an OpenMRS instance.

### Why Check Out to the Tags?

The workflow checks out a specific tagged version of the component's repository, the tag is imported from the previous "
build" job. This is necessary because the goal is to perform end-to-end tests on the codebase that corresponds to a
particular release version, rather than the code at the head of the repository. In case of using pre-releases, it checkouts
to the main branch as we don't create tags for pre-releases.
16 changes: 16 additions & 0 deletions distro/e2e_test_support_files/commit_and_export_images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

backend_container_id=$(docker ps --filter "name=backend" --format "{{.ID}}")
db_container_id=$(docker ps --filter "name=db" --format "{{.ID}}")
frontend_container_id=$(docker ps --filter "name=frontend" --format "{{.ID}}")
gateway_container_id=$(docker ps --filter "name=gateway" --format "{{.ID}}")

docker commit $frontend_container_id frontend
docker commit $gateway_container_id gateway
docker commit $backend_container_id backend
docker commit $db_container_id db

docker save frontend gateway backend db > e2e_release_env_images.tar

# compress the file (to decrease the upload file size)
gzip -c e2e_release_env_images.tar > e2e_release_env_images.tar.gz
59 changes: 59 additions & 0 deletions distro/e2e_test_support_files/docker-compose-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
version: "3.8"

services:
gateway:
build:
context: ../../gateway
container_name: gateway
restart: "unless-stopped"
depends_on:
- frontend
- backend
ports:
- "80:80"

frontend:
build:
context: ../../frontend
container_name: frontend
restart: "unless-stopped"
environment:
SPA_PATH: /openmrs/spa
API_URL: /openmrs
SPA_CONFIG_URLS: /openmrs/spa/custom-config.json
SPA_DEFAULT_LOCALE:
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost/" ]
timeout: 5s
depends_on:
- backend

backend:
build:
context: ../../
container_name: backend
depends_on:
- db
environment:
OMRS_CONFIG_MODULE_WEB_ADMIN: "true"
OMRS_CONFIG_AUTO_UPDATE_DATABASE: "true"
OMRS_CONFIG_CREATE_TABLES: "true"
OMRS_CONFIG_CONNECTION_SERVER: db
OMRS_CONFIG_CONNECTION_DATABASE: openmrs
OMRS_CONFIG_CONNECTION_USERNAME: ${OPENMRS_DB_USER:-openmrs}
OMRS_CONFIG_CONNECTION_PASSWORD: ${OPENMRS_DB_PASSWORD:-openmrs}
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:8080/openmrs" ]
timeout: 5s

# MariaDB
db:
image: mariadb:10.8.2
container_name: db
command: "mysqld --character-set-server=utf8 --collation-server=utf8_general_ci --datadir=/openmrs-db"
environment:
MYSQL_DATABASE: openmrs
MYSQL_USER: ${OPENMRS_DB_USER:-openmrs}
MYSQL_PASSWORD: ${OPENMRS_DB_PASSWORD:-openmrs}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-openmrs}

26 changes: 26 additions & 0 deletions distro/e2e_test_support_files/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: "3.8"

services:
gateway:
image: gateway
restart: "unless-stopped"
depends_on:
- frontend
- backend
ports:
- "8080:80"

frontend:
image: frontend
restart: "unless-stopped"
depends_on:
- backend

backend:
image: backend
restart: "unless-stopped"

db:
image: db
restart: "unless-stopped"