From 48296990e9509bd1b4b0feddbb261ef93c664923 Mon Sep 17 00:00:00 2001 From: Denny Sheirer Date: Thu, 5 Nov 2026 05:35:18 -0500 Subject: [PATCH] #2578 GitHub workflows use latest component versions. Adds support for automatic releases on tag. Enhances the what's changed logic when selecting the previous version for the scope of the changes. (#2579) Co-authored-by: sheirerd --- .github/workflows/gradle.yml | 10 +-- .github/workflows/nightly.yml | 17 +++-- .github/workflows/release.yml | 130 ++++++++++++++++++++++++++++++++++ README.md | 25 +++++++ 4 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ba032f66..b2f6c64d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,14 +21,14 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Set up JDK 27 - uses: actions/setup-java@v3 + uses: actions/setup-java@v6 with: java-version: '27' distribution: 'liberica' java-package: 'jdk+fx' + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v6 - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: clean build + run: ./gradlew clean build diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a1b5801f..1ff57dec 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -13,32 +13,31 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Set up JDK 27 - uses: actions/setup-java@v3 + uses: actions/setup-java@v6 with: # Must match the JDK version downloaded in build.gradle (jdk_download_base) - jlink requires an exact version match java-version: '27.0.0' distribution: 'liberica' java-package: 'jdk+fx' + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v6 + - name: Build Linux and Mac releases with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: runtimeZipOthers -PprojectVersion=nightly + run: ./gradlew runtimeZipOthers -PprojectVersion=nightly - name: Build Windows release with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: runtimeZipWindows -PprojectVersion=nightly + run: ./gradlew runtimeZipWindows -PprojectVersion=nightly - name: Create Build Info file run: | echo -e "ref: $GITHUB_REF \ncommit: $GITHUB_SHA\nbuild: $(date +"%Y-%m-%dT%H:%M:%SZ")" > build/image/build_info.txt - name: Add build artifacts to nightly release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: tag_name: nightly prerelease: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..e26303d2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,130 @@ +# Publishes a release when a version tag is pushed. The tag has to match +# projectVersion in gradle.properties with a leading 'v': v0.6.2 for a final +# release, or v0.6.2-beta-1 / v0.6.2-alpha-1 for a pre-release. +name: Release + +on: + push: + tags: ['v[0-9]+.[0-9]+.[0-9]+*'] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + previous_tag: ${{ steps.previous.outputs.tag }} + steps: + - uses: actions/checkout@v7 + with: + # Full history and tags, to find the previous release tag for the release notes + fetch-depth: 0 + + - id: version + run: | + expected="v$(sed -n 's/^projectVersion=//p' gradle.properties | tr -d '[:space:]')" + if [ "$GITHUB_REF_NAME" != "$expected" ]; then + echo "::error::Tag $GITHUB_REF_NAME does not match projectVersion in gradle.properties ($expected)" + exit 1 + fi + echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" + + # Release notes list the PRs since the previous version tag (never 'nightly'). A final release + # starts from the previous final release, so it covers every alpha and beta in between. + - id: previous + run: | + exclude=(--exclude "$GITHUB_REF_NAME") + if [[ "$GITHUB_REF_NAME" != *-* ]]; then + exclude+=(--exclude '*-*') + fi + tag="$(git describe --tags --abbrev=0 --match 'v[0-9]*' "${exclude[@]}" HEAD 2>/dev/null || true)" + echo "Release notes start from: ${tag:-(GitHub default)}" + echo "tag=$tag" >> "$GITHUB_OUTPUT" + + - name: Set up JDK 27 + uses: actions/setup-java@v6 + with: + # Must match the JDK version downloaded in build.gradle (jdk_download_base) - jlink requires an exact version match + java-version: '27.0.0' + distribution: 'liberica' + java-package: 'jdk+fx' + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v6 + + - name: Build and test + run: ./gradlew clean build --console=plain + + # The runtime plugin can't build Windows and the other platforms in the same invocation. + - name: Build Linux and Mac releases + run: ./gradlew runtimeZipOthers --console=plain + + - name: Build Windows release + run: ./gradlew runtimeZipWindows --console=plain + + - name: Check release zips + env: + VERSION: ${{ steps.version.outputs.version }} + run: | + missing=0 + for platform in linux-aarch64 linux-x86_64 osx-aarch64 osx-x86_64 windows-aarch64 windows-x86_64; do + zip="build/image/sdr-trunk-${platform}-v${VERSION}.zip" + if [ ! -f "$zip" ]; then + echo "::error::Missing $zip" + missing=1 + fi + done + ls -l build/image/*.zip + exit $missing + + - uses: actions/upload-artifact@v7 + with: + name: release-zips + path: build/image/*.zip + if-no-files-found: error + retention-days: 7 + + publish: + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/download-artifact@v8 + with: + name: release-zips + path: zips + + # Publishing is split into steps that can all be repeated, so a failed + # upload or a re-run finishes the draft left behind rather than failing on + # it: gh retries uploads, and a retry of an upload that had in fact + # succeeded fails with "ReleaseAsset.name already exists" unless clobbering. + - name: Create release + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + VERSION: ${{ needs.build.outputs.version }} + PREVIOUS_TAG: ${{ needs.build.outputs.previous_tag }} + run: | + (cd zips && sha256sum *.zip > SHA256SUMS) + prerelease=() + if [[ "$GITHUB_REF_NAME" == *-* ]]; then + prerelease=(--prerelease) + fi + notes_start=() + if [ -n "$PREVIOUS_TAG" ]; then + notes_start=(--notes-start-tag "$PREVIOUS_TAG") + fi + if gh release view "$GITHUB_REF_NAME" --json isDraft --jq .isDraft 2>/dev/null | grep -qx false; then + echo "::error::Release $GITHUB_REF_NAME is already published" + exit 1 + elif gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then + echo "Reusing the draft release $GITHUB_REF_NAME" + else + gh release create "$GITHUB_REF_NAME" --draft "${prerelease[@]}" \ + --verify-tag --generate-notes "${notes_start[@]}" --title "Version $VERSION" + fi + gh release upload "$GITHUB_REF_NAME" zips/* --clobber + gh release edit "$GITHUB_REF_NAME" --draft=false diff --git a/README.md b/README.md index 274312a3..1b0f7efe 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,28 @@ committed to the code base, so it's not really 'nightly' as much as it is 'curre * **Operating System:** Windows (~~32 or~~ 64-bit), Linux (~~32 or~~ 64-bit) or Mac (64-bit, 12.x or higher) * **CPU:** 4-core * **RAM:** 8GB or more (preferred). Depending on usage, 4GB may be sufficient. + +## Creating a Release (Maintainers) +Releases are built and published automatically by the [Release](.github/workflows/release.yml) GitHub workflow +whenever a version tag is pushed to the repository. + +1. Update `projectVersion` in `gradle.properties` to the new version, following the naming convention described in +that file (e.g. `0.6.2-alpha-1`, `0.6.2-beta-1` or `0.6.2`). +2. Commit and push the change to `master`. +3. Create and push a tag that matches the version with a leading `v`: +``` +git tag v0.6.2-beta-1 +git push origin v0.6.2-beta-1 +``` + +The workflow then: +* Verifies that the tag matches `projectVersion` in `gradle.properties` and fails if it does not. +* Builds and tests the code, then creates the release zips for Linux, Mac and Windows (x86-64 and aarch64). +* Creates a GitHub release titled `Version ` with auto-generated release notes (a "What's Changed" list of +the PRs merged since the previous version tag), and attaches the six zip +files plus a `SHA256SUMS` checksum file. +* Marks tags containing a dash (alpha and beta versions) as pre-releases. Tags without a dash become full releases. + +If the workflow fails part way through, fix the problem and re-run it from the Actions tab. It resumes from the +draft release left behind. It won't modify a release that has already been published. To rebuild a published +release, delete the release and the tag on GitHub, then push the tag again.