Skip to content

Latest commit

 

History

History
117 lines (98 loc) · 4.59 KB

DEVELOPING.md

File metadata and controls

117 lines (98 loc) · 4.59 KB

HACKING

cutting releases

goals

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.

branching

  1. The main branch represents the next major version of the library.
  2. Previous major versions should be tracked using v0.x, v1.x, v2.x, used for backporting changes as necessary.
  3. Libraries should generate a latest release using, e.g., marvinpinto/action-automatic-releases on changes to the main branch.

tag and release process

  1. 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.
  2. Create an empty git commit for the tag to point at: git commit -m 'v1.2.3-rc1' --allow-empty.
  3. Create a new tag against that commit: v1.2.3-rc1.
  4. Push the changes to the library: git push origin main v1.2.3-rc1.
    • You can separate these steps: git push origin main followed by git push origin v1.2.3-rc1, if you want to make absolutely sure the commit you're pushing builds correctly before tagging it.
  5. Wait for the tag build workflow to complete.
    • The build workflow should create a draft release (using softprops/action-gh-release with draft set to true) and upload built artifacts to the release.
  6. 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.
  7. 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 as extism-sys and the dotnet packages to nuget.
      • In python-sdk, this publishes extism to PyPI.
      • In js-sdk, this publishes @extism/extism (and extism) to NPM.

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.)

CLI flow

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

implementation

Libraries should:

  • Provide a ci workflow, triggered on PR and workflow_dispatch.
    • This workflow should exercise the tests, linting, and documentation generation of the library.
  • Provide a build workflow, triggered on v* tags and merges to main
    • This workflow should produce artifacts and attach them to a draft release (if operating on a tag) or a latest release (if operating on main.)
    • Artifacts include: source tarballs, checksums, shared objects, and documentation.
  • 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.

A rough list of libraries and downstreams

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;