From ef7ae4293faf7f461ba59f60f5c9a4631d6bebed Mon Sep 17 00:00:00 2001 From: Tony Germano Date: Fri, 6 Feb 2026 20:27:00 -0500 Subject: [PATCH 1/4] build: fail build if tests fail This will allow all tests for a given sub-project to finish, but will abort the rest of the build. Previously the build would finish successfully even if there were test failures. Issue: https://github.com/OpenIntegrationEngine/engine/issues/144 Signed-off-by: Tony Germano --- client/ant-build.xml | 4 +++- command/build.xml | 4 +++- donkey/build.xml | 4 +++- server/build.xml | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/ant-build.xml b/client/ant-build.xml index de1dbfd09..8d73141a0 100644 --- a/client/ant-build.xml +++ b/client/ant-build.xml @@ -359,7 +359,7 @@ - + @@ -376,6 +376,8 @@ + + diff --git a/command/build.xml b/command/build.xml index 0f2ff9c52..0fb23f505 100644 --- a/command/build.xml +++ b/command/build.xml @@ -98,7 +98,7 @@ - + @@ -115,5 +115,7 @@ + + diff --git a/donkey/build.xml b/donkey/build.xml index 781f0824e..c1135c4ef 100644 --- a/donkey/build.xml +++ b/donkey/build.xml @@ -97,7 +97,7 @@ - + @@ -114,6 +114,8 @@ + + diff --git a/server/build.xml b/server/build.xml index 30091d371..635a76dd3 100644 --- a/server/build.xml +++ b/server/build.xml @@ -1317,7 +1317,7 @@ - + @@ -1356,6 +1356,8 @@ + + From 63c2dfffc08a06e916722419d463b51f427a4091 Mon Sep 17 00:00:00 2001 From: Tony Germano Date: Sat, 7 Feb 2026 06:55:23 -0500 Subject: [PATCH 2/4] build: Standardize test output and decouple JaCoCo coverage Refactors the Ant build scripts across client, command, donkey, and server projects to improve CI integration and local developer experience. Changes: * Decoupled Coverage: Separated unit test execution (`test-run`) from code coverage instrumentation (`test-coverage`). Developers can now run tests locally without the performance penalty of the JaCoCo agent unless explicitly requested. * Standardized Output: Consolidated all test artifacts into a unified, Gradle-compliant directory structure: - Raw results: `build/test-results/test` - HTML/XML Reports: `build/reports/tests` and `build/reports/jacoco` Single project Usage: - Run standard unit tests: `ant test-run` - Run tests with coverage: `ant test-coverage` Full Build Usage: - Run standard unit tests: `ant -f mirth-build.xml build` - Run tests with coverage: `ant -f mirth-build.xml build -Dcoverage=true` Signed-off-by: Tony Germano --- client/ant-build.xml | 100 ++++++++++++++++++++++-------- client/build.properties | 19 ++++++ command/build.properties | 20 +++++- command/build.xml | 116 ++++++++++++++++++++++++---------- donkey/build.properties | 19 ++++++ donkey/build.xml | 104 ++++++++++++++++++++++--------- server/build.properties | 22 ++++++- server/build.xml | 131 ++++++++++++++++++++++++--------------- server/mirth-build.xml | 17 +++-- 9 files changed, 404 insertions(+), 144 deletions(-) diff --git a/client/ant-build.xml b/client/ant-build.xml index 8d73141a0..7bda8d219 100644 --- a/client/ant-build.xml +++ b/client/ant-build.xml @@ -1,4 +1,6 @@ - + + OIE Client Build Help ----------------------- @@ -352,32 +354,78 @@ resource="org/jacoco/ant/antlib.xml" classpathref="jacoco.classpath"/> + + Run unit tests WITH JaCoCo coverage. + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + Run unit tests. Coverage is only enabled if 'jacoco.agent.arg' is set. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/build.properties b/client/build.properties index 05c6e3f82..731c01e7a 100644 --- a/client/build.properties +++ b/client/build.properties @@ -1,6 +1,7 @@ # top level directories src=${basedir}/src test=${basedir}/test +build.dir=${basedir}/build server=${basedir}/../server donkey_src=${basedir}/../donkey/src/main/java donkey_lib=${basedir}/../donkey/lib @@ -13,5 +14,23 @@ dist=${basedir}/dist # jars client.jar=mirth-client.jar +# Reports +reports.dir=${build.dir}/reports + +# JUnit Raw Results (XML) +test.results.dir=${build.dir}/test-results/test + +# JUnit Human-Readable Reports (HTML) +reports.tests.dir=${reports.dir}/tests/test + +# JaCoCo Execution Data (.exec) +jacoco.data.dir=${build.dir}/jacoco +jacoco.exec.file=${jacoco.data.dir}/test.exec + +# JaCoCo Reports (HTML and XML) +reports.jacoco.dir=${reports.dir}/jacoco/test +reports.jacoco.html=${reports.jacoco.dir}/html +reports.jacoco.xml=${reports.jacoco.dir}/jacocoTestReport.xml + # This value is used as the modified time for the files inside of jar, zip, and war files archive.entry.date=1999-01-01T00:00:00.000Z diff --git a/command/build.properties b/command/build.properties index 03e49e197..917d50746 100644 --- a/command/build.properties +++ b/command/build.properties @@ -3,7 +3,7 @@ src=${basedir}/src classes=${basedir}/classes lib=${basedir}/lib conf=${basedir}/conf -build=${basedir}/build +build.dir=${basedir}/build dist=${basedir}/dist test=${basedir}/test testlib=${basedir}/testlib @@ -14,5 +14,23 @@ server=${basedir}/../server cli.jar=mirth-cli.jar cli-launcher.jar=mirth-cli-launcher.jar +# Reports +reports.dir=${build.dir}/reports + +# JUnit Raw Results (XML) +test.results.dir=${build.dir}/test-results/test + +# JUnit Human-Readable Reports (HTML) +reports.tests.dir=${reports.dir}/tests/test + +# JaCoCo Execution Data (.exec) +jacoco.data.dir=${build.dir}/jacoco +jacoco.exec.file=${jacoco.data.dir}/test.exec + +# JaCoCo Reports (HTML and XML) +reports.jacoco.dir=${reports.dir}/jacoco/test +reports.jacoco.html=${reports.jacoco.dir}/html +reports.jacoco.xml=${reports.jacoco.dir}/jacocoTestReport.xml + # This value is used as the modified time for the files inside of jar, zip, and war files archive.entry.date=1999-01-01T00:00:00.000Z diff --git a/command/build.xml b/command/build.xml index 0fb23f505..457b9f601 100644 --- a/command/build.xml +++ b/command/build.xml @@ -1,4 +1,6 @@ - + + @@ -12,7 +14,7 @@ - + @@ -25,28 +27,28 @@ - + - + - + - + - + - + - + @@ -91,31 +93,77 @@ resource="org/jacoco/ant/antlib.xml" classpathref="jacoco.classpath"/> + + Run unit tests WITH JaCoCo coverage. + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + Run unit tests. Coverage is only enabled if 'jacoco.agent.arg' is set. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/donkey/build.properties b/donkey/build.properties index 4f1f6ce8b..58466c9c5 100644 --- a/donkey/build.properties +++ b/donkey/build.properties @@ -3,6 +3,7 @@ src=${basedir}/src/main/java classes=${basedir}/classes test=${basedir}/src/test/java test_classes=${basedir}/test_classes +build.dir=${basedir}/build lib=${basedir}/lib testlib=${basedir}/testlib setup=${basedir}/setup @@ -19,5 +20,23 @@ setup=${basedir}/setup setup.lib=${setup}/lib setup.docs=${setup}/docs +# Reports +reports.dir=${build.dir}/reports + +# JUnit Raw Results (XML) +test.results.dir=${build.dir}/test-results/test + +# JUnit Human-Readable Reports (HTML) +reports.tests.dir=${reports.dir}/tests/test + +# JaCoCo Execution Data (.exec) +jacoco.data.dir=${build.dir}/jacoco +jacoco.exec.file=${jacoco.data.dir}/test.exec + +# JaCoCo Reports (HTML and XML) +reports.jacoco.dir=${reports.dir}/jacoco/test +reports.jacoco.html=${reports.jacoco.dir}/html +reports.jacoco.xml=${reports.jacoco.dir}/jacocoTestReport.xml + # This value is used as the modified time for the files inside of jar, zip, and war files archive.entry.date=1999-01-01T00:00:00.000Z diff --git a/donkey/build.xml b/donkey/build.xml index c1135c4ef..284831c65 100644 --- a/donkey/build.xml +++ b/donkey/build.xml @@ -1,5 +1,7 @@ - + + @@ -89,35 +91,81 @@ - + + + Run unit tests WITH JaCoCo coverage. + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + Run unit tests. Coverage is only enabled if 'jacoco.agent.arg' is set. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/server/build.properties b/server/build.properties index 966ab20b8..d3c6f2708 100644 --- a/server/build.properties +++ b/server/build.properties @@ -11,8 +11,8 @@ conf=${basedir}/conf dbconf=${basedir}/dbconf public_html=${basedir}/public_html public_api_html=${basedir}/public_api_html -build=${basedir}/build -extensions=${build}/extensions +build.dir=${basedir}/build +extensions=${build.dir}/extensions logs=${basedir}/logs docs=${basedir}/docs docs.javadocs=${docs}/javadocs @@ -30,6 +30,24 @@ dbconf.jar=mirth-dbconf.jar userutil-sources.jar=userutil-sources.jar tests.jar=mirth-server-tests.jar +# Reports +reports.dir=${build.dir}/reports + +# JUnit Raw Results (XML) +test.results.dir=${build.dir}/test-results/test + +# JUnit Human-Readable Reports (HTML) +reports.tests.dir=${reports.dir}/tests/test + +# JaCoCo Execution Data (.exec) +jacoco.data.dir=${build.dir}/jacoco +jacoco.exec.file=${jacoco.data.dir}/test.exec + +# JaCoCo Reports (HTML and XML) +reports.jacoco.dir=${reports.dir}/jacoco/test +reports.jacoco.html=${reports.jacoco.dir}/html +reports.jacoco.xml=${reports.jacoco.dir}/jacocoTestReport.xml + # setup directory setup=${basedir}/setup setup.server.lib=${setup}/server-lib diff --git a/server/build.xml b/server/build.xml index 635a76dd3..95453cd3e 100644 --- a/server/build.xml +++ b/server/build.xml @@ -1,5 +1,6 @@ - + @@ -74,7 +75,7 @@ - + @@ -1304,60 +1305,92 @@ resource="org/jacoco/ant/antlib.xml" classpathref="jacoco.classpath"/> + + Run unit tests WITH JaCoCo coverage. + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Run unit tests. Coverage is only enabled if 'jacoco.agent.arg' is set. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + diff --git a/server/mirth-build.xml b/server/mirth-build.xml index 73dda90fd..b12aa394c 100644 --- a/server/mirth-build.xml +++ b/server/mirth-build.xml @@ -187,10 +187,19 @@ - - - - + + + + + + + + + + + + + From f506683a3eee46fd67ead5cbed2d43b475710353 Mon Sep 17 00:00:00 2001 From: Tony Germano Date: Sun, 8 Feb 2026 17:07:09 -0500 Subject: [PATCH 3/4] build: Add comprehensive clean targets and legacy cleanup Improves build hygiene by ensuring all generated artifacts are removed during clean operations. Changes: * Global Clean: Added a top-level `clean-all` target in `mirth-build.xml` that cascades to all sub-projects. * Legacy Cleanup: Introduced `clean-legacy-dirs` target to remove obsolete directories (`junit-reports`, `code-coverage-reports`) ensuring developers do not view stale reports. * Deep Clean: Updated sub-project clean targets to include `${test_classes}` and `${build.dir}`, preventing stale class files from polluting subsequent builds. Signed-off-by: Tony Germano --- client/ant-build.xml | 11 ++++++++++- command/build.xml | 8 +++++++- donkey/build.xml | 14 +++++++++++--- server/build.xml | 9 ++++++++- server/mirth-build.xml | 7 +++++++ 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/client/ant-build.xml b/client/ant-build.xml index 7bda8d219..e42fdf0f4 100644 --- a/client/ant-build.xml +++ b/client/ant-build.xml @@ -69,9 +69,18 @@ - + + + + + + + + + + diff --git a/command/build.xml b/command/build.xml index 457b9f601..a591dabc1 100644 --- a/command/build.xml +++ b/command/build.xml @@ -12,13 +12,19 @@ unless:set="archive.entry.date" /> - + + + + + + + diff --git a/donkey/build.xml b/donkey/build.xml index 284831c65..7dc831adb 100644 --- a/donkey/build.xml +++ b/donkey/build.xml @@ -12,12 +12,20 @@ - - + + + + - + + + + + + + diff --git a/server/build.xml b/server/build.xml index 95453cd3e..32dd10eb8 100644 --- a/server/build.xml +++ b/server/build.xml @@ -68,17 +68,24 @@ - + + + + + + + + diff --git a/server/mirth-build.xml b/server/mirth-build.xml index b12aa394c..e4fc700ad 100644 --- a/server/mirth-build.xml +++ b/server/mirth-build.xml @@ -212,4 +212,11 @@ + + + + + + + From e854921a2140e9995d8d4cb3ce0c82a0ec34613f Mon Sep 17 00:00:00 2001 From: Tony Germano Date: Fri, 6 Feb 2026 16:08:30 -0500 Subject: [PATCH 4/4] ci: Implement secure test result reporting via GitHub Actions Establishes a split-workflow CI pipeline to safely run tests and report results, complying with security best practices for public repositories. Changes: * Build Workflow: - Updated the Ant build command to enable coverage (`-Dcoverage=true`). - Added a "Stage Test Results" step to aggregate XML reports from all sub-projects (client, server, donkey, etc.) while preserving directory structure. - Added an "Event File" job to capture PR metadata for secure downstream processing. * Reporting Workflow: - Created `upload_test_results.yaml` triggered by `workflow_run`. - Implemented the privileged report publishing step separately from the unprivileged build step. - configured `EnricoMi/publish-unit-test-result-action` to ingest the aggregated XML reports. Security: * Uses the `workflow_run` pattern to allow safe PR commenting from forks without exposing write tokens to the build environment. Signed-off-by: Tony Germano --- .github/workflows/build.yaml | 30 +++++++++++++++-- .github/workflows/upload_test_results.yaml | 38 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/upload_test_results.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ec879d84c..f968b4d70 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,4 +1,4 @@ -name: Build OpenIntegrationEngine +name: Build Open Integration Engine on: push: @@ -9,6 +9,16 @@ on: - main jobs: + event_file: + name: "Event File" + runs-on: ubuntu-latest + steps: + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: Event File + path: ${{ github.event_path }} + build: runs-on: ubuntu-latest @@ -30,7 +40,7 @@ jobs: - name: Build OIE (unsigned) if: github.ref != 'refs/heads/main' working-directory: server - run: ant -f mirth-build.xml -DdisableSigning=true + run: ant -f mirth-build.xml -DdisableSigning=true -Dcoverage=true - name: Package distribution run: tar czf openintegrationengine.tar.gz -C server/ setup --transform 's|^setup|openintegrationengine/|' @@ -40,3 +50,19 @@ jobs: with: name: oie-build path: openintegrationengine.tar.gz + + - name: Stage Test Results + if: (!cancelled()) + run: | + mkdir -p aggregate-test-results + # Copy the directory structures + cp -r --parents */build/test-results aggregate-test-results/ + + - name: Upload Test Results + if: (!cancelled()) + uses: actions/upload-artifact@v4 + with: + name: Test Results + path: | + aggregate-test-results/**/*.xml + diff --git a/.github/workflows/upload_test_results.yaml b/.github/workflows/upload_test_results.yaml new file mode 100644 index 000000000..21ab857bb --- /dev/null +++ b/.github/workflows/upload_test_results.yaml @@ -0,0 +1,38 @@ +name: Test Results + +on: + workflow_run: + workflows: ["Build Open Integration Engine"] + types: + - completed + +permissions: {} + +jobs: + test-results: + name: Test Results + runs-on: ubuntu-latest + if: github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure' + + permissions: + checks: write + # needed unless run with comment_mode: off + pull-requests: write + # required by download step to access artifacts API + actions: read + + steps: + - name: Download and Extract Artifacts + uses: actions/download-artifact@v4 + with: + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + path: artifacts + + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + with: + commit: ${{ github.event.workflow_run.head_sha }} + event_file: artifacts/Event File/event.json + event_name: ${{ github.event.workflow_run.event }} + files: "artifacts/Test Results/**/*.xml"