Repository navigation
Release #55
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| developmentVersion: | |
| 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 | |
| # Only the jobs that push commits, tags or the GitHub release get write access. | |
| permissions: | |
| contents: read | |
| # Two releases at once would race on the pushed commits and tags. | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| jobs: | |
| # Nothing reaches main before release:prepare has succeeded: the changelog | |
| # commit is made locally, release:prepare adds its two commits and the tag on | |
| # top, and all of it is pushed in one atomic push at the end. A failure on the | |
| # way leaves main untouched, so the release can simply be dispatched again. | |
| prepare-release: | |
| name: Prepare release | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| contents: write | |
| outputs: | |
| release_tag: ${{ steps.release-version.outputs.tag }} | |
| release_body: ${{ steps.git-cliff.outputs.content }} | |
| steps: | |
| # The full history, for git-cliff. | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: main | |
| fetch-depth: 0 | |
| - name: Git config | |
| run: | | |
| git config --global user.name "${{ github.actor }}" | |
| git config --global user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com" | |
| # The version is the one release:prepare will tag: the pom's version without | |
| # -SNAPSHOT. git-cliff is told it rather than bumping from the commit types, so | |
| # that the changelog, the Maven tag and the GitHub release always agree. | |
| - name: Determine and check the versions | |
| id: release-version | |
| env: | |
| DEVELOPMENT_VERSION: ${{ inputs.developmentVersion }} | |
| run: | | |
| version=$(sed -n '0,/<version>/s|.*<version>\([^<]*\)</version>.*|\1|p' pom.xml) | |
| version="${version%-SNAPSHOT}" | |
| echo "Release version: $version, next development version: $DEVELOPMENT_VERSION" | |
| if ! [[ "$DEVELOPMENT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT$ ]]; then | |
| echo "::error::developmentVersion must look like 1.2.3-SNAPSHOT, got '$DEVELOPMENT_VERSION'" | |
| exit 1 | |
| fi | |
| if [ "${DEVELOPMENT_VERSION%-SNAPSHOT}" == "$version" ]; then | |
| echo "::error::developmentVersion must differ from the release version $version" | |
| exit 1 | |
| fi | |
| if git rev-parse -q --verify "refs/tags/v$version" >/dev/null; then | |
| echo "::error::Tag v$version already exists" | |
| exit 1 | |
| fi | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "tag=v$version" >> "$GITHUB_OUTPUT" | |
| # Written outside the checkout, which release:prepare requires to be clean. | |
| - name: Generate the release notes | |
| uses: orhun/git-cliff-action@v4 | |
| id: git-cliff | |
| with: | |
| config: .github/changelog/cliff-release.toml | |
| args: -v -u --strip footer --tag ${{ steps.release-version.outputs.tag }} --use-branch-tags | |
| env: | |
| OUTPUT: ${{ runner.temp }}/release-notes.md | |
| - name: Update CHANGELOG.md | |
| uses: orhun/git-cliff-action@v4 | |
| with: | |
| config: .github/changelog/cliff.toml | |
| args: -v --tag ${{ steps.release-version.outputs.tag }} --use-branch-tags | |
| env: | |
| OUTPUT: CHANGELOG.md | |
| - name: Commit CHANGELOG.md | |
| env: | |
| RELEASE_TAG: ${{ steps.release-version.outputs.tag }} | |
| run: | | |
| git add CHANGELOG.md | |
| git commit -m "chore(release): Update CHANGELOG.md for $RELEASE_TAG" | |
| - name: Set up Java | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| # preparationGoals is "clean validate" instead of the default "clean verify": | |
| # verify would compile WebRTC and FFmpeg here, on a runner without their | |
| # caches, only for the platform jobs below to build the tagged tree again. | |
| # | |
| # 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 | |
| env: | |
| DEVELOPMENT_VERSION: ${{ inputs.developmentVersion }} | |
| EXPECTED_VERSION: ${{ steps.release-version.outputs.version }} | |
| run: | | |
| mvn -B release:prepare -DpushChanges=false \ | |
| -DpreparationGoals="clean validate" \ | |
| -DdryRun=${{ inputs.dryRun }} \ | |
| -DdevelopmentVersion="$DEVELOPMENT_VERSION" | |
| # Get the release version from the release.properties file | |
| 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:-<none>}" | |
| if [ "$RELEASE_VERSION" != "$EXPECTED_VERSION" ]; then | |
| echo "::error::release:prepare chose version '$RELEASE_VERSION', expected '$EXPECTED_VERSION'" | |
| exit 1 | |
| fi | |
| echo "RELEASE_VERSION=$RELEASE_VERSION" >> "$GITHUB_ENV" | |
| - name: Push release commits and tag | |
| if: ${{ !inputs.dryRun }} | |
| env: | |
| DEVELOPMENT_VERSION: ${{ inputs.developmentVersion }} | |
| RELEASE_TAG: ${{ steps.release-version.outputs.tag }} | |
| run: | | |
| # Update versions.ts file | |
| echo "Updating versions.ts with release version: $RELEASE_VERSION and development version: $DEVELOPMENT_VERSION" | |
| sed -i "s/VERSION: '.*'/VERSION: '$RELEASE_VERSION'/g" docs/.vitepress/versions.ts | |
| sed -i "s/VERSION_SNAPSHOT: '.*'/VERSION_SNAPSHOT: '$DEVELOPMENT_VERSION'/g" docs/.vitepress/versions.ts | |
| # Add the updated file to the existing commit | |
| git add docs/.vitepress/versions.ts | |
| git commit --amend --no-edit | |
| # The branch and the tag land together or not at all. | |
| git push --atomic origin HEAD:main "refs/tags/$RELEASE_TAG" | |
| # The tag prepare-release pushed. A dry run pushes none and builds the | |
| # dispatched commit instead. | |
| platforms: | |
| needs: prepare-release | |
| 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, platforms] | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ !inputs.dryRun && needs.prepare-release.outputs.release_tag || '' }} | |
| - name: Set up Maven cache | |
| uses: actions/cache@v6 | |
| with: | |
| path: | | |
| ~/.m2/repository | |
| !~/.m2/repository/dev/onvoid/webrtc | |
| 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 | |
| env: | |
| RELEASE_TAG: ${{ needs.prepare-release.outputs.release_tag }} | |
| run: | | |
| if [ "${{ inputs.dryRun }}" == "true" ]; then | |
| version=$(mvn -B -q -N help:evaluate -Dexpression=project.version -DforceStdout) | |
| else | |
| version="${RELEASE_TAG#v}" | |
| fi | |
| echo "Version to publish: $version" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| # 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 | |
| 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 }} | |
| with: | |
| version: ${{ steps.release-version.outputs.version }} | |
| profiles: release | |
| skip-publishing: ${{ 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 \ | |
| webrtc-java-media/target/*.jar webrtc-java-media/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@v7 | |
| with: | |
| name: deployment-bundle-dry-run | |
| path: | | |
| target/central-*/** | |
| webrtc/target/central-*/** | |
| webrtc/target/*.jar | |
| webrtc/target/*.asc | |
| webrtc-java-media/target/central-*/** | |
| webrtc-java-media/target/*.jar | |
| webrtc-java-media/target/*.asc | |
| natives/*.asc | |
| if-no-files-found: warn | |
| retention-days: 7 | |
| publish-release: | |
| name: Publish GitHub release | |
| needs: [prepare-release, publish-central] | |
| if: ${{ !inputs.dryRun }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| # The notes are commit subjects, so they go through the environment and a file | |
| # rather than into the script, where a quote or a backtick would be run. | |
| # --verify-tag fails instead of creating a tag that release:prepare did not. | |
| - name: Publish | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RELEASE_VERSION: ${{ needs.prepare-release.outputs.release_tag }} | |
| RELEASE_BODY: ${{ needs.prepare-release.outputs.release_body }} | |
| run: | | |
| printf '%s\n' "$RELEASE_BODY" > release-notes.md | |
| gh release create "$RELEASE_VERSION" --draft --verify-tag \ | |
| -t "Release $RELEASE_VERSION" -F release-notes.md |