Skip to content

Commit

Permalink
Add a GitHub Actions workflow for preparing a libcnb.rs release
Browse files Browse the repository at this point in the history
Libcnb.rs uses a two stage release process. Until now both of those
stages required a maintainer to perform the steps manually:
https://github.com/heroku/libcnb.rs/blob/main/RELEASING.md

This new GitHub Actions workflow replaces the manual steps in the first
half of the release process, leading up to the creation of the
"Prepare release" PR.

In the future, the second stage of the release process will be automated
too, but that will require sorting out a service account (which will also
have to be backed by a GitHub account, since currently crates.io only
supports login via GitHub oauth).

See also:
https://github.com/killercup/cargo-edit#cargo-set-version
https://github.com/heroku/languages-github-actions/blob/main/.github/workflows/_buildpacks-release.yml

First part of #595.
GUS-W-13977983.
  • Loading branch information
edmorley committed Sep 24, 2023
1 parent 768a1e9 commit 1483679
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 12 deletions.
99 changes: 99 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -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/[email protected]

- 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/[email protected]
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 }}
14 changes: 2 additions & 12 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 1483679

Please sign in to comment.