diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 00000000..581ee571 --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,99 @@ +name: Prepare release + +on: + workflow_dispatch: + inputs: + bump: + description: "Which component of the version to increment" + required: true + default: "patch" + type: choice + options: + - major + - minor + - patch + +env: + CARGO_TERM_COLOR: always + +jobs: + prepare-release: + name: Prepare Release + runs-on: pub-hk-ubuntu-22.04-small + steps: + - name: Get token for GH application (Linguist) + uses: heroku/use-app-token-action@main + id: generate-token + with: + app_id: ${{ vars.LINGUIST_GH_APP_ID }} + private_key: ${{ secrets.LINGUIST_GH_PRIVATE_KEY }} + + - name: Checkout + uses: actions/checkout@v4 + with: + # We always want the version bump/changelog and resultant PR to target main, not the branch of the workflow_dispatch. + ref: main + # Using the GH application token here will configure the local git config for this repo with credentials + # that can be used to make signed commits that are attributed to the GH application user + token: ${{ steps.generate-token.outputs.app_token }} + + - name: Update Rust toolchain + run: rustup update + + - name: Rust Cache + uses: Swatinem/rust-cache@v2.7.0 + + - name: Install cargo-edit + run: cargo install cargo-edit + + - name: Record old crate version + id: old-version + run: echo "version=$(yq '.workspace.package.version' Cargo.toml)" >> "${GITHUB_OUTPUT}" + + - name: Bump crate versions + # We use `--package libcnb` here to prevent the example and test buildpack crates from + # having their versions bumped too. Since the libcnb package's version is set via the + # root Cargo.toml's `workspace.package.version` field, all other publishable crates will + # still have their versions bumped, even though they are not explicitly listed here. + run: cargo set-version --package libcnb --bump '${{ inputs.bump }}' + + - name: Record new crate version + id: new-version + run: echo "version=$(yq '.workspace.package.version' Cargo.toml)" >> "${GITHUB_OUTPUT}" + + - name: Update changelog + run: | + OLD_VERSION='${{ steps.old-version.outputs.version }}' + NEW_VERSION='${{ steps.new-version.outputs.version }}' + DATE_TODAY="$(date --utc --iso-8601)" + UNRELEASED_URL="https://github.com/${{ github.repository }}/compare/v${NEW_VERSION}...HEAD" + NEW_VERSION_URL="https://github.com/${{ github.repository }}/compare/v${OLD_VERSION}...v${NEW_VERSION}" + + sed --in-place --regexp-extended \ + --expression "s~(^## \[Unreleased\])$~\1\n\n\n## [${NEW_VERSION}] - ${DATE_TODAY}~" \ + --expression "s~(^\[unreleased\]:) .*$~\1 ${UNRELEASED_URL}\n[${NEW_VERSION}]: ${NEW_VERSION_URL}~" \ + CHANGELOG.md + + - name: Upgrade in-range dependency versions + run: cargo upgrade + + - name: Create pull request + id: pr + uses: peter-evans/create-pull-request@v5.0.2 + with: + token: ${{ steps.generate-token.outputs.app_token }} + title: Prepare release v${{ steps.new-version.outputs.version }} + body: | + Changes: + https://github.com/${{ github.repository }}/compare/v${{ steps.old-version.outputs.version }}...main + commit-message: Prepare release v${{ steps.new-version.outputs.version }} + branch: prepare-release + delete-branch: true + committer: ${{ vars.LINGUIST_GH_APP_USERNAME }} <${{ vars.LINGUIST_GH_APP_EMAIL }}> + author: ${{ vars.LINGUIST_GH_APP_USERNAME }} <${{ vars.LINGUIST_GH_APP_EMAIL }}> + + - name: Configure pull request + if: steps.pr.outputs.pull-request-operation == 'created' + run: gh pr merge --auto --squash "${{ steps.pr.outputs.pull-request-number }}" + env: + GH_TOKEN: ${{ steps.generate-token.outputs.app_token }} diff --git a/RELEASING.md b/RELEASING.md index 70b0e7dd..64d0ad57 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -5,21 +5,11 @@ easier to gauge cross-crate compatibility. ## Prepare Release -1. Create a new branch for the upcoming release -2. Update [Cargo.toml](./Cargo.toml) in the root of the repository: - 1. In the `workspace.package` table, update `version` to the new version - 2. In the `workspace.dependencies` table, update the `version` of each of the repository-local dependencies to the new version -3. Update [CHANGELOG.md](./CHANGELOG.md) - 1. Move all content under `## [Unreleased]` to a new section that follows this pattern: `## [VERSION] - YYYY-MM-DD` - 2. If appropriate, add a high-level summary of changes at the beginning of the new section - 3. Update the version compare links at the bottom of the file to both add the new version, and update the "unreleased" link's "from" version. -4. Install the latest version of [cargo-edit](https://github.com/killercup/cargo-edit): `cargo install cargo-edit` -5. Bump in-range dependency versions using: `cargo upgrade` -6. Commit the changes, push them and open a PR targeting `main` +1. Trigger the [Prepare release](https://github.com/heroku/libcnb.rs/actions/workflows/prepare-release.yml) GitHub Actions workflow with a suitable `{patch,minor,major}` version bump. ## Release -1. After peer-review, merge the release preparation PR +1. Once the release preparation PR has been opened, review it (including ensuring the changelog is accurate) and then merge. 2. On your local machine, run `git switch main && git pull` to ensure you're on the `main` branch with the latest changes 3. Create a (lightweight) Git tag for the release and push it: (i.e. for version `1.1.38`: `git tag v1.1.38 && git push origin v1.1.38`) 4. Use `cargo` to release all crates, making sure to release dependencies of other crates first: