Automated Release Process #31
This file contains 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
# The purpose of this workflow is to orchestrate Wasmtime's release process as | |
# much as possible. This specific workflow is responsible for a few timed parts | |
# of the process: | |
# | |
# * On the 5th of every month a new release branch is automatically created and | |
# the version number of the `main` branch is increased | |
# * On the 20th of every month the previous release branch is published. | |
# | |
# This automation is all done through PRs except for the creation of the release | |
# branch itself which is an write-action performed by this script. Otherwise | |
# humans are ideally reviewing and rubber-stamping the output of the script all | |
# other steps of the way. | |
# | |
# Note that this script also helps manage patch releases by sending a PR to the | |
# release branch with a bumped version number for all crates with a patch-bump. | |
name: "Automated Release Process" | |
on: | |
schedule: | |
# “At 00:00 on day-of-month 5.” | |
# | |
# https://crontab.guru/#0_0_5_*_* | |
- cron: '0 0 5 * *' | |
- cron: '0 0 20 * *' | |
# Allow manually triggering this request via the button at | |
# https://github.com/bytecodealliance/wasmtime/actions/workflows/release-process.yml | |
workflow_dispatch: | |
inputs: | |
action: | |
description: 'Publish script argument: "cut", "release-latest", or "release-patch"' | |
required: false | |
default: 'cut' | |
jobs: | |
release_process: | |
if: "github.repository == 'bytecodealliance/wasmtime' || !github.event.schedule" | |
name: Run the release process | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
submodules: true | |
- name: Setup | |
run: | | |
rustc scripts/publish.rs | |
git config user.name 'Wasmtime Publish' | |
git config user.email '[email protected]' | |
git remote set-url origin https://git:${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/${{ github.repository }} | |
- uses: ./.github/actions/install-rust | |
- uses: ./.github/actions/install-cargo-vet | |
- name: Bump major version number | |
run: | | |
set -ex | |
# Push the current contents of `main` to a new release branch | |
cur=$(./ci/print-current-version.sh) | |
git push origin HEAD:release-$cur | |
# Update version numbers and make a commit indicating that. Note that | |
# on merge this will not trigger a publish. | |
./publish bump | |
num=$(./ci/print-current-version.sh) | |
# Remove all release notes for the currnet version now that the | |
# release branch has been created. Additionally add an entry in the | |
# list of all versions pointing to the release notes on the newly | |
# created branch. | |
sed -i '0,/-----------/d' RELEASES.md | |
sed -i "/ARCHIVE_START/a * [$cur](https://github.com/${{ github.repository }}/blob/release-$cur/RELEASES.md)" RELEASES.md | |
# Use `RELEASES-template.md` as the new release notes and then append | |
# the archive of all historical releases to the end of it. | |
cp RELEASES.md backup-releases | |
sed "s/VERSION/$num/" ci/RELEASES-template.md > RELEASES.md | |
cat backup-releases >> RELEASES.md | |
rm backup-releases | |
# Update `cargo vet` entries for all the new crate versions | |
cargo vet | |
# Commit all of the above changes. | |
git commit -am "Bump Wasmtime to $num" | |
# Push the result to a branch and setup metadata for the step below | |
# that creates a PR | |
git push origin HEAD:ci/bump-to-$num | |
echo "PR_HEAD=ci/bump-to-$num" >> $GITHUB_ENV | |
echo "PR_TITLE=Bump Wasmtime to $num" >> $GITHUB_ENV | |
echo "PR_BASE=main" >> $GITHUB_ENV | |
cat > pr-body <<-EOF | |
This is an [automated pull request][process] from CI which indicates that the next [\`release-$cur\` branch][branch] has been created and the \`main\` branch is getting its version number bumped from $cur to $num. | |
Maintainers should take a moment to review the [release notes][RELEASES.md] for $cur and any updates should be made directly to the [release branch][branch]. | |
Another automated PR will be made in roughly 2 weeks time when for the actual release itself. | |
If any issues arise on the \`main\` branch before the release is made then the issue should first be fixed on \`main\` and then backport to the \`release-$cur\` branch. | |
[RELEASES.md]: https://github.com/${{ github.repository }}/blob/release-$cur/RELEASES.md | |
[branch]: https://github.com/${{ github.repository }}/tree/release-$cur | |
[process]: https://docs.wasmtime.dev/contributing-release-process.html | |
EOF | |
if: >- | |
github.event.schedule == '0 0 5 * *' || | |
github.event.inputs.action == 'cut' | |
- name: Perform latest release | |
run: | | |
set -ex | |
git fetch origin | |
# Determine the latest release branch | |
rustc ci/find-latest-release.rs -o /tmp/find-latest-release | |
cur=`/tmp/find-latest-release` | |
# Move to the most recent release branch, update the release date and | |
# commit it, indicating that the commit is what will get tagged and | |
# released | |
git reset --hard origin/release-$cur | |
git submodule update --init --recursive | |
sed -i "s/^Unreleased/Released $(date +'%Y-%m-%d')/" RELEASES.md | |
git commit --allow-empty -a -F-<<EOF | |
Release Wasmtime $cur | |
[automatically-tag-and-release-this-commit] | |
EOF | |
# Push the result to a branch and setup metadata for the step below | |
# that creates a PR | |
git push origin HEAD:ci/release-$cur | |
echo "PR_HEAD=ci/release-$cur" >> $GITHUB_ENV | |
echo "PR_TITLE=Release Wasmtime $cur" >> $GITHUB_ENV | |
echo "PR_BASE=release-$cur" >> $GITHUB_ENV | |
cat > pr-body <<-EOF | |
This is an [automated pull request][process] from CI which is intended to notify maintainers that it's time to release Wasmtime $cur. The [release branch][branch] was created roughly two weeks ago and it's now time for it to be published and released. | |
It's recommended that maintainers double-check that [RELEASES.md] is up-to-date and that there are no known issues before merging this PR. When this PR is merged a release tag will automatically created, crates will be published, and CI artifacts will be produced. | |
[RELEASES.md]: https://github.com/${{ github.repository }}/blob/release-$cur/RELEASES.md | |
[process]: https://docs.wasmtime.dev/contributing-release-process.html | |
[branch]: https://github.com/${{ github.repository }}/tree/release-$cur | |
EOF | |
if: >- | |
github.event.schedule == '0 0 20 * *' || | |
github.event.inputs.action == 'release-latest' | |
- name: Bump and release patch version number | |
run: | | |
set -ex | |
# Update version numbers on a patch basis and update RELEASES.md if a | |
# patch release marker is already in there. Note that this commit | |
# message indicates that on-merge a release will be made. | |
./publish bump-patch | |
# Update `cargo vet` entries for all the new crate versions | |
cargo vet | |
sed -i "s/^Unreleased/Released $(date +'%Y-%m-%d')/" RELEASES.md | |
num=$(./ci/print-current-version.sh) | |
git commit -a -F-<<EOF | |
Release Wasmtime $num | |
[automatically-tag-and-release-this-commit] | |
EOF | |
# Push the result to a branch and setup metadata for the step below | |
# that creates a PR | |
git push origin HEAD:ci/bump-to-$num | |
echo "PR_HEAD=ci/bump-to-$num" >> $GITHUB_ENV | |
echo "PR_TITLE=Release Wasmtime $num" >> $GITHUB_ENV | |
echo "PR_BASE=${{ github.ref_name }}" >> $GITHUB_ENV | |
cat > pr-body <<-EOF | |
This is an [automated pull request][process] from CI to create a patch release for Wasmtime $num, requested by @${{ github.actor }}. | |
It's recommended that maintainers double-check that [RELEASES.md] is up-to-date and that there are no known issues before merging this PR. When this PR is merged a release tag will automatically be created, crates will be published, and CI artifacts will be produced. | |
[RELEASES.md]: https://github.com/${{ github.repository }}/blob/release-$num/RELEASES.md | |
[process]: https://docs.wasmtime.dev/contributing-release-process.html | |
EOF | |
if: github.event.inputs.action == 'release-patch' | |
- name: Make a PR | |
# Note that the syntax here is kinda funky, and the general gist is that | |
# I couldn't figure out a good way to have a multiline string-literal | |
# become a json-encoded string literal to send to GitHub. This | |
# represents my best attempt. | |
run: | | |
set -ex | |
body=$(jq -sR < ./pr-body) | |
curl --include --request POST \ | |
https://api.github.com/repos/${{ github.repository }}/pulls \ | |
--header "Authorization: token ${{ secrets.PERSONAL_ACCESS_TOKEN }}" \ | |
--data @- << EOF | |
{ | |
"head": "$PR_HEAD", | |
"base": "$PR_BASE", | |
"title": "$PR_TITLE", | |
"body": $body, | |
"maintainer_can_modify": true | |
} | |
EOF |