diff --git a/.github/actions/build-macos-x86_64/action.yml b/.github/actions/build-macos-x86_64/action.yml deleted file mode 100644 index 6ee6d9e7..00000000 --- a/.github/actions/build-macos-x86_64/action.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: 'Maven Build' - -description: 'Build the platform dependent Java library' - -inputs: - java-version: - description: 'The Java build version.' - required: true - default: '17' - - platform-name: - description: 'The target platform.' - required: true - - maven-username: - description: 'The Maven username.' - required: true - - maven-password: - description: 'The Maven password.' - required: true - -runs: - using: "composite" - steps: - - name: Derive the WebRTC cache branch from the pom - run: echo "WEBRTC_CACHE_BRANCH=$(sed -n 's|.*branch-heads/\([^<]*\).*|\1|p' webrtc-jni/pom.xml)" >> "$GITHUB_ENV" - shell: bash - - # Restored here, saved right after the build below: the post step of - # actions/cache only saves when the whole job succeeds, so a failing test - # would otherwise throw away a WebRTC build that took the better part of an - # hour. - - id: webrtc-cache - name: Restore WebRTC cache - uses: actions/cache/restore@v6 - with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} - key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}-${{ hashFiles('webrtc-jni/pom.xml') }} - restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}- - - - name: Derive the FFmpeg version from the pom - run: echo "FFMPEG_VERSION=$(sed -n 's|.*\([^<]*\).*|\1|p' webrtc-java-media/pom.xml)" >> "$GITHUB_ENV" - shell: bash - - - id: ffmpeg-cache - name: Restore FFmpeg cache - uses: actions/cache/restore@v6 - with: - path: ~/ffmpeg - key: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}-${{ hashFiles('webrtc-java-media/pom.xml') }} - restore-keys: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}- - - # One cache per OS: the dependencies do not differ between the platforms of - # an OS. The project's own artifacts, which mvn deploy installs, change with - # every build and stay out of it. - - name: Set up Maven cache - uses: actions/cache@v6 - with: - path: | - ~/.m2/repository - !~/.m2/repository/dev/onvoid/webrtc - key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} - restore-keys: maven-${{ runner.os }}- - - # The runner is Apple Silicon. The build runs natively and cross compiles - # for Intel; only the tests need an Intel JVM, to load what was built, and - # that one runs under Rosetta. - - id: jdk-x64 - name: Set up JDK (x64, for the tests) - uses: actions/setup-java@v5 - with: - architecture: 'x64' - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - overwrite-settings: false - - # Set up last, so that it is the JAVA_HOME the build runs with and the one - # whose settings.xml carries the deploy credentials. - - name: Set up JDK (arm64, for the build) - uses: actions/setup-java@v5 - with: - architecture: 'aarch64' - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - - - name: Build - run: mvn package -DskipTests -Pmacos-cross-x86_64 - shell: bash - - - name: Save WebRTC cache - if: steps.webrtc-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v6 - with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} - key: ${{ steps.webrtc-cache.outputs.cache-primary-key }} - - - name: Save FFmpeg cache - if: steps.ffmpeg-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v6 - with: - path: ~/ffmpeg - key: ${{ steps.ffmpeg-cache.outputs.cache-primary-key }} - - - name: Test - run: JAVA_HOME="${{ steps.jdk-x64.outputs.path }}" mvn -B jar:jar surefire:test -Pmacos-cross-x86_64 -Dsurefire.timeout=1800 - shell: bash - - # What failed, for runners that cannot be reproduced locally. - - name: Upload test reports - if: failure() - uses: actions/upload-artifact@v7 - with: - name: test-reports-${{ inputs.platform-name }} - path: '**/target/surefire-reports/' - if-no-files-found: ignore - retention-days: 7 - - - name: Deploy - if: ${{ github.event_name != 'pull_request' && github.repository == 'devopvoid/webrtc-java' }} - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - run: mvn deploy -DskipTests -Pmacos-cross-x86_64 - shell: bash diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 6c5463e5..585754e1 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -1,24 +1,26 @@ name: 'Maven Build' -description: 'Build the platform dependent Java library' +description: 'Build the native libraries of one platform and upload them as artifacts' inputs: - java-version: - description: 'The Java build version.' - required: true - default: '17' - platform-name: description: 'The target platform.' required: true - maven-username: - description: 'The Maven username.' - required: true + profile: + description: 'The Maven profile that selects a cross compiled classifier. Empty for the runner''s own.' + required: false + default: '' - maven-password: - description: 'The Maven password.' - required: true + java-version: + description: 'The Java build version.' + required: false + default: '17' + + retention-days: + description: 'How long the natives artifacts are kept.' + required: false + default: '1' runs: using: "composite" @@ -28,9 +30,9 @@ runs: shell: bash # Restored here, saved right after the build below: the post step of - # actions/cache only saves when the whole job succeeds, so a failing test - # would otherwise throw away a WebRTC build that took the better part of an - # hour. + # actions/cache only saves when the whole job succeeds, so a failure in a + # later step would otherwise throw away a WebRTC build that took the better + # part of an hour. - id: webrtc-cache name: Restore WebRTC cache uses: actions/cache/restore@v6 @@ -52,8 +54,8 @@ runs: restore-keys: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}- # One cache per OS: the dependencies do not differ between the platforms of - # an OS. The project's own artifacts, which mvn deploy installs, change with - # every build and stay out of it. + # an OS. The project's own artifacts change with every build and stay out + # of it. - name: Set up Maven cache uses: actions/cache@v6 with: @@ -68,21 +70,11 @@ runs: with: java-version: ${{ inputs.java-version }} distribution: 'temurin' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - name: Build - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn package -DskipTests -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn package -DskipTests -Plinux-aarch64 - elif [ "${{ inputs.platform-name }}" == "windows_arm64" ]; then - mvn package -DskipTests -Pwindows-aarch64 - else - mvn package -DskipTests - fi + env: + PROFILE: ${{ inputs.profile }} + run: mvn -B package -DskipTests ${PROFILE:+-P$PROFILE} shell: bash - name: Save WebRTC cache @@ -99,34 +91,30 @@ runs: path: ~/ffmpeg key: ${{ steps.ffmpeg-cache.outputs.cache-primary-key }} - - name: Test - if: ${{ inputs.platform-name != 'linux_arm' && inputs.platform-name != 'linux_arm64' && inputs.platform-name != 'windows_arm64' }} - run: mvn -B jar:jar surefire:test -Dsurefire.timeout=1800 - shell: bash - - # What failed, for runners that cannot be reproduced locally. - - name: Upload test reports - if: failure() + # The natives of every platform go to test-natives, which tests them on a + # runner of their own OS and architecture, and to the callers' publishing + # job, which attaches all of them to a single deployment. Both artifacts + # hold one flat jar each, so that a natives-* download with merge-multiple + # puts every jar into one directory. + - name: Upload native library jar uses: actions/upload-artifact@v7 with: - name: test-reports-${{ inputs.platform-name }} - path: '**/target/surefire-reports/' - if-no-files-found: ignore - retention-days: 7 - - - name: Deploy - if: ${{ github.event_name != 'pull_request' && github.repository == 'devopvoid/webrtc-java' }} - env: - MAVEN_USERNAME: ${{ inputs.maven-username }} - MAVEN_TOKEN: ${{ inputs.maven-password }} - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn deploy -DskipTests -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn deploy -DskipTests -Plinux-aarch64 - elif [ "${{ inputs.platform-name }}" == "windows_arm64" ]; then - mvn deploy -DskipTests -Pwindows-aarch64 - else - mvn deploy -DskipTests - fi - shell: bash + name: natives-${{ inputs.platform-name }} + path: webrtc-jni/target/webrtc-java-*.jar + if-no-files-found: error + retention-days: ${{ inputs.retention-days }} + overwrite: true + + # Only the classifier jar: the main jar is platform independent and the + # publishing job builds it itself. + - name: Upload media native library jar + uses: actions/upload-artifact@v7 + with: + name: natives-media-${{ inputs.platform-name }} + path: | + webrtc-java-media/target/webrtc-java-media-*-windows-*.jar + webrtc-java-media/target/webrtc-java-media-*-linux-*.jar + webrtc-java-media/target/webrtc-java-media-*-macos-*.jar + if-no-files-found: error + retention-days: ${{ inputs.retention-days }} + overwrite: true diff --git a/.github/actions/publish/action.yml b/.github/actions/publish/action.yml new file mode 100644 index 00000000..2182705c --- /dev/null +++ b/.github/actions/publish/action.yml @@ -0,0 +1,84 @@ +name: 'Maven Publish' + +description: 'Deploy one version with the native libraries of every platform attached, as a single deployment' + +# Expects the checkout of the version to deploy, a JDK whose settings.xml has +# the "central" server, and MAVEN_USERNAME and MAVEN_TOKEN (plus +# MAVEN_GPG_PASSPHRASE for a release) in the environment of the calling step. + +inputs: + version: + description: 'The version to deploy, as the natives jars are named.' + required: true + + profiles: + description: 'Maven profiles to activate, comma separated. "release" adds sources, javadoc and signatures.' + required: false + default: '' + + skip-publishing: + description: 'Build, sign and bundle everything, but upload nothing.' + required: false + default: 'false' + +runs: + using: "composite" + steps: + - name: Download the native library jars of all platforms + uses: actions/download-artifact@v8 + with: + pattern: natives-* + path: natives + merge-multiple: true + + - name: Verify that every platform is present + env: + VERSION: ${{ inputs.version }} + run: | + status=0 + + for classifier in windows-x86_64 windows-aarch64 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 + if [ ! -f "natives/webrtc-java-media-$VERSION-$classifier.jar" ]; then + echo "::error::Missing media native library jar for $classifier" + status=1 + fi + done + + exit $status + shell: bash + + # 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 + env: + VERSION: ${{ inputs.version }} + run: | + 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 + shell: bash + + # natives.dir makes webrtc and webrtc-java-media attach the jars of all + # platforms instead of the host's. skipPublishing suppresses both the + # bundling and the upload. + - name: Deploy + env: + PROFILES: ${{ inputs.profiles }} + SKIP_PUBLISHING: ${{ inputs.skip-publishing }} + run: > + mvn -B deploy -pl .,webrtc,webrtc-java-media -DskipTests + ${PROFILES:+-P$PROFILES} + -Dnatives.dir="$PWD/natives" + -DskipPublishing="$SKIP_PUBLISHING" + shell: bash diff --git a/.github/actions/release-macos-x86_64/action.yml b/.github/actions/release-macos-x86_64/action.yml deleted file mode 100644 index 42656994..00000000 --- a/.github/actions/release-macos-x86_64/action.yml +++ /dev/null @@ -1,135 +0,0 @@ -name: 'Maven Release' - -description: 'Release the platform dependent Java library' - -inputs: - java-version: - description: 'The Java build version.' - required: true - default: '17' - - platform-name: - description: 'The target platform.' - required: true - -runs: - using: "composite" - steps: - - name: Derive the WebRTC cache branch from the pom - run: echo "WEBRTC_CACHE_BRANCH=$(sed -n 's|.*branch-heads/\([^<]*\).*|\1|p' webrtc-jni/pom.xml)" >> "$GITHUB_ENV" - shell: bash - - # Restored here, saved right after the build below: the post step of - # actions/cache only saves when the whole job succeeds, so a failing test - # would otherwise throw away a WebRTC build that took the better part of an - # hour. - - id: webrtc-cache - name: Restore WebRTC cache - uses: actions/cache/restore@v6 - with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} - key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}-${{ hashFiles('webrtc-jni/pom.xml') }} - restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}- - - - name: Derive the FFmpeg version from the pom - run: echo "FFMPEG_VERSION=$(sed -n 's|.*\([^<]*\).*|\1|p' webrtc-java-media/pom.xml)" >> "$GITHUB_ENV" - shell: bash - - - id: ffmpeg-cache - name: Restore FFmpeg cache - uses: actions/cache/restore@v6 - with: - path: ~/ffmpeg - key: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}-${{ hashFiles('webrtc-java-media/pom.xml') }} - restore-keys: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}- - - # One cache per OS: the dependencies do not differ between the platforms of - # an OS. The project's own artifacts, which mvn deploy installs, change with - # every build and stay out of it. - - name: Set up Maven cache - uses: actions/cache@v6 - with: - path: | - ~/.m2/repository - !~/.m2/repository/dev/onvoid/webrtc - key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} - restore-keys: maven-${{ runner.os }}- - - # The runner is Apple Silicon. The build runs natively and cross compiles - # for Intel; only the tests need an Intel JVM, to load what was built, and - # that one runs under Rosetta. - - id: jdk-x64 - name: Set up JDK ${{ inputs.java-version }} (x64, for the tests) - uses: actions/setup-java@v5 - with: - architecture: 'x64' - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - - # Set up last, so that it is the JAVA_HOME the build runs with. - - name: Set up JDK ${{ inputs.java-version }} (arm64, for the build) - uses: actions/setup-java@v5 - with: - architecture: 'aarch64' - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - - - name: Build - run: mvn package -DskipTests -Pmacos-cross-x86_64 - shell: bash - - - name: Save WebRTC cache - if: steps.webrtc-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v6 - with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} - key: ${{ steps.webrtc-cache.outputs.cache-primary-key }} - - - name: Save FFmpeg cache - if: steps.ffmpeg-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v6 - with: - path: ~/ffmpeg - key: ${{ steps.ffmpeg-cache.outputs.cache-primary-key }} - - - name: Test - run: JAVA_HOME="${{ steps.jdk-x64.outputs.path }}" mvn -B jar:jar surefire:test -Pmacos-cross-x86_64 -Dsurefire.timeout=1800 - shell: bash - - # What failed, for runners that cannot be reproduced locally. - - name: Upload test reports - if: failure() - uses: actions/upload-artifact@v7 - with: - name: test-reports-${{ inputs.platform-name }} - path: '**/target/surefire-reports/' - if-no-files-found: ignore - retention-days: 7 - - # 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@v7 - with: - name: natives-${{ inputs.platform-name }} - path: webrtc-jni/target/webrtc-java-*.jar - if-no-files-found: error - retention-days: 7 - overwrite: true - - # The media module's natives go the same way. Only the classifier jar: the - # main jar is platform independent and publish-central builds it itself. The - # name matches publish-central's natives-* download pattern, which merges - # both uploads into one flat directory. - - name: Upload media native library jar - uses: actions/upload-artifact@v7 - with: - name: natives-media-${{ inputs.platform-name }} - path: | - webrtc-java-media/target/webrtc-java-media-*-windows-*.jar - webrtc-java-media/target/webrtc-java-media-*-linux-*.jar - webrtc-java-media/target/webrtc-java-media-*-macos-*.jar - if-no-files-found: error - retention-days: 7 - overwrite: true diff --git a/.github/actions/release/action.yml b/.github/actions/release/action.yml deleted file mode 100644 index 45bba012..00000000 --- a/.github/actions/release/action.yml +++ /dev/null @@ -1,131 +0,0 @@ -name: 'Maven Release' - -description: 'Release the platform dependent Java library' - -inputs: - java-version: - description: 'The Java build version.' - required: true - default: '17' - - platform-name: - description: 'The target platform.' - required: true -runs: - using: "composite" - steps: - - name: Derive the WebRTC cache branch from the pom - run: echo "WEBRTC_CACHE_BRANCH=$(sed -n 's|.*branch-heads/\([^<]*\).*|\1|p' webrtc-jni/pom.xml)" >> "$GITHUB_ENV" - shell: bash - - # Restored here, saved right after the build below: the post step of - # actions/cache only saves when the whole job succeeds, so a failing test - # would otherwise throw away a WebRTC build that took the better part of an - # hour. - - id: webrtc-cache - name: Restore WebRTC cache - uses: actions/cache/restore@v6 - with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} - key: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}-${{ hashFiles('webrtc-jni/pom.xml') }} - restore-keys: webrtc-${{ env.WEBRTC_CACHE_BRANCH }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt') }}- - - - name: Derive the FFmpeg version from the pom - run: echo "FFMPEG_VERSION=$(sed -n 's|.*\([^<]*\).*|\1|p' webrtc-java-media/pom.xml)" >> "$GITHUB_ENV" - shell: bash - - - id: ffmpeg-cache - name: Restore FFmpeg cache - uses: actions/cache/restore@v6 - with: - path: ~/ffmpeg - key: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}-${{ hashFiles('webrtc-java-media/pom.xml') }} - restore-keys: ffmpeg-${{ env.FFMPEG_VERSION }}-${{ inputs.platform-name }}-${{ hashFiles('webrtc-java-media/src/main/cpp/dependencies/ffmpeg/CMakeLists.txt') }}- - - # One cache per OS: the dependencies do not differ between the platforms of - # an OS. The project's own artifacts, which mvn deploy installs, change with - # every build and stay out of it. - - name: Set up Maven cache - uses: actions/cache@v6 - with: - path: | - ~/.m2/repository - !~/.m2/repository/dev/onvoid/webrtc - key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} - restore-keys: maven-${{ runner.os }}- - - - name: Set up JDK ${{ inputs.java-version }} - uses: actions/setup-java@v5 - with: - java-version: ${{ inputs.java-version }} - distribution: 'temurin' - - - name: Build - run: | - if [ "${{ inputs.platform-name }}" == "linux_arm" ]; then - mvn package -DskipTests -Plinux-aarch32 - elif [ "${{ inputs.platform-name }}" == "linux_arm64" ]; then - mvn package -DskipTests -Plinux-aarch64 - elif [ "${{ inputs.platform-name }}" == "windows_arm64" ]; then - mvn package -DskipTests -Pwindows-aarch64 - else - mvn package -DskipTests - fi - shell: bash - - - name: Save WebRTC cache - if: steps.webrtc-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v6 - with: - path: ~/${{ env.WEBRTC_INSTALL_FOLDER }} - key: ${{ steps.webrtc-cache.outputs.cache-primary-key }} - - - name: Save FFmpeg cache - if: steps.ffmpeg-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v6 - with: - path: ~/ffmpeg - key: ${{ steps.ffmpeg-cache.outputs.cache-primary-key }} - - - name: Test - if: ${{ inputs.platform-name != 'linux_arm' && inputs.platform-name != 'linux_arm64' && inputs.platform-name != 'windows_arm64' }} - run: mvn -B jar:jar surefire:test -Dsurefire.timeout=1800 - shell: bash - - # What failed, for runners that cannot be reproduced locally. - - name: Upload test reports - if: failure() - uses: actions/upload-artifact@v7 - with: - name: test-reports-${{ inputs.platform-name }} - path: '**/target/surefire-reports/' - if-no-files-found: ignore - retention-days: 7 - - # 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@v7 - with: - name: natives-${{ inputs.platform-name }} - path: webrtc-jni/target/webrtc-java-*.jar - if-no-files-found: error - retention-days: 7 - overwrite: true - - # The media module's natives go the same way. Only the classifier jar: the - # main jar is platform independent and publish-central builds it itself. The - # name matches publish-central's natives-* download pattern, which merges - # both uploads into one flat directory. - - name: Upload media native library jar - uses: actions/upload-artifact@v7 - with: - name: natives-media-${{ inputs.platform-name }} - path: | - webrtc-java-media/target/webrtc-java-media-*-windows-*.jar - webrtc-java-media/target/webrtc-java-media-*-linux-*.jar - webrtc-java-media/target/webrtc-java-media-*-macos-*.jar - if-no-files-found: error - retention-days: 7 - overwrite: true diff --git a/.github/actions/test-natives/action.yml b/.github/actions/test-natives/action.yml index 490fd10c..4ae794c9 100644 --- a/.github/actions/test-natives/action.yml +++ b/.github/actions/test-natives/action.yml @@ -1,6 +1,6 @@ name: 'Test Natives' -description: 'Run the test suite on a native runner against natives that a cross compiling lane built' +description: 'Run the test suite on a runner of the platform''s own OS and architecture, against the natives the build job uploaded' inputs: platform-name: @@ -33,12 +33,20 @@ inputs: runs: using: "composite" steps: + # The build uploads each platform's two native jars as separate artifacts, + # one flat jar each. - name: Download natives uses: actions/download-artifact@v8 with: name: natives-${{ inputs.platform-name }} path: natives + - name: Download media natives + uses: actions/download-artifact@v8 + with: + name: natives-media-${{ inputs.platform-name }} + path: natives + # PulseAudio, libudev and libdbus are deliberately not installed here: the # natives open them at runtime, and the armhf lane, whose image has none of # them, proves that they load without them. @@ -64,21 +72,20 @@ runs: distribution: ${{ inputs.java-distribution }} architecture: ${{ inputs.java-architecture }} - - name: Ensure Maven - run: | - if ! command -v mvn >/dev/null 2>&1; then - url=https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip - curl -sSfLo maven.zip "$url" - echo "$(curl -sSfL "$url.sha512" | cut -d' ' -f1) maven.zip" | sha512sum -c - - unzip -q maven.zip -d "$RUNNER_TEMP/maven" - echo "$RUNNER_TEMP/maven/apache-maven-3.9.9/bin" >> "$GITHUB_PATH" - fi - shell: bash - - name: Install the natives into the local repository run: | - VERSION=$(sed -n '0,//s|.*\([^<]*\).*|\1|p' pom.xml) - JAR=$(find natives -path '*webrtc-jni*' -name 'webrtc-java-*.jar' | head -n 1) + # The root pom has no parent, so its first is the project's. + # Not sed's 0,/re/ address: that is GNU only, and macOS has BSD sed. + VERSION=$(sed -n 's|.*\([^<]*\).*|\1|p' pom.xml | head -n 1) + if [ -z "$VERSION" ]; then + echo "Could not read the project version from pom.xml" >&2 + exit 1 + fi + JAR=$(find natives -name 'webrtc-java-*-${{ inputs.classifier }}.jar' ! -name 'webrtc-java-media-*' | head -n 1) + if [ -z "$JAR" ]; then + echo "No webrtc-java natives for ${{ inputs.classifier }} in the artifact" >&2 + exit 1 + fi echo "Installing $JAR as webrtc-java:$VERSION:${{ inputs.classifier }}" mvn -B -q install:install-file -Dfile="$JAR" -DgroupId=dev.onvoid.webrtc \ -DartifactId=webrtc-java -Dversion="$VERSION" -Dpackaging=jar \ @@ -95,7 +102,7 @@ runs: - name: Unpack the natives where the tests look for them run: | MEDIA_JAR=$(find natives -name 'webrtc-java-media-*-${{ inputs.classifier }}.jar' | head -n 1) - WEBRTC_JAR=$(find natives -path '*webrtc-jni*' -name 'webrtc-java-*.jar' | head -n 1) + WEBRTC_JAR=$(find natives -name 'webrtc-java-*-${{ inputs.classifier }}.jar' ! -name 'webrtc-java-media-*' | head -n 1) if [ -z "$MEDIA_JAR" ]; then echo "No webrtc-java-media natives for ${{ inputs.classifier }} in the artifact" >&2 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2f38542..c9c1c95f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,176 +36,59 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} -env: - WEBRTC_CHECKOUT_FOLDER: webrtc - WEBRTC_INSTALL_FOLDER: webrtc/build - jobs: - build-windows: - strategy: - fail-fast: false - matrix: - platform: - - name: windows_x86_64 - runs-on: windows-2022 - - name: windows_arm64 - runs-on: windows-2022 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} + platforms: + uses: ./.github/workflows/platforms.yml + with: + # Only the deploy-snapshot job of this same run reads them. + retention-days: 1 + + # One deployment with the natives of every platform attached, the way + # release.yml publishes a release, instead of seven jobs each deploying the + # whole reactor and racing on the snapshot metadata. It runs only once every + # platform has been built and tested. + deploy-snapshot: + name: Deploy snapshot + needs: platforms + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' && github.repository == 'devopvoid/webrtc-java' + runs-on: ubuntu-22.04 steps: - name: Checkout code uses: actions/checkout@v6 - with: - # The media module builds FFmpeg from its third-party submodule. - submodules: true - - - id: prepare - name: Prepare build - uses: ./.github/actions/prepare-windows - - - id: maven-build - name: Maven build - uses: ./.github/actions/build - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - - name: Upload natives for native testing - if: matrix.platform.name == 'windows_arm64' - uses: actions/upload-artifact@v7 + - name: Set up Maven cache + uses: actions/cache@v6 with: - name: natives-${{ matrix.platform.name }} path: | - webrtc-jni/target/webrtc-java-*.jar - webrtc-java-media/target/webrtc-java-media-*.jar - if-no-files-found: error - # Only test-natives of this same run reads them. - retention-days: 1 + ~/.m2/repository + !~/.m2/repository/dev/onvoid/webrtc + key: maven-publish-${{ hashFiles('**/pom.xml') }} + restore-keys: maven-publish- - build-linux: - strategy: - fail-fast: false - matrix: - platform: - - name: linux_arm - runs-on: ubuntu-22.04 - - name: linux_arm64 - runs-on: ubuntu-22.04 - - name: linux_x86-64 - runs-on: ubuntu-22.04 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - - name: Checkout code - uses: actions/checkout@v6 + - name: Set up JDK 17 + uses: actions/setup-java@v5 with: - # The media module builds FFmpeg from its third-party submodule. - submodules: true - - - id: prepare - name: Prepare build - uses: ./.github/actions/prepare-linux - - - id: maven-build - name: Maven build - uses: ./.github/actions/build - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - - - name: Upload natives for native testing - if: matrix.platform.name == 'linux_arm' || matrix.platform.name == 'linux_arm64' - uses: actions/upload-artifact@v7 - with: - name: natives-${{ matrix.platform.name }} - path: | - webrtc-jni/target/webrtc-java-*.jar - webrtc-java-media/target/webrtc-java-media-*.jar - if-no-files-found: error - # Only test-natives of this same run reads them. - retention-days: 1 - - build-macos: - strategy: - fail-fast: false - matrix: - platform: - - name: macos_x86-64 - runs-on: macos-14 - - name: macos_arm64 - runs-on: macos-14 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - # The media module builds FFmpeg from its third-party submodule. - submodules: true - - - id: prepare-build - name: Prepare build - uses: ./.github/actions/prepare-macos - - - id: maven-build-arm64 - name: Maven build - Apple Silicon - if: matrix.platform.name == 'macos_arm64' - uses: ./.github/actions/build - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - - - id: maven-build-x86_64 - name: Maven build - Intel - if: matrix.platform.name == 'macos_x86-64' - uses: ./.github/actions/build-macos-x86_64 - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - maven-username: ${{ secrets.MAVEN_USERNAME }} - maven-password: ${{ secrets.MAVEN_TOKEN }} - - test-natives: - needs: [build-windows, build-linux] - timeout-minutes: 30 - strategy: - fail-fast: false - matrix: - platform: - - name: windows_arm64 - runs-on: windows-11-arm - classifier: windows-aarch64 - profile: windows-aarch64 - java-distribution: microsoft - java-architecture: aarch64 - - name: linux_arm64 - runs-on: ubuntu-22.04-arm - classifier: linux-aarch64 - profile: linux-aarch64 - java-distribution: temurin - java-architecture: '' - - name: linux_arm - runs-on: ubuntu-22.04-arm - classifier: linux-aarch32 - profile: linux-aarch32 - java-distribution: liberica - java-architecture: armv7 - runs-on: ${{ matrix.platform.runs-on }} - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Test natives - uses: ./.github/actions/test-natives + java-version: '17' + distribution: 'temurin' + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_TOKEN + + - name: Determine the version to deploy + id: version + run: | + version=$(mvn -B -q -N help:evaluate -Dexpression=project.version -DforceStdout) + echo "Version to deploy: $version" + if [[ "$version" != *-SNAPSHOT ]]; then + echo "::error::main is at $version, which is not a snapshot; releases are published by release.yml" + exit 1 + fi + echo "version=$version" >> "$GITHUB_OUTPUT" + + - name: Deploy + uses: ./.github/actions/publish + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} with: - platform-name: ${{ matrix.platform.name }} - classifier: ${{ matrix.platform.classifier }} - profile: ${{ matrix.platform.profile }} - java-distribution: ${{ matrix.platform.java-distribution }} - java-architecture: ${{ matrix.platform.java-architecture }} + version: ${{ steps.version.outputs.version }} diff --git a/.github/workflows/platforms.yml b/.github/workflows/platforms.yml new file mode 100644 index 00000000..ecf44bdc --- /dev/null +++ b/.github/workflows/platforms.yml @@ -0,0 +1,151 @@ +name: Platforms + +# Builds the native libraries of every supported platform, tests each of them on +# a runner of its own OS and architecture, and hands them on as artifacts: +# natives- holds the webrtc-java native jar, natives-media- +# the webrtc-java-media one. Nothing is deployed here; the callers do that once, +# from all platforms together, because Maven Central publishes a version as one +# bundle. +# +# Called by build.yml for every push and PR, and by release.yml for the tag it +# releases, so that both build exactly the same way. + +on: + workflow_call: + inputs: + ref: + description: "The commit, branch or tag to build. Empty for the one that triggered the caller." + type: string + default: '' + retention-days: + description: "How long the natives artifacts are kept." + type: number + default: 1 + +env: + # The default webrtc.install.dir of webrtc-jni/pom.xml, below the home directory. + WEBRTC_INSTALL_FOLDER: webrtc/build + +jobs: + build: + name: build (${{ matrix.platform.name }}) + strategy: + fail-fast: false + matrix: + # profile: the Maven profile that selects a cross compiled classifier; + # empty when the classifier is the runner's own. The macOS Intel + # build runs on Apple Silicon and cross compiles. + platform: + - name: windows_x86_64 + runs-on: windows-2022 + profile: '' + - name: windows_arm64 + runs-on: windows-2022 + profile: windows-aarch64 + - name: linux_x86-64 + runs-on: ubuntu-22.04 + profile: '' + - name: linux_arm64 + runs-on: ubuntu-22.04 + profile: linux-aarch64 + - name: linux_arm + runs-on: ubuntu-22.04 + profile: linux-aarch32 + - name: macos_arm64 + runs-on: macos-14 + profile: '' + - name: macos_x86-64 + runs-on: macos-14 + profile: macos-cross-x86_64 + runs-on: ${{ matrix.platform.runs-on }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + ref: ${{ inputs.ref }} + # The media module builds FFmpeg from its third-party submodule. + submodules: true + + - name: Prepare build + if: runner.os == 'Windows' + uses: ./.github/actions/prepare-windows + + - name: Prepare build + if: runner.os == 'Linux' + uses: ./.github/actions/prepare-linux + + - name: Prepare build + if: runner.os == 'macOS' + uses: ./.github/actions/prepare-macos + + - name: Maven build + uses: ./.github/actions/build + with: + platform-name: ${{ matrix.platform.name }} + profile: ${{ matrix.platform.profile }} + retention-days: ${{ inputs.retention-days }} + + # Every platform is tested on a runner of its own OS and architecture, + # against the natives the build job uploaded, so that what is tested is + # exactly what gets published. Most of them are cross compiled and could not + # be loaded on the runner that built them. + test-natives: + name: test-natives (${{ matrix.platform.name }}) + needs: build + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + # java-architecture: the JDK architecture, when it differs from the + # runner's. linux_arm runs a 32-bit ARM JDK on an arm64 runner. + platform: + - name: windows_x86_64 + runs-on: windows-2022 + classifier: windows-x86_64 + java-distribution: temurin + java-architecture: '' + - name: windows_arm64 + runs-on: windows-11-arm + classifier: windows-aarch64 + java-distribution: microsoft + java-architecture: aarch64 + - name: linux_x86-64 + runs-on: ubuntu-22.04 + classifier: linux-x86_64 + java-distribution: temurin + java-architecture: '' + - name: linux_arm64 + runs-on: ubuntu-22.04-arm + classifier: linux-aarch64 + java-distribution: temurin + java-architecture: '' + - name: linux_arm + runs-on: ubuntu-22.04-arm + classifier: linux-aarch32 + java-distribution: liberica + java-architecture: armv7 + - name: macos_arm64 + runs-on: macos-14 + classifier: macos-aarch64 + java-distribution: temurin + java-architecture: '' + - name: macos_x86-64 + runs-on: macos-15-intel + classifier: macos-x86_64 + java-distribution: temurin + java-architecture: '' + runs-on: ${{ matrix.platform.runs-on }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + ref: ${{ inputs.ref }} + + - name: Test natives + uses: ./.github/actions/test-natives + with: + platform-name: ${{ matrix.platform.name }} + classifier: ${{ matrix.platform.classifier }} + profile: ${{ matrix.platform.classifier }} + java-distribution: ${{ matrix.platform.java-distribution }} + java-architecture: ${{ matrix.platform.java-architecture }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 433eb998..6a7237b2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,10 +13,6 @@ on: type: boolean default: false -env: - WEBRTC_CHECKOUT_FOLDER: webrtc - WEBRTC_INSTALL_FOLDER: webrtc/build - # Only the jobs that push commits, tags or the GitHub release get write access. permissions: contents: read @@ -155,119 +151,18 @@ jobs: # The branch and the tag land together or not at all. git push --atomic origin HEAD:main "refs/tags/$RELEASE_TAG" - build-windows: - needs: prepare-release - strategy: - fail-fast: false - matrix: - platform: - - name: windows_x86_64 - runs-on: windows-2022 - - name: windows_arm64 - runs-on: windows-2022 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - # The tag prepare-release pushed. A dry run pushes none and builds the - # dispatched commit instead. - - name: Checkout code - uses: actions/checkout@v6 - with: - ref: ${{ !inputs.dryRun && needs.prepare-release.outputs.release_tag || '' }} - # The media module builds FFmpeg from its third-party submodule. - submodules: true - - - id: prepare - name: Prepare release build - uses: ./.github/actions/prepare-windows - - - id: maven-build - name: Maven build - uses: ./.github/actions/release - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - - build-linux: - needs: prepare-release - strategy: - fail-fast: false - matrix: - platform: - - name: linux_arm - runs-on: ubuntu-22.04 - - name: linux_arm64 - runs-on: ubuntu-22.04 - - name: linux_x86-64 - runs-on: ubuntu-22.04 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - # The tag prepare-release pushed. A dry run pushes none and builds the - # dispatched commit instead. - - name: Checkout code - uses: actions/checkout@v6 - with: - ref: ${{ !inputs.dryRun && needs.prepare-release.outputs.release_tag || '' }} - # The media module builds FFmpeg from its third-party submodule. - submodules: true - - - id: prepare-build - name: Prepare release build - uses: ./.github/actions/prepare-linux - - - id: maven-build - name: Maven build - uses: ./.github/actions/release - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - - build-macos: + # The tag prepare-release pushed. A dry run pushes none and builds the + # dispatched commit instead. + platforms: needs: prepare-release - strategy: - fail-fast: false - matrix: - platform: - - name: macos_x86-64 - runs-on: macos-14 - - name: macos_arm64 - runs-on: macos-14 - java: [17] - runs-on: ${{ matrix.platform.runs-on }} - steps: - # The tag prepare-release pushed. A dry run pushes none and builds the - # dispatched commit instead. - - name: Checkout code - uses: actions/checkout@v6 - with: - ref: ${{ !inputs.dryRun && needs.prepare-release.outputs.release_tag || '' }} - # The media module builds FFmpeg from its third-party submodule. - submodules: true - - - id: prepare-build - name: Prepare release build - uses: ./.github/actions/prepare-macos - - - id: maven-build-arm64 - name: Maven build - Apple Silicon - if: matrix.platform.name == 'macos_arm64' - uses: ./.github/actions/release - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} - - - id: maven-build-x86_64 - name: Maven build - Intel - if: matrix.platform.name == 'macos_x86-64' - uses: ./.github/actions/release-macos-x86_64 - with: - java-version: ${{ matrix.java }} - platform-name: ${{ matrix.platform.name }} + uses: ./.github/workflows/platforms.yml + with: + ref: ${{ !inputs.dryRun && needs.prepare-release.outputs.release_tag || '' }} + retention-days: 7 publish-central: name: Publish to Maven Central - needs: [prepare-release, build-windows, build-linux, build-macos] + needs: [prepare-release, platforms] runs-on: ubuntu-22.04 steps: @@ -279,7 +174,9 @@ jobs: - name: Set up Maven cache uses: actions/cache@v6 with: - path: ~/.m2/repository + path: | + ~/.m2/repository + !~/.m2/repository/dev/onvoid/webrtc key: maven-publish-${{ hashFiles('**/pom.xml') }} restore-keys: maven-publish- @@ -308,48 +205,6 @@ jobs: echo "Version to publish: $version" echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Download the native library jars of all platforms - uses: actions/download-artifact@v8 - 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 windows-aarch64 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 - if [ ! -f "natives/webrtc-java-media-$version-$classifier.jar" ]; then - echo "::error::Missing media 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 @@ -357,14 +212,15 @@ jobs: # fails on authentication instead of publishing a release. Signing does run, so # the GPG passphrase stays intact. - name: Deploy + uses: ./.github/actions/publish 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,webrtc-java-media -Prelease -DskipTests - -Dnatives.dir="$PWD/natives" - -DskipPublishing=${{ inputs.dryRun }} + with: + version: ${{ steps.release-version.outputs.version }} + profiles: release + skip-publishing: ${{ inputs.dryRun }} - name: Summarize what would have been published if: ${{ inputs.dryRun }}