Skip to content

Add integration tests to CI - #294

Open
mgaffigan wants to merge 4 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:feat/smoketest
Open

Add integration tests to CI#294
mgaffigan wants to merge 4 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:feat/smoketest

Conversation

@mgaffigan

@mgaffigan mgaffigan commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Modifies CI to primarily build within Docker. Uses that newfound Docker capability to run message-processing smoke tests against each supported runtime and database: alpine and Ubuntu (temurin21), with back-ends for derby, mysql, postgres, and sqlserver.

Adds file-based fixture tests. Each configuration in ci/configurations/ runs the applicable cases in ci/tests/. A fixture case deploys one or more exported channels, submits its message fixtures through the OIE client API, and asserts the resulting source and destination messages. Procedure to add a test:

  1. Create a test folder (ci/tests/110-hl7-no-op)
  2. Add any channels needed (ci/tests/110-hl7-no-op/channels/01-hl7-no-op/channel.xml) by exporting from a running instance
  3. Add messages (ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/source)
  4. Add assertions (ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/source_response, dest01, status/metadata, etc.)

Assertions are byte-for-byte, with ((ANY)) matching variable content such as generated IDs or timestamps. See ci/README.md for the full list of assertion files and how to add a new configuration. When a scenario needs logic that can't be expressed as input data and expected results, there is a JUnit 5 escape hatch under smoketest/src/test/java/... using the Harness/OieServer helpers.

Integration tests produce JUnit XML results at ci/test-results/<configuration>/.

Run every configuration locally:

ci/runtests.sh

For "inner loop troubleshooting" it is often worthwhile to run a single configuration:

ci/runtests.sh alpine-temurin21-mysql

Or iterate against an already-running server:

./gradlew :smoketest:test -Doie.baseUrl=https://localhost:8443

Responsive to #11 and #98

@github-actions

github-actions Bot commented Apr 12, 2026

Copy link
Copy Markdown

Test Results

121 files  121 suites   2m 37s ⏱️
677 tests 677 ✅ 0 💤 0 ❌
689 runs  689 ✅ 0 💤 0 ❌

Results for commit 5ea53df.

♻️ This comment has been updated with latest results.

@mgaffigan
mgaffigan force-pushed the feat/smoketest branch 2 times, most recently from c81c101 to a07f581 Compare April 12, 2026 04:50
@mgaffigan
mgaffigan force-pushed the feat/smoketest branch 2 times, most recently from 379f74b to b36b39b Compare July 24, 2026 17:01
@mgaffigan
mgaffigan requested a review from Copilot July 24, 2026 17:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR shifts CI toward Docker-based builds and adds a Dockerized integration-test runner that boots various docker-compose configurations and validates message processing using filesystem-discovered fixtures, publishing JUnit XML results as artifacts.

Changes:

  • Update GitHub Actions build pipeline to build/load Docker images, export build artifacts/test results from a Docker stage, and run matrix “docker smoke” integration tests per configuration.
  • Add a Python-based test runner container (ci/runner/) plus a PowerShell entrypoint for local execution (ci/runtests.ps1).
  • Introduce file-based integration test fixtures under ci/tests/ (RAW and HL7 no-op examples) and formalize the approach in ci/README.md.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tools/gen-dockerignore.py Adds generator to derive .dockerignore from .gitignore plus Docker-specific excludes.
