Cutting a release should be a boring, rote process with as little excitement as possible. Following the processes in this document, we should be able to cut a release at any time without worrying about producing bad artifacts. Our process should let us resolve build issues without affecting library users.
- The
main
branch represents the next major version of the library. - Previous major versions should be tracked using
v0.x
,v1.x
,v2.x
, used for backporting changes as necessary. - Libraries should generate a
latest
release using, e.g.,marvinpinto/action-automatic-releases
on changes to themain
branch.
- Pick a target semver value. Prepend the semver value with
v
:v1.2.3
. Increment the minor version for additive changes and patch for bugfixes.- For trickier changes, consider using release candidates:
rc0
,rc1
, etc.
- For trickier changes, consider using release candidates:
- Create an empty git commit for the tag to point at:
git commit -m 'v1.2.3-rc1' --allow-empty
. - Create a new tag against that commit:
v1.2.3-rc1
. - Push the changes to the library:
git push origin main v1.2.3-rc1
.- You can separate these steps:
git push origin main
followed bygit push origin v1.2.3-rc1
, if you want to make absolutely sure the commit you're pushing builds correctly before tagging it.
- You can separate these steps:
- Wait for the tag
build
workflow to complete.- The
build
workflow should create a draft release (usingsoftprops/action-gh-release
withdraft
set totrue
) and upload built artifacts to the release.
- The
- Once the workflow is complete, do whatever testing is necessary using the artifacts.
- TODO: We can add automation to this step so that we test on downstream deps automatically: e.g., if we
build a new kernel, we should be able to trigger tests in the
python-sdk
using that new kernel.
- TODO: We can add automation to this step so that we test on downstream deps automatically: e.g., if we
build a new kernel, we should be able to trigger tests in the
- Once we're confident the release is good, go to the releases page for the library and edit the draft release.
- If the release is a release candidate (
rc0..N
), make sure to mark the release as a "prerelease". - Publish the draft release.
- This kicks off the publication workflow: taking the artifacts built during the
build
workflow and publishing them to any necessary registry or repository.- In extism, this publishes
extism-maturin
to PyPI asextism-sys
and the dotnet packages to nuget. - In
python-sdk
, this publishesextism
to PyPI. - In
js-sdk
, this publishes@extism/extism
(andextism
) to NPM.
- In extism, this publishes
- If the release is a release candidate (
Note If you're at all worried about a release, use a private fork of the target library repo to test the release first (e.g.,
extism/dev-extism
.)
For official releases:
$ git commit -m 'v9.9.9' --allow-empty
$ git tag v9.9.9
$ git push origin main v9.9.9
$ gh run watch
$ gh release edit v9.9.9 --tag v9.9.9 --title 'v9.9.9' --draft=false
$ gh run watch
For prereleases:
$ git commit -m 'v9.9.9' --allow-empty
$ git tag v9.9.9
$ git push origin main v9.9.9
$ gh run watch
$ gh release edit v9.9.9 --tag v9.9.9 --title 'v9.9.9' --draft=false --prerelease
$ gh run watch
Libraries should:
- Provide a
ci
workflow, triggered on PR andworkflow_dispatch
.- This workflow should exercise the tests, linting, and documentation generation of the library.
- Provide a
build
workflow, triggered onv*
tags and merges tomain
- This workflow should produce artifacts and attach them to a draft release (if operating on a tag) or a
latest
release (if operating onmain
.) - Artifacts include: source tarballs, checksums, shared objects, and documentation.
- This workflow should produce artifacts and attach them to a draft release (if operating on a tag) or a
- Provide a
release
workflow, triggered on github releases:- This workflow should expect artifacts from the draft release to be available.
- Artifacts from the release should be published to their final destination as part of this workflow: tarballs to NPM, documentation to Cloudflare R2/Amazon S3/$yourFavoriteBucket.
flowchart TD;
A["runtime"] --> B["libextism"];
B --> C["extism-maturin"];
B --> X["nuget-extism"];
C --> D["python-sdk"];
B --> E["ruby-sdk"];
A --> F["go-sdk"];
G["plugins"] --> B;
G --> D;
G --> E;
G --> F;
G --> H["js-sdk"];
F --> I["cli"];
G --> J["dotnet-sdk"];
X --> J;
G --> K["cpp-sdk"];
G --> L["zig-sdk"];
B --> L;
G --> M["haskell-sdk"];
B --> M;
G --> N["php-sdk"];
B --> N;
G --> O["elixir-sdk"];
B --> O;
G --> P["d-sdk"];
B --> P;
G --> Q["ocaml-sdk"];
B --> Q;