From 5b6c31bd8916ca4845e14a6b9726cd9bd481d1da Mon Sep 17 00:00:00 2001 From: Gideon <87426140+GideonBear@users.noreply.github.com> Date: Fri, 31 Oct 2025 19:31:37 +0100 Subject: [PATCH] chore(release): switch to release-plz (#1333) --- .github/workflows/check_semver.yml | 30 -------- .github/workflows/create_release_assets.yml | 78 +++++++-------------- .github/workflows/release-plz.yml | 63 +++++++++++++++++ .github/workflows/release_to_aur.yml | 24 ++----- .github/workflows/release_to_homebrew.yml | 12 ++-- .github/workflows/release_to_pypi.yml | 9 +-- .github/workflows/release_to_winget.yml | 6 +- RELEASE_PROCEDURE.md | 45 +----------- 8 files changed, 106 insertions(+), 161 deletions(-) delete mode 100644 .github/workflows/check_semver.yml create mode 100644 .github/workflows/release-plz.yml diff --git a/.github/workflows/check_semver.yml b/.github/workflows/check_semver.yml deleted file mode 100644 index b7300318..00000000 --- a/.github/workflows/check_semver.yml +++ /dev/null @@ -1,30 +0,0 @@ -on: - release: - types: [published, edited] - -name: Check SemVer compliance - -permissions: - contents: read - -jobs: - prepare: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # v1.0.7 - with: - toolchain: nightly-2022-08-03 - override: true - components: rustfmt, clippy - - semver: - runs-on: ubuntu-latest - steps: - - uses: actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # v1.0.3 - with: - command: install - args: --git https://github.com/rust-lang/rust-semverver - - run: eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)" - - run: cargo semver | tee semver_out - - run: (head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1) diff --git a/.github/workflows/create_release_assets.yml b/.github/workflows/create_release_assets.yml index 2a67c62b..1ac408a5 100644 --- a/.github/workflows/create_release_assets.yml +++ b/.github/workflows/create_release_assets.yml @@ -1,23 +1,8 @@ name: Publish release files for CD native and non-cd-native environments on: - release: - types: [ created ] - # When a release failed, and there is something you need to fix in this - # YML file, you can manually re-run the job via this event to re-do the - # release. (Simply re-run the job through GitHub UI won't work as it would use - # the old YML file, which needs a fix.) - workflow_dispatch: - inputs: - # The GitHub Action (softprops/action-gh-release) used in this pipeline - # needs a tag, you specify it through this parameter. - # - # In the case described above, it should be an existing tag. E.g., the - # release of v16.0.4 failed, you should specify "v16.0.4" here. - existing_tag: - description: "The tag of the failed release that you wanna re-run and fix" - required: true - type: string + repository_dispatch: + types: [ release-created ] permissions: contents: read @@ -91,21 +76,11 @@ jobs: - name: Build in Release profile with all features enabled run: cargo build --release --all-features - - name: Determine tag name - id: determine_tag_name - shell: bash # Or it won't work on Windows - run: | - if [ -n "${{ github.event.release.tag_name }}" ]; then - echo "tag_name=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT - else - echo "tag_name=${{ github.event.inputs.existing_tag }}" >> $GITHUB_OUTPUT - fi - - name: Rename Release (Unix) run: | cargo install default-target mkdir -p assets - FILENAME=topgrade-${{ steps.determine_tag_name.outputs.tag_name }}-$(default-target) + FILENAME=topgrade-${{ github.event.client_payload.tag }}-$(default-target) mv target/release/topgrade assets cd assets tar --format=ustar -czf $FILENAME.tar.gz topgrade @@ -136,7 +111,7 @@ jobs: run: | cargo install default-target mkdir assets - FILENAME=topgrade-${{steps.determine_tag_name.outputs.tag_name}}-$(default-target) + FILENAME=topgrade-${{ github.event.client_payload.tag }}-$(default-target) mv target/release/topgrade.exe assets/topgrade.exe cd assets powershell Compress-Archive -Path * -Destination ${FILENAME}.zip @@ -145,12 +120,11 @@ jobs: if: ${{ matrix.platform == 'windows-latest' }} shell: bash - - - name: Release - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 - with: - tag_name: ${{ steps.determine_tag_name.outputs.tag_name }} - files: assets/* + - name: Upload assets + run: + gh release upload "${{ github.event.client_payload.tag }}" assets/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Generate artifact attestations uses: actions/attest-build-provenance@v3.0.0 @@ -250,20 +224,10 @@ jobs: - name: Build in Release profile with all features enabled run: cross build --release --all-features --target ${{matrix.target}} - - name: Determine tag name - id: determine_tag_name - shell: bash # Or it won't work on Windows - run: | - if [ -n "${{ github.event.release.tag_name }}" ]; then - echo "tag_name=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT - else - echo "tag_name=${{ github.event.inputs.existing_tag }}" >> $GITHUB_OUTPUT - fi - - name: Rename Release run: | mkdir -p assets - FILENAME=topgrade-${{steps.determine_tag_name.outputs.tag_name}}-${{matrix.target}} + FILENAME=topgrade-${{ github.event.client_payload.tag }}-${{matrix.target}} mv target/${{matrix.target}}/release/topgrade assets cd assets tar --format=ustar -czf $FILENAME.tar.gz topgrade @@ -289,13 +253,25 @@ jobs: shell: bash - - name: Release - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 - with: - tag_name: ${{ steps.determine_tag_name.outputs.tag_name }} - files: assets/* + - name: Upload assets + run: + gh release upload "${{ github.event.client_payload.tag }}" assets/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Generate artifact attestations uses: actions/attest-build-provenance@v3.0.0 with: subject-path: assets/* + + triggers: + runs-on: ubuntu-latest + needs: [ native_build, cross_build ] + steps: + - name: Trigger workflows + run: | + gh api repos/${{ github.repository }}/dispatches \ + -f "event_type=release-assets-built" \ + -F "client_payload[tag]=${{ github.event.client_payload.tag }}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml new file mode 100644 index 00000000..7050aecc --- /dev/null +++ b/.github/workflows/release-plz.yml @@ -0,0 +1,63 @@ +name: Release-plz + +on: + push: + branches: + - main + +jobs: + + # Release unpublished packages. + release-plz-release: + name: Release-plz release + runs-on: ubuntu-latest + environment: crates_io + permissions: + contents: write + id-token: write # For trusted publishing + steps: + - &checkout + name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + persist-credentials: false + - &install-rust + name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Run release-plz + id: release-plz + uses: release-plz/action@v0.5 + with: + command: release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Trigger workflows + if: steps.release-plz.outputs.releases_created == 'true' + run: | + gh api repos/${{ github.repository }}/dispatches \ + -f "event_type=release-created" \ + -F "client_payload[tag]=${{ fromJSON(steps.release-plz.outputs.releases)[0].tag }}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Create a PR with the new versions and changelog, preparing the next release. + release-plz-pr: + name: Release-plz PR + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + concurrency: + group: release-plz-${{ github.ref }} + cancel-in-progress: false + steps: + - *checkout + - *install-rust + - name: Run release-plz + uses: release-plz/action@v0.5 + with: + command: release-pr + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release_to_aur.yml b/.github/workflows/release_to_aur.yml index 02ae7135..6822d652 100644 --- a/.github/workflows/release_to_aur.yml +++ b/.github/workflows/release_to_aur.yml @@ -1,19 +1,8 @@ name: Publish to AUR on: - # Step "Publish binary AUR package" needs the binaries built by the following - # workflow, so we wait for it to complete. - workflow_run: - workflows: ["Publish release files for CD native and non-cd-native environments"] - types: - - completed - workflow_dispatch: - inputs: - # Example: 16.0.4 - version: - description: "The version of this manual release, e.g., 16.0.4" - required: false - type: string + repository_dispatch: + types: [ release-assets-built ] permissions: contents: read @@ -25,12 +14,9 @@ jobs: - name: Determine version id: determine_version run: | - if [ -n "${{ github.event.inputs.version }}" ]; then - echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT - else - # GITHUB_REF should be something like "v16.0.4", remove the prefix v here - echo "version=${GITHUB_REF#v}" >> $GITHUB_OUTPUT - fi + # tag should be something like "v16.0.4", remove the prefix v here + tag="${{ github.event.client_payload.tag }}" + echo "version=${tag#v}" >> $GITHUB_OUTPUT - name: Publish source AUR package uses: varabyte/update-aur-package@572e31b1972fa289a27b1926c06a489eb89c7fd7 diff --git a/.github/workflows/release_to_homebrew.yml b/.github/workflows/release_to_homebrew.yml index 760582f9..9c6d6775 100644 --- a/.github/workflows/release_to_homebrew.yml +++ b/.github/workflows/release_to_homebrew.yml @@ -1,14 +1,8 @@ name: Publish to Homebrew on: - # workflow_run: - # workflows: ["Check SemVer compliance"] - # types: - # - completed - workflow_dispatch: - push: - tags: - - "v*" + repository_dispatch: + types: [ release-created ] permissions: contents: read @@ -20,6 +14,7 @@ jobs: - name: Set up Homebrew id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@24a0b15df658487e137fcd20fba32757d41a9411 # master + - name: Cache Homebrew Bundler RubyGems id: cache uses: actions/cache@v4.3.0 @@ -31,6 +26,7 @@ jobs: - name: Install Homebrew Bundler RubyGems if: steps.cache.outputs.cache-hit != 'true' run: brew install-bundler-gems + - name: Bump formulae uses: Homebrew/actions/bump-packages@24a0b15df658487e137fcd20fba32757d41a9411 # master continue-on-error: true diff --git a/.github/workflows/release_to_pypi.yml b/.github/workflows/release_to_pypi.yml index 3ba96921..915c88b5 100644 --- a/.github/workflows/release_to_pypi.yml +++ b/.github/workflows/release_to_pypi.yml @@ -1,14 +1,14 @@ name: Update PyPi on: - release: - types: [published] - workflow_dispatch: + repository_dispatch: + types: [ release-created ] permissions: contents: read jobs: + # TODO: make linux/windows/macos/sdist a matrix. See how other workflows do it. linux: runs-on: ubuntu-latest strategy: @@ -21,7 +21,6 @@ jobs: with: target: ${{ matrix.target }} args: --release --out dist - sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} manylinux: auto - name: Upload wheels uses: actions/upload-artifact@v5.0.0 @@ -41,7 +40,6 @@ jobs: with: target: ${{ matrix.target }} args: --release --out dist - sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Upload wheels uses: actions/upload-artifact@v5.0.0 with: @@ -60,7 +58,6 @@ jobs: with: target: ${{ matrix.target }} args: --release --out dist - sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Upload wheels uses: actions/upload-artifact@v5.0.0 with: diff --git a/.github/workflows/release_to_winget.yml b/.github/workflows/release_to_winget.yml index 9425ded8..c34d3695 100644 --- a/.github/workflows/release_to_winget.yml +++ b/.github/workflows/release_to_winget.yml @@ -1,8 +1,8 @@ name: Publish to WinGet + on: - release: - types: [released] - workflow_dispatch: + repository_dispatch: + types: [ release-created ] permissions: contents: read diff --git a/RELEASE_PROCEDURE.md b/RELEASE_PROCEDURE.md index 7fa1177d..965c84d6 100644 --- a/RELEASE_PROCEDURE.md +++ b/RELEASE_PROCEDURE.md @@ -1,9 +1,4 @@ -> This document lists the steps that lead to a successful release of Topgrade. - -1. Open a PR that: - - > Here is an [Example PR](https://github.com/topgrade-rs/topgrade/pull/652) - > that you can refer to. +Non-major versions go via release-plz. 1. bumps the version number. @@ -24,41 +19,3 @@ [breaking_changes_dev]: https://github.com/topgrade-rs/topgrade/blob/main/BREAKINGCHANGES_dev.md [breaking_changes]: https://github.com/topgrade-rs/topgrade/blob/main/BREAKINGCHANGES.md - -2. Check and merge that PR. - -3. Go to the [release](https://github.com/topgrade-rs/topgrade/releases) page - and click the [Draft a new release button](https://github.com/topgrade-rs/topgrade/releases/new) - -4. Write the release notes - - We usually use GitHub's [Automatically generated release notes][auto_gen_release_notes] - functionality to generate release notes, but you write your own one instead. - - [auto_gen_release_notes]: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes - -5. Attaching binaries - - You don't need to do this as our CI will automatically do it for you, - binaries for Linux, macOS and Windows will be created and attached. - - And the CI will publish the new binary to: - - 1. AUR - 2. PyPi - 3. Homebrew (seems that this is not working correctly) - 4. Winget - -6. Manually release it to Crates.io - - > Yeah, this is unfortunate, our CI won't do this for us. We should probably add one. - - 1. `cd` to the Topgrade directory, make sure that it is the latest version - (i.e., including the PR that bumps the version number). - 2. Set up your token with `cargo login`. - 3. Dry-run the publish `cargo publish --dry-run`. - 4. If step 3 works, then do the final release `cargo publish`. - - > You can also take a look at the official tutorial [Publishing on crates.io][doc] - > - > [doc]: https://doc.rust-lang.org/cargo/reference/publishing.html