From d759e8bcd2566f25b81dd6591717c30d58ea4bd2 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 18:32:26 +0200 Subject: [PATCH 01/10] [refactor] modernize Maven 3 build and release pipeline Switch all 59 POMs to ${revision} with flatten-maven-plugin resolving it in deployed artifacts. Replace activeByDefault on installer/stress/ benchmarks with explicit umbrella profiles: local-build (default), release-build (installer + Central Portal publishing via central-publishing-maven-plugin), perf-tests (stress + benchmarks). Add release-preflight enforcer and GPG signing to release-build. Migrate macOS notarization from deprecated altool to notarytool+staple; fix CI activation guard on mac-dmg-on-mac. close #3394 close #4519 see #6176 --- .gitignore | 1 + exist-ant/pom.xml | 2 +- exist-core-jcstress/pom.xml | 2 +- exist-core-jmh/pom.xml | 2 +- exist-core/pom.xml | 2 +- exist-distribution/pom.xml | 39 +++-- exist-docker/pom.xml | 2 +- exist-indexes-jmh/pom.xml | 2 +- exist-installer/pom.xml | 2 +- exist-jetty-config/pom.xml | 2 +- exist-parent/pom.xml | 139 +++++++++++++++++- exist-samples/pom.xml | 2 +- exist-service/pom.xml | 2 +- exist-start/pom.xml | 2 +- exist-xqts/pom.xml | 2 +- extensions/contentextraction/pom.xml | 2 +- extensions/exiftool/pom.xml | 2 +- extensions/expath/pom.xml | 2 +- extensions/exquery/modules/pom.xml | 2 +- extensions/exquery/modules/request/pom.xml | 2 +- extensions/exquery/pom.xml | 2 +- extensions/exquery/restxq/pom.xml | 2 +- .../indexes/indexes-integration-tests/pom.xml | 2 +- extensions/indexes/lucene/pom.xml | 2 +- extensions/indexes/ngram/pom.xml | 2 +- extensions/indexes/pom.xml | 2 +- extensions/indexes/range/pom.xml | 2 +- extensions/indexes/sort/pom.xml | 2 +- extensions/indexes/spatial/pom.xml | 2 +- extensions/indexes/vector-it/pom.xml | 2 +- extensions/modules/cache/pom.xml | 2 +- extensions/modules/compression/pom.xml | 2 +- extensions/modules/counter/pom.xml | 2 +- extensions/modules/cqlparser/pom.xml | 2 +- extensions/modules/example/pom.xml | 2 +- extensions/modules/exi/pom.xml | 2 +- .../expathrepo-trigger-test/pom.xml | 2 +- extensions/modules/expathrepo/pom.xml | 2 +- extensions/modules/file/pom.xml | 2 +- extensions/modules/image/pom.xml | 2 +- extensions/modules/jndi/pom.xml | 2 +- extensions/modules/mail/pom.xml | 2 +- extensions/modules/persistentlogin/pom.xml | 2 +- extensions/modules/pom.xml | 2 +- extensions/modules/process/pom.xml | 2 +- extensions/modules/scheduler/pom.xml | 2 +- extensions/modules/simpleql/pom.xml | 2 +- extensions/modules/sql-oracle/pom.xml | 2 +- extensions/modules/sql/pom.xml | 2 +- extensions/modules/xmldiff/pom.xml | 2 +- extensions/modules/xslfo/pom.xml | 2 +- extensions/pom.xml | 2 +- extensions/security/activedirectory/pom.xml | 2 +- extensions/security/iprange/pom.xml | 2 +- extensions/security/ldap/pom.xml | 2 +- extensions/security/pom.xml | 2 +- extensions/vector/pom.xml | 2 +- extensions/webdav/pom.xml | 2 +- extensions/xqdoc/pom.xml | 2 +- pom.xml | 37 ++++- 60 files changed, 249 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index a75cffd65c9..94b2ee9a3a4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ dependency-reduced-pom.xml # Maven generated effective-pom.xml +.flattened-pom.xml # XQTS test artefacts work/ diff --git a/exist-ant/pom.xml b/exist-ant/pom.xml index f444da8b0a3..6f224a75f1e 100644 --- a/exist-ant/pom.xml +++ b/exist-ant/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-core-jcstress/pom.xml b/exist-core-jcstress/pom.xml index 45154ea6d3c..cb3ca9567a0 100644 --- a/exist-core-jcstress/pom.xml +++ b/exist-core-jcstress/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-core-jmh/pom.xml b/exist-core-jmh/pom.xml index 0682c8d17e8..4cd46392e92 100644 --- a/exist-core-jmh/pom.xml +++ b/exist-core-jmh/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-core/pom.xml b/exist-core/pom.xml index 3661e56f8bc..f320af4a2b7 100644 --- a/exist-core/pom.xml +++ b/exist-core/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-distribution/pom.xml b/exist-distribution/pom.xml index 90c793e8154..db5fbfae870 100644 --- a/exist-distribution/pom.xml +++ b/exist-distribution/pom.xml @@ -29,7 +29,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent @@ -1063,10 +1063,10 @@ mac - + - env.CI - !true + mac-signing + true @@ -1187,16 +1187,31 @@ true /usr/bin/xcrun - altool - --notarize-app - --verbose - --primary-bundle-id - org.exist-db - --username - ${existdb.release.notarize.username} + notarytool + submit + ${mac.dmg} + --apple-id + ${existdb.release.notarize.apple-id} --password ${existdb.release.notarize.password} - --file + --team-id + ${existdb.release.notarize.team-id} + --wait + + + + + mac-staple-dmg + package + + exec + + + true + /usr/bin/xcrun + + stapler + staple ${mac.dmg} diff --git a/exist-docker/pom.xml b/exist-docker/pom.xml index 11dfab67732..a55b137d09a 100644 --- a/exist-docker/pom.xml +++ b/exist-docker/pom.xml @@ -30,7 +30,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-indexes-jmh/pom.xml b/exist-indexes-jmh/pom.xml index 8ebaa16fd89..e2e580aa826 100644 --- a/exist-indexes-jmh/pom.xml +++ b/exist-indexes-jmh/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-installer/pom.xml b/exist-installer/pom.xml index b8f30786529..e8e8d821a4a 100644 --- a/exist-installer/pom.xml +++ b/exist-installer/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-jetty-config/pom.xml b/exist-jetty-config/pom.xml index 379d7a5d9f4..6a10d6a72bf 100644 --- a/exist-jetty-config/pom.xml +++ b/exist-jetty-config/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index 229bffe26d7..1a25a8c7a8f 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -27,7 +27,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} pom eXist-db Parent @@ -97,14 +97,18 @@ GitHub Registry for Snapshots https://maven.pkg.github.com/eXist-db/exist - + + + 7.0.0-SNAPSHOT + 21 ${maven.compiler.release} ${maven.compiler.release} @@ -831,6 +835,16 @@ + + org.codehaus.mojo + flatten-maven-plugin + 1.7.0 + + + org.sonatype.central + central-publishing-maven-plugin + 0.7.0 + software.xdev find-and-replace-maven-plugin @@ -1206,6 +1220,31 @@ + + + org.codehaus.mojo + flatten-maven-plugin + + true + resolveCiFriendlyVersions + + + + flatten + process-resources + + flatten + + + + flatten.clean + clean + + clean + + + + org.apache.maven.plugins maven-enforcer-plugin @@ -1447,6 +1486,100 @@ + + + release-build + + true + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + ${existdb.release.key} + ${existdb.release.key.passphrase} + + --batch + --pinentry-mode + loopback + + + + + + + org.sonatype.central + central-publishing-maven-plugin + true + + central + true + + uploaded + + + + + + + + release-preflight + + + release.preflight + true + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + release-preflight-checks + validate + + enforce + + + + + CENTRAL_TOKEN_USERNAME + CENTRAL_TOKEN_USERNAME env var is required for release publishing. + + + CENTRAL_TOKEN_PASSWORD + CENTRAL_TOKEN_PASSWORD env var is required for release publishing. + + + existdb.release.key + existdb.release.key is required for GPG artifact signing. + + + existdb.release.key.passphrase + existdb.release.key.passphrase is required for GPG artifact signing. + + + + + + + + + + + exist-release diff --git a/exist-samples/pom.xml b/exist-samples/pom.xml index 2705d0ce6b2..6de65c7e9ea 100644 --- a/exist-samples/pom.xml +++ b/exist-samples/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-service/pom.xml b/exist-service/pom.xml index 1fe65bc9770..096ba4c4e81 100644 --- a/exist-service/pom.xml +++ b/exist-service/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-start/pom.xml b/exist-start/pom.xml index 5883584378c..ea538edf731 100644 --- a/exist-start/pom.xml +++ b/exist-start/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/exist-xqts/pom.xml b/exist-xqts/pom.xml index e3649152438..b020dd19beb 100644 --- a/exist-xqts/pom.xml +++ b/exist-xqts/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/extensions/contentextraction/pom.xml b/extensions/contentextraction/pom.xml index 274cf24ba47..ab4131a17fe 100644 --- a/extensions/contentextraction/pom.xml +++ b/extensions/contentextraction/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/exiftool/pom.xml b/extensions/exiftool/pom.xml index 4ab26234f74..52a00233b8c 100644 --- a/extensions/exiftool/pom.xml +++ b/extensions/exiftool/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/expath/pom.xml b/extensions/expath/pom.xml index b189b3307a0..4b9c69bdf21 100644 --- a/extensions/expath/pom.xml +++ b/extensions/expath/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/exquery/modules/pom.xml b/extensions/exquery/modules/pom.xml index 2bd4d2b5259..f52f73f695a 100644 --- a/extensions/exquery/modules/pom.xml +++ b/extensions/exquery/modules/pom.xml @@ -32,7 +32,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/exquery/modules/request/pom.xml b/extensions/exquery/modules/request/pom.xml index 2a5344f2e04..13a79043c34 100644 --- a/extensions/exquery/modules/request/pom.xml +++ b/extensions/exquery/modules/request/pom.xml @@ -33,7 +33,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../../exist-parent diff --git a/extensions/exquery/pom.xml b/extensions/exquery/pom.xml index fc5b38d4994..78cf4a3ce4a 100644 --- a/extensions/exquery/pom.xml +++ b/extensions/exquery/pom.xml @@ -32,7 +32,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/exquery/restxq/pom.xml b/extensions/exquery/restxq/pom.xml index ccc37f26ed3..ec8806776e6 100644 --- a/extensions/exquery/restxq/pom.xml +++ b/extensions/exquery/restxq/pom.xml @@ -32,7 +32,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/indexes/indexes-integration-tests/pom.xml b/extensions/indexes/indexes-integration-tests/pom.xml index 14b7508ffec..1bb19aed591 100644 --- a/extensions/indexes/indexes-integration-tests/pom.xml +++ b/extensions/indexes/indexes-integration-tests/pom.xml @@ -29,7 +29,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/indexes/lucene/pom.xml b/extensions/indexes/lucene/pom.xml index 1e403935ec6..8d4aed7828d 100644 --- a/extensions/indexes/lucene/pom.xml +++ b/extensions/indexes/lucene/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/indexes/ngram/pom.xml b/extensions/indexes/ngram/pom.xml index e8ceb03d366..d26a662119a 100644 --- a/extensions/indexes/ngram/pom.xml +++ b/extensions/indexes/ngram/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/indexes/pom.xml b/extensions/indexes/pom.xml index 3bf62ebd987..2b31830dab6 100644 --- a/extensions/indexes/pom.xml +++ b/extensions/indexes/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/indexes/range/pom.xml b/extensions/indexes/range/pom.xml index ed8f4691655..1e24fddfe6c 100644 --- a/extensions/indexes/range/pom.xml +++ b/extensions/indexes/range/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/indexes/sort/pom.xml b/extensions/indexes/sort/pom.xml index ba3365dcb6d..c15e5e39fb1 100644 --- a/extensions/indexes/sort/pom.xml +++ b/extensions/indexes/sort/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/indexes/spatial/pom.xml b/extensions/indexes/spatial/pom.xml index 04dcd18962f..cc0ea7cca9a 100644 --- a/extensions/indexes/spatial/pom.xml +++ b/extensions/indexes/spatial/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/indexes/vector-it/pom.xml b/extensions/indexes/vector-it/pom.xml index 327f2951ada..2afe479846e 100644 --- a/extensions/indexes/vector-it/pom.xml +++ b/extensions/indexes/vector-it/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/cache/pom.xml b/extensions/modules/cache/pom.xml index 1c1e2aa35fa..4b59c15c463 100644 --- a/extensions/modules/cache/pom.xml +++ b/extensions/modules/cache/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/compression/pom.xml b/extensions/modules/compression/pom.xml index 28c5c6b86ff..f3e1c3a04bf 100644 --- a/extensions/modules/compression/pom.xml +++ b/extensions/modules/compression/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/counter/pom.xml b/extensions/modules/counter/pom.xml index 5abea008ba2..e52373641a9 100644 --- a/extensions/modules/counter/pom.xml +++ b/extensions/modules/counter/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/cqlparser/pom.xml b/extensions/modules/cqlparser/pom.xml index c0600735b0e..9c3a12f5d54 100644 --- a/extensions/modules/cqlparser/pom.xml +++ b/extensions/modules/cqlparser/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/example/pom.xml b/extensions/modules/example/pom.xml index b1f70d9bd99..1273fde4c76 100644 --- a/extensions/modules/example/pom.xml +++ b/extensions/modules/example/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/exi/pom.xml b/extensions/modules/exi/pom.xml index 4db6a7562c2..18135d48f0d 100644 --- a/extensions/modules/exi/pom.xml +++ b/extensions/modules/exi/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/expathrepo/expathrepo-trigger-test/pom.xml b/extensions/modules/expathrepo/expathrepo-trigger-test/pom.xml index 6de00696892..a42e5c53a00 100644 --- a/extensions/modules/expathrepo/expathrepo-trigger-test/pom.xml +++ b/extensions/modules/expathrepo/expathrepo-trigger-test/pom.xml @@ -29,7 +29,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../../exist-parent diff --git a/extensions/modules/expathrepo/pom.xml b/extensions/modules/expathrepo/pom.xml index 9a55407256e..526e989bd7f 100644 --- a/extensions/modules/expathrepo/pom.xml +++ b/extensions/modules/expathrepo/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/file/pom.xml b/extensions/modules/file/pom.xml index 08da6131c37..5fc4f4461f2 100644 --- a/extensions/modules/file/pom.xml +++ b/extensions/modules/file/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/image/pom.xml b/extensions/modules/image/pom.xml index c0e0709c31f..33ab613bb2c 100644 --- a/extensions/modules/image/pom.xml +++ b/extensions/modules/image/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/jndi/pom.xml b/extensions/modules/jndi/pom.xml index adf9f6e1a62..d1c54a7fdef 100644 --- a/extensions/modules/jndi/pom.xml +++ b/extensions/modules/jndi/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/mail/pom.xml b/extensions/modules/mail/pom.xml index 4cee3eab489..4db017836f5 100644 --- a/extensions/modules/mail/pom.xml +++ b/extensions/modules/mail/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/persistentlogin/pom.xml b/extensions/modules/persistentlogin/pom.xml index d65335db765..98db46565d7 100644 --- a/extensions/modules/persistentlogin/pom.xml +++ b/extensions/modules/persistentlogin/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/pom.xml b/extensions/modules/pom.xml index 56c67297a17..b8b96cd2b5a 100644 --- a/extensions/modules/pom.xml +++ b/extensions/modules/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/modules/process/pom.xml b/extensions/modules/process/pom.xml index 4432f137d72..39bb636f0f2 100644 --- a/extensions/modules/process/pom.xml +++ b/extensions/modules/process/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/scheduler/pom.xml b/extensions/modules/scheduler/pom.xml index 1e3fe399ae2..9bb38aab65d 100644 --- a/extensions/modules/scheduler/pom.xml +++ b/extensions/modules/scheduler/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/simpleql/pom.xml b/extensions/modules/simpleql/pom.xml index 3072d65c9a4..57c67974fe7 100644 --- a/extensions/modules/simpleql/pom.xml +++ b/extensions/modules/simpleql/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/sql-oracle/pom.xml b/extensions/modules/sql-oracle/pom.xml index 3b8f2c00f65..8ea17349f46 100644 --- a/extensions/modules/sql-oracle/pom.xml +++ b/extensions/modules/sql-oracle/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/sql/pom.xml b/extensions/modules/sql/pom.xml index 3a164c0ef04..e5a33f6fe12 100644 --- a/extensions/modules/sql/pom.xml +++ b/extensions/modules/sql/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/xmldiff/pom.xml b/extensions/modules/xmldiff/pom.xml index bea8010fa83..b148fc741ff 100644 --- a/extensions/modules/xmldiff/pom.xml +++ b/extensions/modules/xmldiff/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/modules/xslfo/pom.xml b/extensions/modules/xslfo/pom.xml index b2b63f67f05..61ab3c73fd3 100644 --- a/extensions/modules/xslfo/pom.xml +++ b/extensions/modules/xslfo/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/pom.xml b/extensions/pom.xml index 8d811d729c8..cb90aa25341 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../exist-parent diff --git a/extensions/security/activedirectory/pom.xml b/extensions/security/activedirectory/pom.xml index 71765f33391..0fde319ba3b 100644 --- a/extensions/security/activedirectory/pom.xml +++ b/extensions/security/activedirectory/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/security/iprange/pom.xml b/extensions/security/iprange/pom.xml index cb7c528a459..e46d71e21ce 100644 --- a/extensions/security/iprange/pom.xml +++ b/extensions/security/iprange/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/security/ldap/pom.xml b/extensions/security/ldap/pom.xml index d04704cc50c..9815d855fec 100644 --- a/extensions/security/ldap/pom.xml +++ b/extensions/security/ldap/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../../exist-parent diff --git a/extensions/security/pom.xml b/extensions/security/pom.xml index f8297425e98..9c97519d015 100644 --- a/extensions/security/pom.xml +++ b/extensions/security/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/vector/pom.xml b/extensions/vector/pom.xml index aa8beaf5f92..3018e1fd977 100644 --- a/extensions/vector/pom.xml +++ b/extensions/vector/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/webdav/pom.xml b/extensions/webdav/pom.xml index 3f902141300..072e402be5c 100644 --- a/extensions/webdav/pom.xml +++ b/extensions/webdav/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/extensions/xqdoc/pom.xml b/extensions/xqdoc/pom.xml index 1f00e9d1aa5..913ac228d3c 100644 --- a/extensions/xqdoc/pom.xml +++ b/extensions/xqdoc/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} ../../exist-parent diff --git a/pom.xml b/pom.xml index 95334ac704f..88916fe1325 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ org.exist-db exist-parent - 7.0.0-SNAPSHOT + ${revision} exist-parent @@ -71,11 +71,28 @@ + - installer + + local-build true + + + + + release-build + + exist-installer + + + + + + installer exist-installer @@ -94,11 +111,18 @@ + + + perf-tests + + exist-core-jcstress + exist-core-jmh + exist-indexes-jmh + + + concurrency-stress-tests - - true - exist-core-jcstress @@ -106,9 +130,6 @@ micro-benchmarks - - true - exist-core-jmh exist-indexes-jmh From f15aaeea71b6f345f0978ae042700d0603c615e5 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 18:58:39 +0200 Subject: [PATCH 02/10] [ci] add tag-triggered release pipeline and update release docs Replaces mvn release:prepare/perform with two GitHub Actions workflows: ci-release-prepare (workflow_dispatch) updates CITATION.cff, commits, and pushes an annotated eXist-X.Y.Z tag; ci-release (tag-triggered) runs parallel platform jobs for Maven Central deploy, signed+notarized macOS DMG, and Authenticode-signed Windows installer, converging on a GitHub Release. Updates exist-versioning-release.md to document the new procedure. Closes #5597 #4217 --- .../actions/maven-github-settings/action.yml | 30 +- .github/workflows/ci-release-prepare.yml | 63 ++++ .github/workflows/ci-release.yml | 309 ++++++++++++++++++ exist-versioning-release.md | 191 ++++------- 4 files changed, 466 insertions(+), 127 deletions(-) create mode 100644 .github/workflows/ci-release-prepare.yml create mode 100644 .github/workflows/ci-release.yml diff --git a/.github/actions/maven-github-settings/action.yml b/.github/actions/maven-github-settings/action.yml index c0451dc35fb..25264d54d1a 100644 --- a/.github/actions/maven-github-settings/action.yml +++ b/.github/actions/maven-github-settings/action.yml @@ -1,19 +1,43 @@ -# Creates Maven settings.xml with auth for the eXist-db org's GitHub Packages repos. +# Creates Maven settings.xml with auth for the eXist-db org's GitHub Packages repos +# and optionally for Sonatype Central Portal publishing. # Required for resolving artifacts from maven.pkg.github.com/eXist-db/{exist, exist-xqts-runner, jackrabbit-webdav-jakarta}. name: Maven GitHub Packages settings -description: Create settings.xml with github, github-xqts-runner, and github-jackrabbit-webdav-jakarta servers +description: Create settings.xml with GitHub Packages and (optionally) Sonatype Central Portal servers inputs: token: description: 'GitHub token for package authentication' required: true + central-token-username: + description: 'Sonatype Central Portal user token username (release jobs only)' + required: false + default: '' + central-token-password: + description: 'Sonatype Central Portal user token password (release jobs only)' + required: false + default: '' runs: using: 'composite' steps: - name: Create Maven settings for GitHub Packages shell: bash + env: + CENTRAL_TOKEN_USERNAME: ${{ inputs.central-token-username }} + CENTRAL_TOKEN_PASSWORD: ${{ inputs.central-token-password }} run: | mkdir -p ~/.m2 OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + + # Build optional Central Portal server block + CENTRAL_SERVER="" + if [ -n "$CENTRAL_TOKEN_USERNAME" ]; then + CENTRAL_SERVER=" + + central + ${CENTRAL_TOKEN_USERNAME} + ${CENTRAL_TOKEN_PASSWORD} + " + fi + cat > ~/.m2/settings.xml << EOF @@ -31,7 +55,7 @@ runs: github-jackrabbit-webdav-jakarta ${OWNER} ${{ inputs.token }} - + ${CENTRAL_SERVER} EOF diff --git a/.github/workflows/ci-release-prepare.yml b/.github/workflows/ci-release-prepare.yml new file mode 100644 index 00000000000..ea749a8ebdd --- /dev/null +++ b/.github/workflows/ci-release-prepare.yml @@ -0,0 +1,63 @@ +name: Prepare Release + +# Replaces mvn release:prepare. Updates CITATION.cff, commits, creates the +# annotated tag, and pushes — which then triggers ci-release.yml. +# +# Requires a fine-grained PAT (RELEASE_PAT) with contents:write on this repo. +# GITHUB_TOKEN pushes do not trigger downstream tag workflows. + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g. 7.0.0)' + required: true + type: string + +permissions: + contents: write + +jobs: + prepare: + name: Prepare eXist-${{ inputs.version }} + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + # PAT required so the tag push triggers ci-release.yml. + # GITHUB_TOKEN pushes are intentionally blocked from triggering workflows. + token: ${{ secrets.RELEASE_PAT }} + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: '21' + + - uses: ./.github/actions/maven-cache + + - uses: ./.github/actions/maven-github-settings + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Update CITATION.cff + run: | + mvn -B --no-transfer-progress \ + -Pcitation-release-metadata \ + -DupdateCff=true \ + -Drevision=${{ inputs.version }} \ + validate + + - name: Commit and tag + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add CITATION.cff + # Only commit if CITATION.cff actually changed + git diff --staged --quiet || \ + git commit -m "[release] Prepare eXist-${{ inputs.version }}" + git tag -a "eXist-${{ inputs.version }}" \ + -m "eXist-db ${{ inputs.version }}" + git push origin HEAD + git push origin "eXist-${{ inputs.version }}" diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml new file mode 100644 index 00000000000..b3abe79ab37 --- /dev/null +++ b/.github/workflows/ci-release.yml @@ -0,0 +1,309 @@ +name: Release + +# Triggered by an eXist-* tag (created by ci-release-prepare.yml). +# Four jobs run in parallel then converge on a single GitHub Release: +# build-linux — Maven Central deploy + zip/tar archives (Ubuntu) +# build-mac — signed + notarized DMG (macOS) +# build-windows — signed installer JAR + Authenticode .exe (Windows) +# publish-github-release — collects all artifacts, creates the GitHub Release + +on: + push: + tags: + - 'eXist-*' + workflow_dispatch: + inputs: + tag: + description: 'Existing tag to re-release (e.g. eXist-7.0.0)' + required: false + type: string + +permissions: + contents: write + +env: + JAVA_VERSION: '21' + +# ─── Shared helper ──────────────────────────────────────────────────────────── +# Extract the semantic version from the tag name (strips the "eXist-" prefix). +# Usage in run steps: TAG="${{ github.event.inputs.tag || github.ref_name }}" +# REVISION="${TAG#eXist-}" + +jobs: + + # ── Job 1: Build and publish to Maven Central ──────────────────────────────── + build-linux: + name: Build and publish to Maven Central + runs-on: ubuntu-latest + timeout-minutes: 90 + env: + CENTRAL_TOKEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }} + CENTRAL_TOKEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN_PASSWORD }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ env.JAVA_VERSION }} + + - uses: ./.github/actions/maven-cache + + - uses: ./.github/actions/maven-github-settings + with: + token: ${{ secrets.GITHUB_TOKEN }} + central-token-username: ${{ secrets.CENTRAL_TOKEN_USERNAME }} + central-token-password: ${{ secrets.CENTRAL_TOKEN_PASSWORD }} + + - name: Import GPG key + env: + EXISTDB_RELEASE_KEY: ${{ secrets.EXISTDB_RELEASE_KEY }} + run: echo "$EXISTDB_RELEASE_KEY" | base64 --decode | gpg --batch --import + + - name: Deploy to Maven Central + env: + EXISTDB_RELEASE_KEY_ID: ${{ secrets.EXISTDB_RELEASE_KEY_ID }} + EXISTDB_RELEASE_KEY_PASSPHRASE: ${{ secrets.EXISTDB_RELEASE_KEY_PASSPHRASE }} + run: | + TAG="${{ github.event.inputs.tag || github.ref_name }}" + REVISION="${TAG#eXist-}" + mvn -V -B --no-transfer-progress \ + -Prelease-build \ + -Drevision="$REVISION" \ + -Drelease.preflight=true \ + -DskipTests \ + -Ddependency-check.skip=true \ + -Dlicense.skip=true \ + -Dexistdb.release.key="$EXISTDB_RELEASE_KEY_ID" \ + -Dexistdb.release.key.passphrase="$EXISTDB_RELEASE_KEY_PASSPHRASE" \ + clean deploy + + - name: Collect distribution archives + run: | + mkdir -p /tmp/release-assets + cp exist-distribution/target/*.zip /tmp/release-assets/ 2>/dev/null || true + cp exist-distribution/target/*.tar.bz2 /tmp/release-assets/ 2>/dev/null || true + + - uses: actions/upload-artifact@v7 + with: + name: release-linux + path: /tmp/release-assets/ + retention-days: 1 + + # ── Job 2: Build signed + notarized macOS DMG ──────────────────────────────── + build-mac: + name: Build macOS DMG + runs-on: macos-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ env.JAVA_VERSION }} + + - uses: ./.github/actions/maven-cache + + - uses: ./.github/actions/maven-github-settings + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Import Developer ID certificate + env: + EXISTDB_MAC_CERTIFICATE: ${{ secrets.EXISTDB_MAC_CERTIFICATE }} + EXISTDB_MAC_CERTIFICATE_PASSWORD: ${{ secrets.EXISTDB_MAC_CERTIFICATE_PASSWORD }} + run: | + KEYCHAIN_PASS=$(openssl rand -base64 32) + security create-keychain -p "$KEYCHAIN_PASS" release.keychain + security default-keychain -s release.keychain + security unlock-keychain -p "$KEYCHAIN_PASS" release.keychain + security set-keychain-settings -lut 21600 release.keychain + echo "$EXISTDB_MAC_CERTIFICATE" | base64 --decode > /tmp/cert.p12 + security import /tmp/cert.p12 -k release.keychain \ + -P "$EXISTDB_MAC_CERTIFICATE_PASSWORD" -T /usr/bin/codesign + security set-key-partition-list \ + -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASS" release.keychain + rm /tmp/cert.p12 + + - name: Build, sign, notarize and staple DMG + env: + EXISTDB_APPLE_ID: ${{ secrets.EXISTDB_APPLE_ID }} + EXISTDB_APPLE_APP_PASSWORD: ${{ secrets.EXISTDB_APPLE_APP_PASSWORD }} + EXISTDB_APPLE_TEAM_ID: ${{ secrets.EXISTDB_APPLE_TEAM_ID }} + run: | + TAG="${{ github.event.inputs.tag || github.ref_name }}" + REVISION="${TAG#eXist-}" + mvn -V -B --no-transfer-progress \ + -Prelease-build \ + -Dmac-signing=true \ + -Drevision="$REVISION" \ + -DskipTests \ + -Ddependency-check.skip=true \ + -Dlicense.skip=true \ + -Dmac.codesign.identity="${{ vars.EXISTDB_MAC_CODESIGN_IDENTITY }}" \ + -Dexistdb.release.notarize.apple-id="$EXISTDB_APPLE_ID" \ + -Dexistdb.release.notarize.password="$EXISTDB_APPLE_APP_PASSWORD" \ + -Dexistdb.release.notarize.team-id="$EXISTDB_APPLE_TEAM_ID" \ + clean package + + - name: Verify DMG notarization + run: | + DMG=$(find exist-distribution/target -name "*.dmg" | head -1) + xcrun stapler validate "$DMG" + + - name: Collect DMG + run: | + mkdir -p /tmp/release-assets + cp exist-distribution/target/*.dmg /tmp/release-assets/ 2>/dev/null || true + + - uses: actions/upload-artifact@v7 + with: + name: release-mac + path: /tmp/release-assets/ + retention-days: 1 + + # ── Job 3: Build signed Windows installer ─────────────────────────────────── + build-windows: + name: Build Windows installer + runs-on: windows-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ env.JAVA_VERSION }} + + - uses: ./.github/actions/maven-cache + + - uses: ./.github/actions/maven-github-settings + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Azure login (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Build installer + shell: bash + run: | + TAG="${{ github.event.inputs.tag || github.ref_name }}" + REVISION="${TAG#eXist-}" + mvn -V -B --no-transfer-progress \ + -Prelease-build \ + -Drevision="$REVISION" \ + -DskipTests \ + -Ddependency-check.skip=true \ + -Dlicense.skip=true \ + clean package + + - name: Sign installer JAR (Azure Key Vault JCA) + shell: bash + env: + AZURE_KEYVAULT_URI: ${{ vars.AZURE_KEYVAULT_URI }} + run: | + JAR=$(find exist-installer/target -name "*.jar" \ + -not -name "*sources*" -not -name "*javadoc*" | head -1) + [ -n "$JAR" ] || { echo "No installer JAR found in exist-installer/target"; exit 1; } + # Download Azure Key Vault JCA provider to classpath + KV_JCA_JAR="$HOME/.m2/azure-keyvault-jca.jar" + if [ ! -f "$KV_JCA_JAR" ]; then + mvn -q dependency:get \ + -Dartifact=com.azure:azure-security-keyvault-jca:2.10.0:jar \ + -Ddest="$KV_JCA_JAR" + fi + VAULT_NAME="${AZURE_KEYVAULT_URI##https://}" + VAULT_NAME="${VAULT_NAME%%.*}" + CERT_NAME=$(az keyvault certificate list \ + --vault-name "$VAULT_NAME" --query "[0].name" -o tsv) + ACCESS_TOKEN=$(az account get-access-token \ + --resource "https://vault.azure.net" --query accessToken -o tsv) + jarsigner \ + -keystore NONE \ + -storetype AzureKeyVault \ + -providerClass com.azure.security.keyvault.jca.KeyVaultJcaProvider \ + -providerArg "-J-Dazure.keyvault.uri=${AZURE_KEYVAULT_URI}" \ + -J-Dazure.keyvault.accessToken="$ACCESS_TOKEN" \ + -J-cp "$KV_JCA_JAR" \ + -tsa http://timestamp.sectigo.com/ \ + "$JAR" "$CERT_NAME" + jarsigner -verify -strict "$JAR" + + - name: Sign .exe with Authenticode (AzureSignTool) + shell: pwsh + env: + AZURE_KEYVAULT_URI: ${{ vars.AZURE_KEYVAULT_URI }} + run: | + $exe = Get-ChildItem -Path exist-installer/target -Filter "*.exe" | + Select-Object -First 1 + if (-not $exe) { + Write-Host "No .exe produced on this runner; skipping Authenticode signing" + exit 0 + } + dotnet tool install --global AzureSignTool --version 5.0.0 + $vaultName = ($env:AZURE_KEYVAULT_URI -replace 'https://|\.vault\.azure\.net/?', '') + $certName = az keyvault certificate list ` + --vault-name $vaultName --query "[0].name" -o tsv + $token = az account get-access-token ` + --resource "https://vault.azure.net" --query accessToken -o tsv + AzureSignTool sign ` + --azure-key-vault-url $env:AZURE_KEYVAULT_URI ` + --azure-key-vault-certificate $certName ` + --azure-key-vault-accesstoken $token ` + --timestamp-rfc3161 http://timestamp.sectigo.com/ ` + --description "eXist-db Installer" ` + $exe.FullName + $sig = Get-AuthenticodeSignature $exe.FullName + if ($sig.Status -ne 'Valid') { + Write-Error "Authenticode signature invalid: $($sig.Status)" + exit 1 + } + + - name: Collect installer artifacts + shell: bash + run: | + mkdir -p /tmp/release-assets + find exist-installer/target \ + -name "*.jar" -not -name "*sources*" -not -name "*javadoc*" \ + -exec cp {} /tmp/release-assets/ \; + find exist-installer/target -name "*.exe" \ + -exec cp {} /tmp/release-assets/ \; 2>/dev/null || true + + - uses: actions/upload-artifact@v7 + with: + name: release-windows + path: /tmp/release-assets/ + retention-days: 1 + + # ── Job 4: Publish GitHub Release ─────────────────────────────────────────── + publish-github-release: + name: Publish GitHub Release + runs-on: ubuntu-latest + timeout-minutes: 15 + needs: [build-linux, build-mac, build-windows] + steps: + - uses: actions/download-artifact@v4 + with: + pattern: release-* + merge-multiple: true + path: /tmp/release-assets + + - name: List release assets + run: ls -lh /tmp/release-assets/ + + - uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.event.inputs.tag || github.ref_name }} + files: /tmp/release-assets/* + generate_release_notes: true diff --git a/exist-versioning-release.md b/exist-versioning-release.md index ec784a5e2f0..f5004091130 100644 --- a/exist-versioning-release.md +++ b/exist-versioning-release.md @@ -84,150 +84,87 @@ It is trivial for a developer to relate a timestamp back to a Git hash (by using ### Where the version number is stored -The version number is stored in the `exist-parent/pom.xml` file, in a single property, ``. The Semantic Versioning number `3.2.0-SNAPSHOT` would be stored as follows: -``` -3.2.0-SNAPSHOT +The version number is stored in `exist-parent/pom.xml` as the `` CI-friendly property: +```xml + + 7.0.0-SNAPSHOT + ``` +All module `` blocks reference `${revision}`. The `flatten-maven-plugin` resolves `${revision}` to a literal version in every installed or deployed POM so that downstream consumers see a concrete version, not the placeholder. + That version number is also copied into the `META-INF/MANIFEST.MF` file of any Jar packages that are built, using the standard manifest attributes: `Specification-Version` and `Implementation-Version`. ## Release Process -This section details concrete steps for creating and publishing product releases. Each section here assumes you are starting with a clean Git checkout of the `develop` branch from [https://github.com/eXist-db/exist.git](https://github.com/eXist-db/exist.git). +This section details concrete steps for creating and publishing product releases. Releases are fully automated via two GitHub Actions workflows — no local Maven invocation is required for normal releases. + +### Overview: two-workflow release pattern + +| Workflow | Trigger | What it does | +|----------|---------|--------------| +| `ci-release-prepare.yml` | `workflow_dispatch` | Updates `CITATION.cff`, commits, creates annotated tag `eXist-X.Y.Z`, pushes | +| `ci-release.yml` | `push.tags: eXist-*` | Parallel platform builds → GitHub Release | -### Initiating Semantic Versioning +The `ci-release.yml` workflow runs four jobs in parallel then converges: -Version 3.0.0 was released before Semantic Versioning. The following steps will initiate Semantic Versioning for the remainder of the development phase of the next release, a new minor version to be called version 3.1.0: +| Job | Runner | Output | +|-----|--------|--------| +| `build-linux` | ubuntu-latest | zip + tar.bz2 archives; deploy to Maven Central | +| `build-mac` | macos-latest | signed + notarized DMG | +| `build-windows` | windows-latest | signed installer JAR + Authenticode `.exe` | +| `publish-github-release` | ubuntu-latest | GitHub Release with all assets attached | -1. Modify `$EXIST_HOME/build.properties` to read: +### Prerequisites: required GitHub secrets - ``` - project.version = 3.1.0-SNAPSHOT - ``` +All secrets must be in place under **Settings → Secrets and variables → Actions** before running a release. See `plans/internal-release-runbook.template.md` for the full table and rotation guidance. -2. Commit the changes and push to `origin` (or `upstream` if you are on a fork). +| Secret | Used by | +|--------|---------| +| `RELEASE_PAT` | `ci-release-prepare` — PAT with `contents:write`; required because `GITHUB_TOKEN` pushes do not trigger downstream tag workflows | +| `EXISTDB_RELEASE_KEY` | `build-linux` — GPG private key (armored, base64-encoded); imported via `gpg --import` | +| `EXISTDB_RELEASE_KEY_ID` | `build-linux` — GPG key ID passed to `-Dexistdb.release.key=` (e.g. `ABC1234`) | +| `EXISTDB_RELEASE_KEY_PASSPHRASE` | `build-linux` — GPG passphrase | +| `CENTRAL_TOKEN_USERNAME` | `build-linux` — Sonatype Central Portal user token username | +| `CENTRAL_TOKEN_PASSWORD` | `build-linux` — Sonatype Central Portal user token password | +| `EXISTDB_MAC_CERTIFICATE` | `build-mac` — Developer ID Application cert (base64 PKCS12) | +| `EXISTDB_MAC_CERTIFICATE_PASSWORD` | `build-mac` — Certificate password | +| `EXISTDB_APPLE_ID` | `build-mac` — Apple ID for `notarytool` | +| `EXISTDB_APPLE_APP_PASSWORD` | `build-mac` — App-specific password for `notarytool` | +| `EXISTDB_APPLE_TEAM_ID` | `build-mac` — Apple Developer Team ID | +| `AZURE_CLIENT_ID` | `build-windows` — OIDC app registration client ID | +| `AZURE_TENANT_ID` | `build-windows` — Azure tenant | +| `AZURE_SUBSCRIPTION_ID` | `build-windows` — Azure subscription | + +Repository variable (not a secret): `AZURE_KEYVAULT_URI` (e.g. `https://exist-db-signing.vault.azure.net/`) and `EXISTDB_MAC_CODESIGN_IDENTITY`. ### Preparing a Product Release -Once development on a new stable version is complete, the following steps will prepare the version for release. For purposes of illustration, we will assume we are preparing the stable release of version 5.3.0. -You will require a system with: -* macOS -* JDK 8 -* Maven 3.6.0+ -* Docker -* GnuPG -* A GPG key (for signing release artifacts) -* A Java KeyStore with key (for signing IzPack Installer) -* A valid Apple Developer Certificate (for signing Mac DMG) -* A Github account and username / password or Github Personal access tokens (https://github.com/settings/tokens) with permission to publish Github releases to the eXist-db .org - -1. You will need login credentials for the eXist-db organisation on: - 1. Sonatype OSS staging for Maven Central - https://oss.sonatype.org/ - 2. DockerHub - https://cloud.docker.com/orgs/existdb/ - - Your credentials for these should be stored securely in the ` section on your machine in your local `~/.m2/settings.xml` file, e.g.: - ```xml - - - - - - - sonatype-nexus-staging - YOUR-USERNAME - YOUR-PASSWORD - - - - - docker.io - YOUR-USERNAME - YOUR-PASSWORD - - - - - github - [Github Personal access tokens] - - - - ``` - -2. You will need your GPG Key, Java KeyStore, and Apple Notarization API credentials for signing the release artifacts in the ` section on your machine in your local `~/.m2/settings.xml` file, e.g.: - ```xml - - - - existdb-release-signing - - ABC1234 - ${user.home}/.gnupg/pubring.gpg - ${user.home}/.gnupg/secring.gpg - your-password - - ${user.home}/your.store - your-keystore-password - your-alias - your-key-password - - your-apple-developer-email@your-dom.ain - your-apple-notarize-api-password - - - - - - - - - existdb-release-signing - - - ``` - -3. Merge any outstanding PRs that have been reviewed and accepted for the milestone eXist-5.3.0. - -4. Make sure that you have the HEAD of `origin/develop` (or `upstream` if you are on a fork). - -5. Prepare the release, if you wish you can do a dry-run first by specifiying `-DdryRun=true`: - ``` - $ mvn -Ddocker=true -Dmac-signing=true -P installer -Dizpack-signing=true -Darguments="-Ddocker=true -Dmac-signing=true -P installer -Dizpack-signing=true" release:prepare - ``` - - Maven will start the release process and prompt you for any information that it requires, for example: - - ``` - [INFO] --- maven-release-plugin:2.1:prepare (default-cli) @ exist --- - [INFO] Verifying that there are no local modifications... - [INFO] ignoring changes on: pom.xml.next, pom.xml.releaseBackup, pom.xml.tag, pom.xml.backup, pom.xml.branch, release.properties - [INFO] Executing: /bin/sh -c cd /Users/aretter/code/exist.maven && git status - [INFO] Working directory: /Users/aretter/code/exist.maven - [INFO] Checking dependencies and plugins for snapshots ... - What is the release version for "eXist-db"? (org.exist-db:exist) 5.3.0: : - What is SCM release tag or label for "eXist-db"? (org.exist-db:exist) eXist-5.3.0: : - What is the new development version for "eXist-db"? (org.exist-db:exist) 5.4.0-SNAPSHOT: : - ``` - -6. Once the prepare process completes you can perform the release. This will upload Maven Artifacts to Maven -Central (staging), Docker images to Docker Hub, and eXist-db distributions and installer to Github releases: - ``` - $ mvn -Ddocker=true -Dmac-signing=true -P installer -Dizpack-signing=true -Djarsigner.skip=false -Darguments="-Ddocker=true -Dmac-signing=true -P installer -Dizpack-signing=true -Djarsigner.skip=false" release:perform - ``` - -7. Update the stable branch (`master`) of eXist-db to reflect the latest release: - ``` - $ git push origin eXist-5.3.0:master - ``` +For purposes of illustration, we will assume we are preparing the stable release of version 7.0.0. + +1. Merge any outstanding PRs that have been reviewed and accepted for the milestone eXist-7.0.0. + +2. Confirm that CI is green on `develop` (or your release branch). + +3. Go to **Actions → Prepare Release** and click **Run workflow**. Enter the version number (e.g. `7.0.0`). Click **Run workflow**. + + The workflow will: + - Run `mvn -Pcitation-release-metadata -DupdateCff=true -Drevision=7.0.0 validate` to update `CITATION.cff`. + - Commit the change if `CITATION.cff` was modified (`[release] Prepare eXist-7.0.0`). + - Create an annotated tag `eXist-7.0.0`. + - Push the commit and the tag. + +4. The tag push automatically triggers **Actions → Release**. Monitor the four parallel jobs. Total runtime is approximately 45–90 minutes (macOS notarization and Windows Authenticode signing dominate). + +5. When all four jobs pass, the **Publish GitHub Release** job creates the GitHub Release and attaches all artifacts automatically. #### Publishing/Promoting the Product Release + 1. Check that the new versions are visible on [Github](https://github.com/eXist-db/exist/releases). 2. Check that the new versions are visible on [DockerHub](https://hub.docker.com/r/existdb/existdb). -3. Login to https://oss.sonatype.org and release the Maven artifacts to Maven central as described [here](https://central.sonatype.org/pages/releasing-the-deployment.html). +3. Maven Central: the `build-linux` job deploys via `central-publishing-maven-plugin` with `autoPublish=true`. Artifacts are queued for sync immediately after upload. Check [central.sonatype.com](https://central.sonatype.com) for the `org.exist-db` namespace to confirm propagation (typically 15–30 min after job completion). 4. Update the Mac HomeBrew for eXist-db, see: [Releasing to Homebrew](https://github.com/eXist-db/exist/blob/develop/exist-versioning-release.md#releasing-to-homebrew). @@ -298,6 +235,12 @@ Central (staging), Docker images to Docker Hub, and eXist-db distributions and i 13. Go to GitHub and move all issues and PRs which are still open for the release milestone to the next release milestone. Close the release milestone. +### Manual fallback (CI unavailable) + +If the CI release workflow is unavailable, the `exist-release` Maven profile (backed by `maven-release-plugin`) remains usable for emergency releases. This path requires a local macOS machine with valid Apple credentials, GnuPG, and all signing keys available in `~/.m2/settings.xml`. See `plans/internal-release-runbook.template.md` §9 for the full procedure and required properties. + +Tag naming must still follow the `eXist-X.Y.Z` convention. After a manual tag push, re-run **Actions → Release** via `workflow_dispatch` with the tag name to produce platform artifacts that were skipped locally. + ### Releasing to Homebrew [Homebrew](http://brew.sh) is a popular command-line package manager for macOS. Once Homebrew is installed, applications like eXist can be installed via a simple command. eXist's presence on Homebrew is found in the Caskroom project, as a "cask", at [https://github.com/caskroom/homebrew-cask/blob/master/Casks/exist-db.rb](https://github.com/caskroom/homebrew-cask/blob/master/Casks/exist-db.rb). From 71943fe7438c7fca3e7a971f5ffb90c3fe108e27 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 19:16:10 +0200 Subject: [PATCH 03/10] [bugfix] remove default eb mac codesign cert closes #6414 --- exist-distribution/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exist-distribution/pom.xml b/exist-distribution/pom.xml index db5fbfae870..b986540b754 100644 --- a/exist-distribution/pom.xml +++ b/exist-distribution/pom.xml @@ -54,7 +54,7 @@ ${mac.bundle.dir}/Contents/Resources ${mac.bundle.dir}/Contents/Java ${project.build.directory}/eXist-db-${project.version}.dmg - Developer ID Application: Evolved Binary Ltd + From 8daadcf5048fd57bb2a4c32ffd6cf825a61f2e67 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 19:21:03 +0200 Subject: [PATCH 04/10] [ci] fix Docker tag publishing on release close #4117 --- .github/workflows/ci-container.yml | 44 ++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-container.yml b/.github/workflows/ci-container.yml index 97e7580f50b..4a17e7e163c 100644 --- a/.github/workflows/ci-container.yml +++ b/.github/workflows/ci-container.yml @@ -1,6 +1,11 @@ name: Publish Container on: push: + branches: + - develop + - master + tags: + - 'eXist-*' pull_request: schedule: - cron: "0 6 * * *" @@ -11,8 +16,13 @@ jobs: name: Test and Publish Container Images runs-on: ubuntu-latest timeout-minutes: 60 - # NOTE (DP): Publish on develop and master, test on PRs against these - if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' || github.base_ref == 'develop' || github.base_ref == 'master' + # Publish on develop (latest) and eXist-* tags (versioned + release); test on PRs against these branches. + if: > + github.ref == 'refs/heads/develop' || + github.ref == 'refs/heads/master' || + startsWith(github.ref, 'refs/tags/eXist-') || + github.base_ref == 'develop' || + github.base_ref == 'master' steps: - uses: actions/checkout@v6 with: @@ -43,7 +53,17 @@ jobs: timeout-minutes: 35 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn -V -B --no-transfer-progress -q -Pdocker -DskipTests -Ddependency-check.skip=true -P !mac-dmg-on-unix,!installer,!concurrency-stress-tests,!micro-benchmarks,skip-build-dist-archives clean package + run: | + REVISION_ARG="" + if [[ "${{ github.ref }}" == refs/tags/eXist-* ]]; then + VERSION="${{ github.ref_name }}" + REVISION_ARG="-Drevision=${VERSION#eXist-}" + fi + mvn -V -B --no-transfer-progress -q \ + -Pdocker -DskipTests -Ddependency-check.skip=true \ + -P '!mac-dmg-on-unix,skip-build-dist-archives' \ + $REVISION_ARG \ + clean package - name: Check local images run: docker image ls - name: Check license headers @@ -73,8 +93,6 @@ jobs: name: exist-core-failed-log path: exist.log - # NOTE (DP): When on master push release, when on develop push latest: Version is included automatically - # TODO (DP): Confirm that releases triggered from maven publish images with the non SNAPSHOT version - name: Publish latest images if: github.repository == 'eXist-db/exist' && github.ref == 'refs/heads/develop' env: @@ -83,14 +101,24 @@ jobs: DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} run: mvn --no-transfer-progress -q -Ddocker.tag=latest -Ddocker.username=$DOCKER_USERNAME -Ddocker.password=$DOCKER_PASSWORD docker:build docker:push working-directory: ./exist-docker - - name: Publish release images - if: github.repository == 'eXist-db/exist' && github.ref == 'refs/heads/master' + + - name: Publish versioned release images + if: github.repository == 'eXist-db/exist' && startsWith(github.ref, 'refs/tags/eXist-') env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} - run: mvn --no-transfer-progress -q -Ddocker.tag=release -Ddocker.username=$DOCKER_USERNAME -Ddocker.password=$DOCKER_PASSWORD docker:build docker:push + run: | + VERSION="${{ github.ref_name }}" + VERSION="${VERSION#eXist-}" + mvn --no-transfer-progress -q \ + -Drevision="$VERSION" \ + -Ddocker.tag=release \ + -Ddocker.username=$DOCKER_USERNAME \ + -Ddocker.password=$DOCKER_PASSWORD \ + docker:build docker:push working-directory: ./exist-docker + # NOTE (DP): This is for debugging, publishes an experimental image from inside PRs against develop # - name: Publish experimental images # if: github.base_ref == 'develop' From eb9663f45c1629dff2b79ce50f570e0a4a0d9dfc Mon Sep 17 00:00:00 2001 From: Dannes Wessels Date: Fri, 29 May 2026 22:38:47 +0200 Subject: [PATCH 05/10] [bugfix] make sure that in both jansi related JARfiles the mac native code is signed. --- exist-core/pom.xml | 2 +- exist-distribution/pom.xml | 1 + .../src/main/scripts/codesign-jansi-mac.sh | 50 +++++++++++-------- exist-parent/pom.xml | 1 + 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/exist-core/pom.xml b/exist-core/pom.xml index f320af4a2b7..01074c14bec 100644 --- a/exist-core/pom.xml +++ b/exist-core/pom.xml @@ -222,7 +222,7 @@ org.jline jline 4.1.3 - jdk11 + ${jline.classifier} diff --git a/exist-distribution/pom.xml b/exist-distribution/pom.xml index b986540b754..8663ccf3b93 100644 --- a/exist-distribution/pom.xml +++ b/exist-distribution/pom.xml @@ -1027,6 +1027,7 @@ ${jansi.version} ${project.build.directory}/jansi-native ${mac.codesign.identity} + ${jline.classifier} diff --git a/exist-distribution/src/main/scripts/codesign-jansi-mac.sh b/exist-distribution/src/main/scripts/codesign-jansi-mac.sh index 706f05027a5..fc226472724 100755 --- a/exist-distribution/src/main/scripts/codesign-jansi-mac.sh +++ b/exist-distribution/src/main/scripts/codesign-jansi-mac.sh @@ -37,37 +37,45 @@ # $2 is the jansi version # $3 is temp work directory # $4 the mac codesign identity +# $5 is the jline classifier (e.g. jdk11) set -e #set -x ## enable to help debug -# ensure a clean temp work directory -if [ -d "${3}/org" ] -then - rm -rf "${3}/org" -fi - -# for each native arch -archs=('arm64' 'x86' 'x86_64') -for arch in ${archs[@]} +# for each jar file +for jar in "${1}/jansi-${2}.jar" "${1}/jline-${2}-${5}.jar" do - # create the temp output dirs - mkdir -p "${3}/org/jline/nativ/Mac/${arch}" + # ensure a clean temp work directory for each jar + if [ -d "${3}/org" ] + then + rm -rf "${3}/org" + fi + + # for each native arch + archs=('arm64' 'x86' 'x86_64') + for arch in "${archs[@]}" + do + # create the temp output dirs + mkdir -p "${3}/org/jline/nativ/Mac/${arch}" - # switch to temp output dir - pushd "${3}" + # switch to temp output dir + pushd "${3}" - # extract the native files - jar -xf "${1}/jansi-${2}.jar" "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" + # extract the native files + jar -xf "${jar}" "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" - # test if the file is unsigned, and sign if needed - /usr/bin/codesign --verbose --test-requirement="=anchor trusted" --verify "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" || /usr/bin/codesign --verbose --force --timestamp --sign "${4}" "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" + # test if the file is unsigned, and sign if needed + /usr/bin/codesign --verbose --test-requirement="=anchor trusted" \ + --verify "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" || \ + /usr/bin/codesign --verbose --force --timestamp --sign "${4}" \ + "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" - # overwrite the file in the jar - jar -uf "${1}/jansi-${2}.jar" "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" + # overwrite the file in the jar + jar -uf "${jar}" "org/jline/nativ/Mac/${arch}/libjlinenative.jnilib" - # switch back from temp output dir - popd + # switch back from temp output dir + popd + done done diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index 1a25a8c7a8f..b29c72af77d 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -129,6 +129,7 @@ 76.1 5.2.5 4.1.3 + jdk11 4.0.5 4.0.2 2.0.3 From 67eb9fb7127a658ae9fa4dce9febb1dc8ff33130 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 20:01:14 +0200 Subject: [PATCH 06/10] [ci] bump plugin versions and migrate notarization to API Key auth --- .github/workflows/ci-release.yml | 24 +++++++++++++++++------- exist-distribution/pom.xml | 12 ++++++------ exist-parent/pom.xml | 4 ++-- exist-versioning-release.md | 8 ++++---- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index b3abe79ab37..441f844367d 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -130,11 +130,17 @@ jobs: -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASS" release.keychain rm /tmp/cert.p12 + - name: Write Apple API key + env: + EXISTDB_APPLE_API_KEY: ${{ secrets.EXISTDB_APPLE_API_KEY }} + run: | + echo "$EXISTDB_APPLE_API_KEY" | base64 --decode > /tmp/notarytool.p8 + chmod 600 /tmp/notarytool.p8 + - name: Build, sign, notarize and staple DMG env: - EXISTDB_APPLE_ID: ${{ secrets.EXISTDB_APPLE_ID }} - EXISTDB_APPLE_APP_PASSWORD: ${{ secrets.EXISTDB_APPLE_APP_PASSWORD }} - EXISTDB_APPLE_TEAM_ID: ${{ secrets.EXISTDB_APPLE_TEAM_ID }} + EXISTDB_APPLE_API_KEY_ID: ${{ secrets.EXISTDB_APPLE_API_KEY_ID }} + EXISTDB_APPLE_API_ISSUER_ID: ${{ secrets.EXISTDB_APPLE_API_ISSUER_ID }} run: | TAG="${{ github.event.inputs.tag || github.ref_name }}" REVISION="${TAG#eXist-}" @@ -146,11 +152,15 @@ jobs: -Ddependency-check.skip=true \ -Dlicense.skip=true \ -Dmac.codesign.identity="${{ vars.EXISTDB_MAC_CODESIGN_IDENTITY }}" \ - -Dexistdb.release.notarize.apple-id="$EXISTDB_APPLE_ID" \ - -Dexistdb.release.notarize.password="$EXISTDB_APPLE_APP_PASSWORD" \ - -Dexistdb.release.notarize.team-id="$EXISTDB_APPLE_TEAM_ID" \ + -Dexistdb.release.notarize.key-path=/tmp/notarytool.p8 \ + -Dexistdb.release.notarize.key-id="$EXISTDB_APPLE_API_KEY_ID" \ + -Dexistdb.release.notarize.issuer-id="$EXISTDB_APPLE_API_ISSUER_ID" \ clean package + - name: Remove Apple API key + if: always() + run: rm -f /tmp/notarytool.p8 + - name: Verify DMG notarization run: | DMG=$(find exist-distribution/target -name "*.dmg" | head -1) @@ -251,7 +261,7 @@ jobs: Write-Host "No .exe produced on this runner; skipping Authenticode signing" exit 0 } - dotnet tool install --global AzureSignTool --version 5.0.0 + dotnet tool install --global AzureSignTool --version 7.0.1 $vaultName = ($env:AZURE_KEYVAULT_URI -replace 'https://|\.vault\.azure\.net/?', '') $certName = az keyvault certificate list ` --vault-name $vaultName --query "[0].name" -o tsv diff --git a/exist-distribution/pom.xml b/exist-distribution/pom.xml index 8663ccf3b93..05b689b49d2 100644 --- a/exist-distribution/pom.xml +++ b/exist-distribution/pom.xml @@ -1191,12 +1191,12 @@ notarytool submit ${mac.dmg} - --apple-id - ${existdb.release.notarize.apple-id} - --password - ${existdb.release.notarize.password} - --team-id - ${existdb.release.notarize.team-id} + --key + ${existdb.release.notarize.key-path} + --key-id + ${existdb.release.notarize.key-id} + --issuer + ${existdb.release.notarize.issuer-id} --wait diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index b29c72af77d..124557d19f2 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -839,12 +839,12 @@ org.codehaus.mojo flatten-maven-plugin - 1.7.0 + 1.7.3 org.sonatype.central central-publishing-maven-plugin - 0.7.0 + 0.10.0 software.xdev diff --git a/exist-versioning-release.md b/exist-versioning-release.md index f5004091130..7a0c351aaf3 100644 --- a/exist-versioning-release.md +++ b/exist-versioning-release.md @@ -127,11 +127,11 @@ All secrets must be in place under **Settings → Secrets and variables → Acti | `EXISTDB_RELEASE_KEY_PASSPHRASE` | `build-linux` — GPG passphrase | | `CENTRAL_TOKEN_USERNAME` | `build-linux` — Sonatype Central Portal user token username | | `CENTRAL_TOKEN_PASSWORD` | `build-linux` — Sonatype Central Portal user token password | -| `EXISTDB_MAC_CERTIFICATE` | `build-mac` — Developer ID Application cert (base64 PKCS12) | +| `EXISTDB_MAC_CERTIFICATE` | `build-mac` — Developer ID Application cert (base64 PKCS12) for codesigning | | `EXISTDB_MAC_CERTIFICATE_PASSWORD` | `build-mac` — Certificate password | -| `EXISTDB_APPLE_ID` | `build-mac` — Apple ID for `notarytool` | -| `EXISTDB_APPLE_APP_PASSWORD` | `build-mac` — App-specific password for `notarytool` | -| `EXISTDB_APPLE_TEAM_ID` | `build-mac` — Apple Developer Team ID | +| `EXISTDB_APPLE_API_KEY` | `build-mac` — App Store Connect API private key (base64-encoded `.p8`) for notarytool | +| `EXISTDB_APPLE_API_KEY_ID` | `build-mac` — API Key ID (10-char alphanumeric) | +| `EXISTDB_APPLE_API_ISSUER_ID` | `build-mac` — App Store Connect Issuer ID (UUID) | | `AZURE_CLIENT_ID` | `build-windows` — OIDC app registration client ID | | `AZURE_TENANT_ID` | `build-windows` — Azure tenant | | `AZURE_SUBSCRIPTION_ID` | `build-windows` — Azure subscription | From 87ce60e736c2708a7bf9247a2e9296a5215db53c Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 20:20:59 +0200 Subject: [PATCH 07/10] [ci] harden release workflows: - least-privilege permissions, - remove token from CLI args, - SHA-pin third-party actions --- .github/workflows/ci-container.yml | 4 +-- .github/workflows/ci-release.yml | 46 +++++++++++++----------------- exist-parent/pom.xml | 36 ++++++++++++++++------- exist-versioning-release.md | 6 ++-- 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci-container.yml b/.github/workflows/ci-container.yml index 4a17e7e163c..b772217a16b 100644 --- a/.github/workflows/ci-container.yml +++ b/.github/workflows/ci-container.yml @@ -33,11 +33,11 @@ jobs: distribution: temurin java-version: '21' - name: Set up QEMU - uses: docker/setup-qemu-action@v4 + uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4 with: platforms: linux/amd64,linux/arm64 - name: Make buildkit default - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 id: buildx - uses: ./.github/actions/maven-cache - uses: ./.github/actions/maven-github-settings diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index 441f844367d..b584806d138 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -19,7 +19,7 @@ on: type: string permissions: - contents: write + contents: read # default; jobs that need more declare it explicitly env: JAVA_VERSION: '21' @@ -77,7 +77,6 @@ jobs: -Ddependency-check.skip=true \ -Dlicense.skip=true \ -Dexistdb.release.key="$EXISTDB_RELEASE_KEY_ID" \ - -Dexistdb.release.key.passphrase="$EXISTDB_RELEASE_KEY_PASSPHRASE" \ clean deploy - name: Collect distribution archives @@ -90,13 +89,13 @@ jobs: with: name: release-linux path: /tmp/release-assets/ - retention-days: 1 + retention-days: 3 # ── Job 2: Build signed + notarized macOS DMG ──────────────────────────────── build-mac: name: Build macOS DMG runs-on: macos-latest - timeout-minutes: 60 + timeout-minutes: 90 steps: - uses: actions/checkout@v6 with: @@ -175,13 +174,16 @@ jobs: with: name: release-mac path: /tmp/release-assets/ - retention-days: 1 + retention-days: 3 # ── Job 3: Build signed Windows installer ─────────────────────────────────── build-windows: name: Build Windows installer runs-on: windows-latest timeout-minutes: 60 + permissions: + id-token: write # OIDC for Azure Key Vault signing + contents: read steps: - uses: actions/checkout@v6 with: @@ -199,7 +201,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Azure login (OIDC) - uses: azure/login@v2 + uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -233,18 +235,12 @@ jobs: -Dartifact=com.azure:azure-security-keyvault-jca:2.10.0:jar \ -Ddest="$KV_JCA_JAR" fi - VAULT_NAME="${AZURE_KEYVAULT_URI##https://}" - VAULT_NAME="${VAULT_NAME%%.*}" - CERT_NAME=$(az keyvault certificate list \ - --vault-name "$VAULT_NAME" --query "[0].name" -o tsv) - ACCESS_TOKEN=$(az account get-access-token \ - --resource "https://vault.azure.net" --query accessToken -o tsv) + CERT_NAME="${{ vars.AZURE_KEYVAULT_CERT_NAME }}" jarsigner \ -keystore NONE \ -storetype AzureKeyVault \ -providerClass com.azure.security.keyvault.jca.KeyVaultJcaProvider \ -providerArg "-J-Dazure.keyvault.uri=${AZURE_KEYVAULT_URI}" \ - -J-Dazure.keyvault.accessToken="$ACCESS_TOKEN" \ -J-cp "$KV_JCA_JAR" \ -tsa http://timestamp.sectigo.com/ \ "$JAR" "$CERT_NAME" @@ -262,17 +258,13 @@ jobs: exit 0 } dotnet tool install --global AzureSignTool --version 7.0.1 - $vaultName = ($env:AZURE_KEYVAULT_URI -replace 'https://|\.vault\.azure\.net/?', '') - $certName = az keyvault certificate list ` - --vault-name $vaultName --query "[0].name" -o tsv - $token = az account get-access-token ` - --resource "https://vault.azure.net" --query accessToken -o tsv + $certName = '${{ vars.AZURE_KEYVAULT_CERT_NAME }}' AzureSignTool sign ` - --azure-key-vault-url $env:AZURE_KEYVAULT_URI ` - --azure-key-vault-certificate $certName ` - --azure-key-vault-accesstoken $token ` - --timestamp-rfc3161 http://timestamp.sectigo.com/ ` - --description "eXist-db Installer" ` + --azure-key-vault-url $env:AZURE_KEYVAULT_URI ` + --azure-key-vault-certificate $certName ` + --azure-key-vault-managed-identity ` + --timestamp-rfc3161 http://timestamp.sectigo.com/ ` + --description "eXist-db Installer" ` $exe.FullName $sig = Get-AuthenticodeSignature $exe.FullName if ($sig.Status -ne 'Valid') { @@ -294,7 +286,7 @@ jobs: with: name: release-windows path: /tmp/release-assets/ - retention-days: 1 + retention-days: 3 # ── Job 4: Publish GitHub Release ─────────────────────────────────────────── publish-github-release: @@ -302,8 +294,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 needs: [build-linux, build-mac, build-windows] + permissions: + contents: write # create GitHub Release steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v7 with: pattern: release-* merge-multiple: true @@ -312,7 +306,7 @@ jobs: - name: List release assets run: ls -lh /tmp/release-assets/ - - uses: softprops/action-gh-release@v2 + - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: tag_name: ${{ github.event.inputs.tag || github.ref_name }} files: /tmp/release-assets/* diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index 124557d19f2..75299c595dc 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -1507,16 +1507,32 @@ ${existdb.release.key} - ${existdb.release.key.passphrase} - - --batch - --pinentry-mode - loopback - + EXISTDB_RELEASE_KEY_PASSPHRASE + bc + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + jar-no-fork + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + jar + + + org.sonatype.central central-publishing-maven-plugin @@ -1567,10 +1583,10 @@ existdb.release.key existdb.release.key is required for GPG artifact signing. - - existdb.release.key.passphrase - existdb.release.key.passphrase is required for GPG artifact signing. - + + EXISTDB_RELEASE_KEY_PASSPHRASE + EXISTDB_RELEASE_KEY_PASSPHRASE env var is required for GPG artifact signing. + diff --git a/exist-versioning-release.md b/exist-versioning-release.md index 7a0c351aaf3..7e457585a69 100644 --- a/exist-versioning-release.md +++ b/exist-versioning-release.md @@ -115,10 +115,12 @@ The `ci-release.yml` workflow runs four jobs in parallel then converges: | `build-windows` | windows-latest | signed installer JAR + Authenticode `.exe` | | `publish-github-release` | ubuntu-latest | GitHub Release with all assets attached | -### Prerequisites: required GitHub secrets +### Prerequisites: required GitHub secrets and repository rules All secrets must be in place under **Settings → Secrets and variables → Actions** before running a release. See `plans/internal-release-runbook.template.md` for the full table and rotation guidance. +A **tag ruleset** restricts creation and deletion of `eXist-*` tags to users with the Maintain or Admin role (Settings → Rules → Rulesets). The `RELEASE_PAT` owner must hold one of those roles; all other automation only reads tags and is unaffected. + | Secret | Used by | |--------|---------| | `RELEASE_PAT` | `ci-release-prepare` — PAT with `contents:write`; required because `GITHUB_TOKEN` pushes do not trigger downstream tag workflows | @@ -136,7 +138,7 @@ All secrets must be in place under **Settings → Secrets and variables → Acti | `AZURE_TENANT_ID` | `build-windows` — Azure tenant | | `AZURE_SUBSCRIPTION_ID` | `build-windows` — Azure subscription | -Repository variable (not a secret): `AZURE_KEYVAULT_URI` (e.g. `https://exist-db-signing.vault.azure.net/`) and `EXISTDB_MAC_CODESIGN_IDENTITY`. +Repository variables (not secrets): `AZURE_KEYVAULT_URI` (e.g. `https://exist-db-signing.vault.azure.net/`), `AZURE_KEYVAULT_CERT_NAME` (the certificate name as it appears in Key Vault, e.g. `existdb-code-signing`), and `EXISTDB_MAC_CODESIGN_IDENTITY`. ### Preparing a Product Release From cba7030e06d0c465b6a9ca62d6b9b09f84ab8cc1 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 20:59:47 +0200 Subject: [PATCH 08/10] [fix] cleanup CI profile calls CiFriendliesOnly --- .github/workflows/ci-snapshots.yml | 2 +- .github/workflows/ci-test.yml | 6 ++--- .github/workflows/sonarcloud.yml | 2 +- AGENTS.md | 35 ++++++++++++++++++++++++++++++ exist-distribution/pom.xml | 7 ++---- exist-parent/pom.xml | 2 +- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci-snapshots.yml b/.github/workflows/ci-snapshots.yml index 7f725fec994..df6a2ebee19 100644 --- a/.github/workflows/ci-snapshots.yml +++ b/.github/workflows/ci-snapshots.yml @@ -31,5 +31,5 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | mvn -V -B --no-transfer-progress -q -DskipTests -Ddependency-check.skip=true \ - -P !mac-dmg-on-unix,!installer,!concurrency-stress-tests,!micro-benchmarks,skip-build-dist-archives \ + -P skip-build-dist-archives \ clean deploy diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 764d8839ac3..9f0a001a592 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -94,7 +94,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MAVEN_OPTS: ${{ env.MAVEN_OPTS }} -D'aether.connector.basic.connectTimeout=10000' -D'aether.connector.basic.requestTimeout=30000' - run: ${{ steps.install-mvnd.outputs.mvnd-dir }}/mvnd -V -B --no-transfer-progress -T 1C compile test-compile -Ponnx-model -D'dependency-check.skip' -D'license.skip' --projects '!exist-installer' + run: ${{ steps.install-mvnd.outputs.mvnd-dir }}/mvnd -V -B --no-transfer-progress -T 1C compile test-compile -Ponnx-model -D'dependency-check.skip' -D'license.skip' - name: Maven Unit Tests id: unit-tests if: matrix.test-type == 'unit' @@ -109,10 +109,10 @@ jobs: - name: Maven Integration Tests if: matrix.test-type == 'integration' timeout-minutes: 45 - run: ${{ steps.install-mvnd.outputs.mvnd-dir }}/mvnd -V -B --no-transfer-progress verify -Ponnx-model -DskipUnitTests=true -D'dependency-check.skip' -D'license.skip' -D'mvnd.maxLostKeepAlive=6000' + run: ${{ steps.install-mvnd.outputs.mvnd-dir }}/mvnd -V -B --no-transfer-progress verify "-Ponnx-model,!mac-dmg-on-mac" -DskipUnitTests=true -D'dependency-check.skip' -D'license.skip' -D'mvnd.maxLostKeepAlive=6000' - name: Javadoc (ubuntu unit only) if: matrix.os == 'ubuntu-latest' && matrix.test-type == 'unit' - run: ${{ steps.install-mvnd.outputs.mvnd-dir }}/mvnd -V -B --no-transfer-progress -q -T 1C install javadoc:javadoc -DskipTests -D'dependency-check.skip' -D'license.skip' --projects '!exist-distribution,!exist-installer' --also-make + run: ${{ steps.install-mvnd.outputs.mvnd-dir }}/mvnd -V -B --no-transfer-progress -q -T 1C install javadoc:javadoc -DskipTests -D'dependency-check.skip' -D'license.skip' --projects '!exist-distribution' --also-make - name: Maven Code Coverage (Develop branch, ubuntu unit only) if: github.event_name != 'pull_request' && github.ref == 'refs/heads/develop' && matrix.os == 'ubuntu-latest' && matrix.test-type == 'unit' env: diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 50e8e1307b0..db6aa4306fb 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -30,4 +30,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn -V -B --no-transfer-progress -Dsurefire.useFile=false -DtrimStackTrace=false -Ddependency-check.skip=true -Ddocker=false -P \!mac-dmg-on-mac,\!codesign-mac-dmg,\!mac-dmg-on-unix,\!installer,\!concurrency-stress-tests,\!micro-benchmarks,\!build-dist-archives verify site org.sonarsource.scanner.maven:sonar-maven-plugin:sonar + run: mvn -V -B --no-transfer-progress -Dsurefire.useFile=false -DtrimStackTrace=false -Ddependency-check.skip=true -Ddocker=false -Pskip-build-dist-archives verify site org.sonarsource.scanner.maven:sonar-maven-plugin:sonar diff --git a/AGENTS.md b/AGENTS.md index 69f616609eb..384cc23fe02 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -41,6 +41,41 @@ mvn test -pl exist-core -Ddependency-check.skip=true -Ddocker=false mvn test -pl exist-core -Dtest="org.exist.xquery.XPathQueryTest" -Ddependency-check.skip=true -Ddocker=false ``` +### Distribution artifacts (zip, tar.bz2, DMG) + +Produces release archives and, on macOS, an unsigned DMG suitable for local testing. +Output lands in `exist-distribution/target/`. + +```bash +JAVA_HOME=$(/usr/libexec/java_home -v 21) \ + mvn -T1.5C clean package \ + -pl exist-distribution -am \ + -DskipTests \ + -Ddependency-check.skip=true \ + -Ddocker=false \ + -Drevision=7.0.0-SNAPSHOT +``` + +The DMG is unsigned. For the fully signed and notarized DMG used in releases, see `exist-versioning-release.md`. + +### IzPack installer JAR + +Produces the cross-platform installer JAR in `exist-installer/target/`. +Maven will warn "could not be activated because it does not exist" for the `installer` profile — this is a Maven 3 multi-module quirk; the build is correct. + +```bash +JAVA_HOME=$(/usr/libexec/java_home -v 21) \ + mvn -T1.5C clean package \ + -Pinstaller \ + -pl exist-installer -am \ + -DskipTests \ + -Ddependency-check.skip=true \ + -Ddocker=false \ + -Drevision=7.0.0-SNAPSHOT +``` + +Run the installer: `java -jar exist-installer/target/exist-installer-7.0.0-SNAPSHOT.jar` + ### Docker image ```bash diff --git a/exist-distribution/pom.xml b/exist-distribution/pom.xml index 05b689b49d2..9c9a2334861 100644 --- a/exist-distribution/pom.xml +++ b/exist-distribution/pom.xml @@ -1064,11 +1064,8 @@ mac - - - mac-signing - true - + diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index 75299c595dc..b2fca1b1ca0 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -1227,7 +1227,7 @@ flatten-maven-plugin true - resolveCiFriendlyVersions + resolveCiFriendliesOnly From dd3adbb0fb18b8fa04040a5bb538e9055bc53a5c Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 31 May 2026 23:26:48 +0200 Subject: [PATCH 09/10] [chore] bump min mvn version to latest 3.9 in prep for maven 4 --- .github/actions/install-mvnd/action.yml | 2 +- .github/workflows/ci-test.yml | 2 +- exist-parent/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/install-mvnd/action.yml b/.github/actions/install-mvnd/action.yml index 6869f452000..cc64f79d9bb 100644 --- a/.github/actions/install-mvnd/action.yml +++ b/.github/actions/install-mvnd/action.yml @@ -4,7 +4,7 @@ inputs: version: description: 'The version of the Maven Daemon to install' required: true - default: '1.0.3' + default: '1.0.6' file-version-suffix: description: 'A suffix to append to the version of the download file of Maven Daemon to install' required: false diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 9f0a001a592..d51f98f47e2 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -86,7 +86,7 @@ jobs: id: install-mvnd uses: ./.github/actions/install-mvnd with: - version: '1.0.3' + version: '1.0.6' file-version-suffix: '' cache: 'true' - name: Maven Build diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index b2fca1b1ca0..441906f3e06 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -112,7 +112,7 @@ 21 ${maven.compiler.release} ${maven.compiler.release} - 3.9.9 + 3.9.16 UTF-8 The eXist-db Authors From 2fc0afbb649faa03b4f483deeb8cbfd1791fe68d Mon Sep 17 00:00:00 2001 From: duncdrum Date: Mon, 1 Jun 2026 14:40:41 +0200 Subject: [PATCH 10/10] [chore] cleanup --- .github/workflows/ci-container.yml | 4 ++-- AGENTS.md | 8 ++++---- exist-distribution/pom.xml | 3 +++ exist-versioning-release.md | 2 +- pom.xml | 30 ++++-------------------------- 5 files changed, 14 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci-container.yml b/.github/workflows/ci-container.yml index b772217a16b..ba287ecbb7d 100644 --- a/.github/workflows/ci-container.yml +++ b/.github/workflows/ci-container.yml @@ -60,8 +60,8 @@ jobs: REVISION_ARG="-Drevision=${VERSION#eXist-}" fi mvn -V -B --no-transfer-progress -q \ - -Pdocker -DskipTests -Ddependency-check.skip=true \ - -P '!mac-dmg-on-unix,skip-build-dist-archives' \ + -Pdocker,skip-build-dist-archives \ + -DskipTests -Ddependency-check.skip=true \ $REVISION_ARG \ clean package - name: Check local images diff --git a/AGENTS.md b/AGENTS.md index 384cc23fe02..79aa73b9260 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,9 +17,11 @@ eXist-db is an open-source native XML database with full XQuery support. The mai ```bash JAVA_HOME=$(/usr/libexec/java_home -v 21) \ mvn -T1.5C clean install -DskipTests -Ddependency-check.skip=true -Ddocker=false \ - -P 'skip-build-dist-archives,!build-dist-archives,!mac-dmg-on-mac,!codesign-mac-dmg,!mac-dmg-on-unix,!installer,!concurrency-stress-tests,!micro-benchmarks,!appassembler-booter' + -Pskip-build-dist-archives ``` +On macOS this still produces an unsigned DMG (`mac-dmg-on-mac` is active by default on Mac runners). Add `-P '!mac-dmg-on-mac'` to skip it. + ### Build a single module ```bash @@ -61,12 +63,10 @@ The DMG is unsigned. For the fully signed and notarized DMG used in releases, se ### IzPack installer JAR Produces the cross-platform installer JAR in `exist-installer/target/`. -Maven will warn "could not be activated because it does not exist" for the `installer` profile — this is a Maven 3 multi-module quirk; the build is correct. ```bash JAVA_HOME=$(/usr/libexec/java_home -v 21) \ mvn -T1.5C clean package \ - -Pinstaller \ -pl exist-installer -am \ -DskipTests \ -Ddependency-check.skip=true \ @@ -81,7 +81,7 @@ Run the installer: `java -jar exist-installer/target/exist-installer-7.0.0-SNAPS ```bash # Build the Docker image mvn -T1.5C clean package -DskipTests -Ddependency-check.skip=true -Ddocker=true \ - -P 'skip-build-dist-archives,!build-dist-archives,!mac-dmg-on-mac,!codesign-mac-dmg,!mac-dmg-on-unix,!installer,!concurrency-stress-tests,!micro-benchmarks,!appassembler-booter' \ + -Pskip-build-dist-archives \ -pl exist-docker -am cp exist-docker/target/classes/Dockerfile exist-docker/target/exist-docker-*-docker-dir/Dockerfile diff --git a/exist-distribution/pom.xml b/exist-distribution/pom.xml index 9c9a2334861..1c5d1f1cdb4 100644 --- a/exist-distribution/pom.xml +++ b/exist-distribution/pom.xml @@ -968,6 +968,9 @@ + onnx-model diff --git a/exist-versioning-release.md b/exist-versioning-release.md index 7e457585a69..8b7c77a0674 100644 --- a/exist-versioning-release.md +++ b/exist-versioning-release.md @@ -117,7 +117,7 @@ The `ci-release.yml` workflow runs four jobs in parallel then converges: ### Prerequisites: required GitHub secrets and repository rules -All secrets must be in place under **Settings → Secrets and variables → Actions** before running a release. See `plans/internal-release-runbook.template.md` for the full table and rotation guidance. +All secrets must be in place under **Settings → Secrets and variables → Actions** before running a release. See `internal-release-runbook.template.md` for the full table and rotation guidance. A **tag ruleset** restricts creation and deletion of `eXist-*` tags to users with the Maintain or Admin role (Settings → Rules → Rulesets). The `RELEASE_PAT` owner must hold one of those roles; all other automation only reads tags and is unaffected. diff --git a/pom.xml b/pom.xml index 88916fe1325..9566e6abc41 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ + Does NOT build installer or perf modules. --> local-build true @@ -82,8 +82,8 @@ - + release-build exist-installer @@ -91,13 +91,6 @@ - - installer - - exist-installer - - - docker @@ -112,7 +105,7 @@ - + perf-tests exist-core-jcstress @@ -121,21 +114,6 @@ - - concurrency-stress-tests - - exist-core-jcstress - - - - - micro-benchmarks - - exist-core-jmh - exist-indexes-jmh - - - citation-release-metadata