diff --git a/.github/actions/release-macos-x86_64/action.yml b/.github/actions/release-macos-x86_64/action.yml index 7d8f8b76..7331f2cf 100644 --- a/.github/actions/release-macos-x86_64/action.yml +++ b/.github/actions/release-macos-x86_64/action.yml @@ -12,22 +12,6 @@ inputs: description: 'The target platform.' required: true - maven-gpg-private-key: - description: 'The GPG private key to sign Maven artifacts.' - required: true - - maven-gpg-passphrase: - description: 'The GPG passphrase for the GPG key.' - required: true - - maven-username: - description: 'The Maven username.' - required: true - - maven-password: - description: 'The Maven password.' - required: true - runs: using: "composite" steps: @@ -55,11 +39,6 @@ runs: architecture: 'x64' java-version: ${{ inputs.java-version }} distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - gpg-private-key: ${{ inputs.maven-gpg-private-key }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - name: Build run: arch -x86_64 mvn package -DskipTests -Pmacos-cross-x86_64 @@ -69,10 +48,13 @@ runs: run: arch -x86_64 mvn -B jar:jar surefire:test -Pmacos-cross-x86_64 shell: bash - - name: Deploy - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - MAVEN_GPG_PASSPHRASE: ${{ inputs.maven-gpg-passphrase }} - run: arch -x86_64 mvn deploy -DskipTests -Pmacos-cross-x86_64 -Prelease - shell: bash + # Maven Central publishes a version as one atomic bundle, so this job must not + # deploy. The native library jar is handed to the aggregating publish-central + # job instead, which attaches every platform to a single deployment. + - name: Upload native library jar + uses: actions/upload-artifact@v4 + with: + name: natives-${{ inputs.platform-name }} + path: webrtc-jni/target/webrtc-java-*.jar + if-no-files-found: error + retention-days: 1 diff --git a/.github/actions/release/action.yml b/.github/actions/release/action.yml index 94f2fdb4..15cd1f2f 100644 --- a/.github/actions/release/action.yml +++ b/.github/actions/release/action.yml @@ -11,23 +11,6 @@ inputs: platform-name: description: 'The target platform.' required: true - - maven-gpg-private-key: - description: 'The GPG private key to sign Maven artifacts.' - required: true - - maven-gpg-passphrase: - description: 'The GPG passphrase for the GPG key.' - required: true - - maven-username: - description: 'The Maven username.' - required: true - - maven-password: - description: 'The Maven password.' - required: true - runs: using: "composite" steps: @@ -54,11 +37,6 @@ runs: with: java-version: ${{ inputs.java-version }} distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - gpg-private-key: ${{ inputs.maven-gpg-private-key }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - name: Build run: | @@ -76,17 +54,13 @@ runs: run: mvn -B jar:jar surefire:test shell: bash - - name: Deploy - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - MAVEN_GPG_PASSPHRASE: ${{ inputs.maven-gpg-passphrase }} - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn deploy -DskipTests -Prelease -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn deploy -DskipTests -Prelease -Plinux-aarch64 - else - mvn deploy -DskipTests -Prelease - fi - shell: bash + # Maven Central publishes a version as one atomic bundle, so this job must not + # deploy. The native library jar is handed to the aggregating publish-central + # job instead, which attaches every platform to a single deployment. + - name: Upload native library jar + uses: actions/upload-artifact@v4 + with: + name: natives-${{ inputs.platform-name }} + path: webrtc-jni/target/webrtc-java-*.jar + if-no-files-found: error + retention-days: 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 107b6912..da5187e0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,11 @@ on: description: "Default version to use for new local working copy." required: true default: "X.Y.Z-SNAPSHOT" + dryRun: + description: "Dry run: build every platform and assemble the deployment bundle, but push no commits or tags and publish nothing." + required: false + type: boolean + default: false env: WEBRTC_CHECKOUT_FOLDER: webrtc @@ -47,6 +52,7 @@ jobs: OUTPUT: CHANGELOG.md - name: Commit CHANGELOG.md + if: ${{ !inputs.dryRun }} run: | git add CHANGELOG.md git commit -m "chore(release): Update CHANGELOG.md for ${{ steps.git-cliff.outputs.version }}" @@ -93,26 +99,32 @@ jobs: uses: actions/checkout@v6 with: ref: main - env: - MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} - MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - - run: | - mvn release:prepare -DskipTests -DpushChanges=false -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} - + + # A dry run transforms the poms and writes release.properties, but creates no + # commit and no tag, so there is nothing to amend or push below. + - name: Prepare release + run: | + mvn release:prepare -DskipTests -DpushChanges=false \ + -DdryRun=${{ inputs.dryRun }} \ + -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} + # Get the release version from the release.properties file - RELEASE_VERSION=$(grep "project.rel.dev.onvoid.webrtc\\\:webrtc-java=" release.properties | cut -d'=' -f2) - echo "Extracted release version from release.properties: $RELEASE_VERSION" - + RELEASE_VERSION=$(grep "project.rel.dev.onvoid.webrtc\\\:webrtc-java=" release.properties 2>/dev/null | cut -d'=' -f2 || true) + echo "Extracted release version from release.properties: ${RELEASE_VERSION:-}" + echo "RELEASE_VERSION=$RELEASE_VERSION" >> "$GITHUB_ENV" + + - name: Push release commit and tag + if: ${{ !inputs.dryRun }} + run: | # Update versions.ts file echo "Updating versions.ts with release version: $RELEASE_VERSION and development version: ${{ github.event.inputs.developmentVersion }}" sed -i "s/VERSION: '.*'/VERSION: '$RELEASE_VERSION'/g" docs/.vitepress/versions.ts sed -i "s/VERSION_SNAPSHOT: '.*'/VERSION_SNAPSHOT: '${{ github.event.inputs.developmentVersion }}'/g" docs/.vitepress/versions.ts - + # Add the updated file to the existing commit git add docs/.vitepress/versions.ts git commit --amend --no-edit - + git push git push --tags @@ -137,6 +149,7 @@ jobs: - name: Get tag from current branch id: tag-selector + if: ${{ !inputs.dryRun }} shell: bash run: | git fetch -a @@ -154,10 +167,6 @@ jobs: with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} build-linux: needs: prepare-release @@ -181,6 +190,7 @@ jobs: - name: Get tag from current branch id: tag-selector + if: ${{ !inputs.dryRun }} run: | git fetch -a tag=$(git describe --tags `git rev-list --tags --max-count=1`) @@ -197,10 +207,6 @@ jobs: with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} build-macos: needs: prepare-release @@ -222,6 +228,7 @@ jobs: - name: Get tag from current branch id: tag-selector + if: ${{ !inputs.dryRun }} run: | git fetch -a tag=$(git describe --tags `git rev-list --tags --max-count=1`) @@ -239,10 +246,6 @@ jobs: with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - id: maven-build-x86_64 name: Maven build - Intel @@ -251,14 +254,140 @@ jobs: with: java-version: ${{ matrix.java }} platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - maven-gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - maven-gpg-passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + + publish-central: + name: Publish to Maven Central + needs: [build-windows, build-linux, build-macos] + outputs: + release_body: ${{ needs.build-windows.outputs.release_body }} + release_version: ${{ needs.build-windows.outputs.release_version }} + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-tags: true + + - name: Set up Maven cache + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: maven-publish-${{ hashFiles('**/pom.xml') }} + restore-keys: maven-publish- + + - name: Set up JDK 17 + uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: 'temurin' + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_TOKEN + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + + - name: Determine the version to publish + id: release-version + run: | + if [ "${{ inputs.dryRun }}" == "true" ]; then + version=$(mvn -B -q -N help:evaluate -Dexpression=project.version -DforceStdout) + else + git fetch -a + tag=$(git describe --tags `git rev-list --tags --max-count=1`) + git checkout "$tag" + version="${tag#v}" + fi + + echo "Version to publish: $version" + echo "version=$version" >> "$GITHUB_OUTPUT" + + - name: Download the native library jars of all platforms + uses: actions/download-artifact@v4 + with: + pattern: natives-* + path: natives + merge-multiple: true + + - name: Verify that every platform is present + run: | + version="${{ steps.release-version.outputs.version }}" + status=0 + + for classifier in windows-x86_64 linux-x86_64 linux-aarch64 \ + linux-aarch32 macos-x86_64 macos-aarch64; do + if [ ! -f "natives/webrtc-java-$version-$classifier.jar" ]; then + echo "::error::Missing native library jar for $classifier" + status=1 + fi + done + + exit $status + + # The webrtc module depends on its own native library jar for the host + # platform. That dependency is normally installed by webrtc-jni, which is kept + # out of the reactor here to avoid rebuilding the native libraries. + - name: Seed the local repository with the host native library + run: | + version="${{ steps.release-version.outputs.version }}" + + mvn -B install:install-file \ + -Dfile="natives/webrtc-java-$version-linux-x86_64.jar" \ + -DgroupId=dev.onvoid.webrtc \ + -DartifactId=webrtc-java \ + -Dversion="$version" \ + -Dclassifier=linux-x86_64 \ + -Dpackaging=jar \ + -DgeneratePom=false + + # skipPublishing suppresses both the bundling and the upload, so a dry run + # still builds, signs and attaches everything without anything leaving the + # runner. As a second line of defence the Central credentials are replaced by + # a placeholder during a dry run: should the upload ever happen regardless, it + # fails on authentication instead of publishing a release. Signing does run, so + # the GPG passphrase stays intact. + - name: Deploy + env: + MAVEN_USERNAME: ${{ inputs.dryRun && 'dry-run-must-not-upload' || secrets.MAVEN_USERNAME }} + MAVEN_TOKEN: ${{ inputs.dryRun && 'dry-run-must-not-upload' || secrets.MAVEN_TOKEN }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + run: > + mvn -B deploy -pl .,webrtc -Prelease -DskipTests + -Dnatives.dir="$PWD/natives" + -DskipPublishing=${{ inputs.dryRun }} + + - name: Summarize what would have been published + if: ${{ inputs.dryRun }} + run: | + { + echo "## Dry run — nothing was published" + echo + echo "Version: \`${{ steps.release-version.outputs.version }}\`" + echo + echo "Artifacts destined for the deployment bundle:" + echo '```' + ls -1 webrtc/target/*.jar webrtc/target/*.asc natives/*.asc 2>/dev/null || true + echo '```' + } >> "$GITHUB_STEP_SUMMARY" + + - name: Upload the deployment bundle for inspection + if: ${{ inputs.dryRun }} + uses: actions/upload-artifact@v4 + with: + name: deployment-bundle-dry-run + path: | + target/central-*/** + webrtc/target/central-*/** + webrtc/target/*.jar + webrtc/target/*.asc + natives/*.asc + if-no-files-found: warn + retention-days: 7 publish-release: name: Publish GitHub release - needs: [build-windows, build-linux, build-macos] + needs: publish-central + if: ${{ !inputs.dryRun }} runs-on: ubuntu-latest steps: @@ -269,7 +398,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - version="${{ needs.build-windows.outputs.release_version }}" - body="${{ needs.build-windows.outputs.release_body }}" + version="${{ needs.publish-central.outputs.release_version }}" + body="${{ needs.publish-central.outputs.release_body }}" gh release create $version -d -t "Release $version" -n "$body" \ No newline at end of file diff --git a/pom.xml b/pom.xml index c172eb75..afb54658 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,11 @@ maven-antrun-plugin 3.2.0 + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.1 + org.apache.maven.plugins maven-compiler-plugin @@ -108,6 +113,7 @@ true central + ${project.groupId}:webrtc-java:${project.version} webrtc-java-jni webrtc-java-examples @@ -139,6 +145,11 @@ + + org.apache.maven.plugins + maven-help-plugin + 3.5.1 + org.apache.maven.plugins maven-install-plugin @@ -178,11 +189,6 @@ - - org.apache.maven.plugins - maven-project-info-reports-plugin - 3.9.0 - org.apache.maven.plugins maven-release-plugin @@ -223,11 +229,6 @@ maven-surefire-plugin 3.5.6 - - org.apache.maven.plugins - maven-surefire-report-plugin - 3.5.6 - org.apache.maven.plugins maven-failsafe-plugin @@ -348,19 +349,6 @@ - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - - - org.apache.maven.plugins - maven-surefire-report-plugin - - - - org.junit.jupiter diff --git a/webrtc/pom.xml b/webrtc/pom.xml index d92bcae6..a7ba4acc 100644 --- a/webrtc/pom.xml +++ b/webrtc/pom.xml @@ -14,24 +14,6 @@ - - org.apache.maven.plugins - maven-antrun-plugin - - - attach-artifact - package - - run - - - - - - - - - org.apache.maven.plugins maven-surefire-plugin @@ -48,6 +30,112 @@ + + + + attach-native-host + + + !natives.dir + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + attach-artifact + package + + run + + + + + + + + + + + + + + + + attach-natives-all + + + natives.dir + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-natives + package + + attach-artifact + + + + + ${natives.dir}/${project.name}-${project.version}-windows-x86_64.jar + jar + windows-x86_64 + + + ${natives.dir}/${project.name}-${project.version}-linux-x86_64.jar + jar + linux-x86_64 + + + ${natives.dir}/${project.name}-${project.version}-linux-aarch64.jar + jar + linux-aarch64 + + + ${natives.dir}/${project.name}-${project.version}-linux-aarch32.jar + jar + linux-aarch32 + + + ${natives.dir}/${project.name}-${project.version}-macos-x86_64.jar + jar + macos-x86_64 + + + ${natives.dir}/${project.name}-${project.version}-macos-aarch64.jar + jar + macos-aarch64 + + + + + + + + + + + ${project.groupId} @@ -56,4 +144,4 @@ ${platform.classifier} - \ No newline at end of file +