server/src/test/java/com/mirth/connect/server/launcher/Log4jMigrationsTest.java Makes a migration test conditional when filesystem permission semantics don’t enforce non-writability.
Dockerfile Adds a scratch stage to export build artifacts/test-results for CI packaging and upload.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/source_response Adds expected source ACK fixture for HL7 test.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/source Adds HL7 ADT^A01 input message fixture.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/messages/01-adt-a01/dest01_metadata.yml Adds destination metadata assertions for HL7 test.
ci/tests/110-hl7-no-op/channels/01-hl7-no-op/channel.xml Adds exported HL7 channel fixture with metadata column mappings.
ci/tests/101-raw-no-op/channels/01-raw-no-op/messages/01-hello-world/source Adds RAW message input fixture.
ci/tests/101-raw-no-op/channels/01-raw-no-op/messages/01-hello-world/dest01 Adds RAW destination content assertion fixture.
ci/tests/101-raw-no-op/channels/01-raw-no-op/channel.xml Adds exported RAW channel fixture with metadata column mappings.
ci/runtests.ps1 Adds local test entrypoint that builds images and runs the runner container against configs.
ci/runner/run.py Adds runner entrypoint wrapper for calling main().
ci/runner/messagetests.py Implements message fixture discovery, message submission, polling, and assertions (with wildcard support).
ci/runner/main.py Implements runner CLI: boot compose, login, discover/run tests, write JUnit XML, teardown.
ci/runner/junitxml.py Adds minimal JUnit XML writer + helper to wrap steps as testcases.
ci/runner/Dockerfile Defines runner image (docker CLI + Python + lxml + yaml).
ci/runner/compose.py Implements docker compose up/down orchestration and per-run project naming.
ci/runner/channeltests.py Implements channel fixture discovery/deploy/cleanup, and optional test hooks with timeouts.
ci/runner/api.py Implements REST client for login, channel lifecycle, message submission/search, and XML parsing.
ci/README.md Documents the CI integration-test design, fixture format, and runner contract.
ci/configurations/ubuntu-temurin21-postgres.compose.yml Adds Ubuntu+Postgres compose configuration with healthchecks.
ci/configurations/ubuntu-temurin21-derby.compose.yml Adds Ubuntu+Derby compose configuration with healthchecks.
ci/configurations/alpine-temurin21-sqlserver.compose.yml Adds Alpine+SQL Server compose configuration with db-init and healthchecks.
ci/configurations/alpine-temurin21-postgres.compose.yml Adds Alpine+Postgres compose configuration with healthchecks.
ci/configurations/alpine-temurin21-mysql.compose.yml Adds Alpine+MariaDB compose configuration with healthchecks.
ci/configurations/alpine-temurin21-derby.compose.yml Adds Alpine+Derby compose configuration with healthchecks.
ci/.gitignore Ignores runner outputs (test-results/, __pycache__/).
.github/workflows/upload_test_results.yaml Expands test result upload patterns to include docker smoke artifacts.
.github/workflows/build.yaml Reworks CI to build/export via Docker, upload images, and run docker smoke matrix.
.dockerignore Replaces hand-maintained ignore with generated content aligned to .gitignore semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ci/runner/api.py Outdated
Comment thread ci/runner/messagetests.py Outdated
Comment thread ci/runner/channeltests.py Outdated
Comment thread ci/runtests.ps1 Outdated
@mgaffigan
mgaffigan marked this pull request as ready for review July 24, 2026 18:03
@mgaffigan mgaffigan mentioned this pull request Jul 25, 2026
@mgaffigan
mgaffigan force-pushed the feat/smoketest branch 3 times, most recently from b59c7d6 to e6efb18 Compare July 25, 2026 23:28
NicoPiel
NicoPiel previously approved these changes Jul 26, 2026

@jonbartels jonbartels left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a build failure, looks like directory permissions https://github.com/OpenIntegrationEngine/engine/actions/runs/30450937701/job/90630023586?pr=294#step:9:1215

Fix this error and rebase. @ me when you do that and I'll re-review

Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
@mgaffigan

Copy link
Copy Markdown
Contributor Author

@jonbartels fixed

@mgaffigan
mgaffigan requested a review from jonbartels August 10, 2026 18:43
@jonbartels

Copy link
Copy Markdown
Contributor

The code looks good to me. I want to test and review this PR by grabbing the branch and writing my own, new test using the fixtures mechanism. I think I know a few cases for character encoding and strict parser settings that might be good.

Is there a mechanism that will let us test on Oracle? A casual search found https://github.com/gvenzl/oci-oracle-free. Again I can grab the branch and see about adding my own JVM/DB combo to see how it works.

Tentative approval pending some time to try the code out. TY Mitch!

@mgaffigan

Copy link
Copy Markdown
Contributor Author

Is there a mechanism that will let us test on Oracle? A casual search found https://github.com/gvenzl/oci-oracle-free. Again I can grab the branch and see about adding my own JVM/DB combo to see how it works.

I puttered around with ghcr.io/gvenzl/oracle-free:slim-faststart for a bit, but didn't get a working configuration. Oracle has weird client/server compatibility issues before/after v12. I'll see where I left that and push it somewhere.

Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
@mgaffigan

Copy link
Copy Markdown
Contributor Author

@jonbartels

Is there a mechanism that will let us test on Oracle? A casual search found https://github.com/gvenzl/oci-oracle-free. Again I can grab the branch and see about adding my own JVM/DB combo to see how it works.

Seems to work. Must have been unrelated. Maybe it was the download size that had me avoid it (~2GB).

@pacmano1

Copy link
Copy Markdown
Contributor

One thing worth considering: the configurations run serially. runtests.sh all loops the seven configs in the single build job under set -e, so the first failure aborts the rest and there's no parallelism. Since runtests.sh <config> already takes one configuration and the stacks are project-name isolated, a GH Actions matrix (one job per config, needs: build, images from the existing buildx cache) would give wall-time and full failure visibility for basically a build.yaml change.

Minor: a fixture whose configurations file lists only never-matching names is skipped in every config, and --fail-if-no-tests won't catch it — worth validating config names against ci/configurations/ eventually.

@mgaffigan

mgaffigan commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@pacmano1

One thing worth considering: the configurations run serially. runtests.sh all loops the seven configs in the single build job under set -e, so the first failure aborts the rest and there's no parallelism.

I did it this way originally, but since matricies run on different runners, the time it took to restore docker caches/github artifacts was significant. I decided to minimize transfer billing in trade for a few minutes of runtime to minimize costs. The matrix runner did complete faster in wall time, but billed more.

If we're not worried about github limits/billing, I can switch it back.

@pacmano1

Copy link
Copy Markdown
Contributor

No bill here. It's all free. I don't think we will him limts.

@@ -0,0 +1,40 @@
services:
db:
image: mariadb:11.8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: MySQL and MariaDB might be wire-compatible, but it is still a bit confusing that the .yml is named mysql, but it's actually MariaDB being used. It might warrant a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants