From fea4dacf8ceec4bfd8e6db7fce5336c4bd4b0460 Mon Sep 17 00:00:00 2001 From: TestingBot Date: Wed, 15 Jul 2026 15:05:04 +0200 Subject: [PATCH 1/3] Publish a thin main jar; attach runnable uber jar as 'shaded' classifier maven-shade-plugin replaced the main artifact with the uber jar, so the published com.testingbot:TestingBotTunnel Maven artifact bundled Jetty, Apache HTTP, commons-cli, etc. Consumers (e.g. the Jenkins TestingBot plugin) then got those bundled classes shadowing their own copies on a flat classpath, breaking modern APIs and the test harness. Attach the shaded uber jar under the 'shaded' classifier instead of replacing the main artifact: - Maven Central gets a thin main jar whose POM declares the real dependencies (transitive, correctly versioned). - Docker, the CLI release asset, and the package-time smoke test use the runnable '-shaded' jar. - The GitHub release asset keeps the familiar runnable TestingBotTunnel-.jar name. Verified locally: main jar has 0 bundled Jetty classes (451 KB); shaded jar runs 'java -jar ... --version'. --- .github/workflows/release.yml | 12 ++++++++++-- Dockerfile | 2 +- pom.xml | 8 +++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 319eabf..2d8b75a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,11 +43,19 @@ jobs: MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - # Upload the JAR as a release asset + # The published Maven artifact is now the thin jar; use the runnable "shaded" jar as the + # downloadable CLI release asset, keeping the familiar TestingBotTunnel-.jar name. + - name: Prepare runnable jar for release + run: | + VERSION=${GITHUB_REF#refs/tags/v} + mkdir -p release-assets + cp target/TestingBotTunnel-${VERSION}-shaded.jar release-assets/TestingBotTunnel-${VERSION}.jar + + # Upload the runnable JAR as a release asset - name: Upload JAR to GitHub Releases uses: softprops/action-gh-release@v1 with: - files: target/TestingBotTunnel-*.jar + files: release-assets/TestingBotTunnel-*.jar env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 89d62b7..4b2e09b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ RUN mvn -B -ntp -DskipTests \ -Dmaven.javadoc.skip=true \ -Dmaven.source.skip=true \ package \ - && mv target/TestingBotTunnel-*.jar target/testingbot-tunnel.jar + && mv target/TestingBotTunnel-*-shaded.jar target/testingbot-tunnel.jar # -------- Runtime stage -------- FROM eclipse-temurin:11-jre-jammy diff --git a/pom.xml b/pom.xml index 945f394..94edf6a 100644 --- a/pom.xml +++ b/pom.xml @@ -146,6 +146,12 @@ shade + + true + shaded true @@ -254,7 +260,7 @@ java -jar - ${project.build.directory}/${project.build.finalName}.jar + ${project.build.directory}/${project.build.finalName}-shaded.jar --version From 44a9709909e41f49eb1ff8f2b88ad80d9aba68b4 Mon Sep 17 00:00:00 2001 From: TestingBot Date: Wed, 15 Jul 2026 15:13:29 +0200 Subject: [PATCH 2/3] Add manual 'Publish to Maven Central' workflow (workflow_dispatch) Lets us publish the current POM version to Central on demand (e.g. 4.8, already released on GitHub/Docker) without re-tagging or re-running the GitHub release + Docker jobs. Deploy-only, mirrors release.yml's Central/GPG setup. Run it from a branch that produces the thin jar. --- .github/workflows/maven-publish.yml | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/maven-publish.yml diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml new file mode 100644 index 0000000..fd45088 --- /dev/null +++ b/.github/workflows/maven-publish.yml @@ -0,0 +1,38 @@ +name: Publish to Maven Central + +# Manually publish the current POM version to Maven Central, without creating a +# GitHub release or Docker image (use this to publish a version that was already +# tagged/released on GitHub, e.g. 4.8). Select the branch to run from in the +# "Run workflow" dropdown — it publishes whatever version the checked-out POM has. +# +# NOTE: Maven Central versions are immutable. Only run this from a branch whose +# build produces the thin main jar (i.e. after the thin-jar change is merged). +on: + workflow_dispatch: + +jobs: + publish: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + cache: 'maven' + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE + + - name: Build and deploy to Maven Central + run: mvn -B clean deploy -DskipTests -Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }} + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} From 07e29ee1144fcd5e2c77b4fa8c5f2050bbc70d43 Mon Sep 17 00:00:00 2001 From: TestingBot Date: Wed, 15 Jul 2026 15:29:48 +0200 Subject: [PATCH 3/3] Harden publish workflows per review: pin SHAs, least-privilege, concurrency, GPG env maven-publish.yml: - Add contents:read permissions and a maven-central-publish concurrency group (queue, never race) - Pin actions/checkout + actions/setup-java to commit SHAs; set persist-credentials: false - Drop the inline -Dgpg.passphrase (passphrase already supplied via the GPG_PASSPHRASE env by setup-java) release.yml: - Pin softprops/action-gh-release to v3 commit SHA (was mutable @v1) Skipped: restricting workflow_dispatch to a protected release tag + ref/version validation. The workflow is intentionally a maintainer-only manual publish (workflow_dispatch needs repo write and secrets) that must be runnable from master or a feature branch (e.g. to publish 4.8 thin from this branch); tying it to a protected tag defeats that, and Central's immutability already blocks overwriting an existing version. --- .github/workflows/maven-publish.yml | 16 +++++++++++++--- .github/workflows/release.yml | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index fd45088..04afb11 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -10,16 +10,26 @@ name: Publish to Maven Central on: workflow_dispatch: +permissions: + contents: read + +# Never deploy two publishes to Central at the same time; queue instead of racing. +concurrency: + group: maven-central-publish + cancel-in-progress: false + jobs: publish: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Set up JDK 11 - uses: actions/setup-java@v4 + uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4 with: java-version: '11' distribution: 'temurin' @@ -31,7 +41,7 @@ jobs: gpg-passphrase: GPG_PASSPHRASE - name: Build and deploy to Maven Central - run: mvn -B clean deploy -DskipTests -Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }} + run: mvn -B clean deploy -DskipTests env: MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d8b75a..daa930b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,7 @@ jobs: # Upload the runnable JAR as a release asset - name: Upload JAR to GitHub Releases - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3 with: files: release-assets/TestingBotTunnel-*.jar env: