Caution
Cutting a release, end-to-end, takes a reasonable amount of time -- mostly waiting on the CI -- and also requires the availability of colleagues to properly review and approve.
Plan for it to take an entire working day.
Do not rush the process and avoid days on which you and colleagues have limited availability. Don't release on the last working day before a weekend or holiday, etc. If something goes awry before the point of no return, keep calm and don't carry on: Better to revert and try again the next day than having a broken release (and a stressful evening)!
-
If necessary, cherry-pick the commits that should be included in the release. (This should only be done in exceptional circumstances.)
-
Update the
CHANGELOG
, if necessary. This is used in the release announcement, so ensure it conforms to the correct format (as described in theCHANGELOG
introduction).-
By convention, this should be up-to-date as part of the PR process, but it ought to be double-checked. (See below for suggestions on how to partially automate this.)
-
Retitle the "Unreleased" section to this release and create a fresh "Unreleased" section (see comments in the
CHANGELOG
for details).Don't forget to update the "Full list of changes" links appropriately.
-
Tip
Do not wrap bullet points over multiple lines in the CHANGELOG
.
GitHub will preserve those line breaks in the Release Notes, which is
probably not what you want.
Important
Point releases (i.e., not patch releases) should also be given a name, taking the form "[ADJECTIVE] [TREE]", incrementing alphabetically from the previous release (e.g., "Archetypal Aspen", "Benevolent Beech", etc.). Both parts are relatively loose, particularly when it comes to botanical correctness, and a degree of assonance has become traditional.
The name should be decided amongst the team before release.
-
Update the root level
Cargo.toml
.- Bump
workspace.package.version
. - Bump any workspace dependency versions, respectively.
- Bump
-
Update lockfiles and the release workflow.
-
Run
nix flake update
to updateflake.lock
. -
Run
cargo update
to updateCargo.lock
. -
The release workflow is generated by
dist
(formerlycargo-dist
); the version that is currently in use can be found indist-workspace.toml
. If a newer version exists, then:- Download the new version of
dist
. - Run
dist init
. This should update thedist-workspace.toml
configuration and the release workflow (.github/workflows/release.yml
)
- Download the new version of
-
-
Push these changes and wait for green CI across all workflows and peer approval. Upon both, squash-and-merge the PR into
main
.
-
Tag the merged commit in
main
with the release version, prefixed with av
(e.g.,v0.1.0
), and push it to GitHub. The version number must match the one inCargo.toml
, otherwisedist
will fail during CI.git tag v0.1.0 git push --tags
Caution
Pushing the tag will trigger the release workflow (described below). If that succeeds, the release is finalised. This is the point of no return. Only push the tag if you are sure everything is ready for the release.
-
Let the
dist
release workflow create a new release. That is:-
Build binary artefacts for a variety of targets (currently: Apple Silicon macOS, Intel macOS, x64 Windows, ARM64 Linux and x64 Linux). This can take some time; the best part of an hour.
-
Publish a release announcement, featuring the relevant section from the
CHANGELOG
for this version.
-
Warning
If this step fails, delete the new release tag as quickly as possible from GitHub and start over:
git push --delete origin vX.Y.Z
-
Update
crates.io
. As of writing, the workspace cannot be published automatically, so each package in the workspace needs to be individually published in topological order. That is, currently, something like:cargo publish --package topiary-web-tree-sitter-sys cargo publish --package topiary-tree-sitter-facade cargo publish --package topiary-core cargo publish --package topiary-queries cargo publish --package topiary-config cargo publish --package topiary-cli
Important
Publication to crates.io
requires appropriate access. You may need
to escalate this appropriately.
Tip
cargo tree --invert
is useful to determine the topology.
Warning
Point releases, only. Don't publicise patch releases, unless there's a pressing need to do so (e.g., fix of a security vulnerability, etc.).
-
Announce the new version on Tweag's Twitter, Discord and other official social network accounts, via someone with access.
-
Share amongst other social networks (e.g., Reddit, Hacker News, Mastodon, etc.), under personal accounts, at your discretion.
If the unreleased changes in the CHANGELOG
have become stale, the
list of merged PRs can be fetched from:
https://github.com/tweag/topiary/pulls?q=is:pr+base:main+merged:>YYYY-MM-DD
Replacing YYYY-MM-DD
by the date of the last release.
If you have the GitHub CLI client, something like the following may be more convenient:
gh pr list \
--limit 500 \
--base main \
--state merged \
--json number,mergedAt,title,body \
| jq \
--raw-output \
--argjson release "$(gh release view --json createdAt)" \
'
reverse
| .[]
| select(.mergedAt > $release.createdAt)
| ["# PR#\(.number): \(.title)", "*Merged: \(.mergedAt)*", "\(.body)\n"]
| join("\n\n")
'
Tip
The --limit 500
is an arbitrary "large number" ™️ limit of PRs to
fetch, overriding the low default. As of writing, there's no way to
set this to "unlimited"; adjust as necessary.