docs/RELEASE.md
Release
Two human steps. Everything else is automation.
| 1 | 1. git tag && git push → CI creates a GitHub draft |
| 2 | 2. Edit Notes, click Publish |
| 3 | stable → ployz.sh/stable + Homebrew |
| 4 | beta → ployz.sh/beta |
No next branch. Features and fixes both land on main. Beta is a tag.
Cut a release
- Set
[workspace.package] versioninCargo.tomlandployz-sdk/package.jsonto the version you will tag (0.2.0or0.2.0-beta.1).check-release-tag.shrejects a tag if either is missing or differs. - Merge that commit to
main. - Tag and push:
| 1 | git tag v0.2.0 |
| 2 | git push origin v0.2.0 |
Beta: v0.2.0-beta.1 with Cargo version 0.2.0-beta.1. Nightly, -rc, and other suffixes are rejected.
- Wait for the Release workflow. The tag run bounces the compile onto
mainso rust-cache can reuse the previous release, then builds the eight archives and theployz-relayimage and opens a draft GitHub release (--prereleaseon beta tags). - Fill
## Notes. Click Publish. That click is the review gate. Drafts are not public downloads.
Confidence before Publish
Fast CI on main is the merge gate. The ignored cluster suite is informing. A red nightly there does not block a tag or Publish.
Before Publish, run scripts/qualify-release.sh against real Linux Machines using the draft musl archives (PLOYZ_ARTIFACT_DIR). That script does not pick a cloud vendor. You pass SSH targets. Those hosts must be uninitialized Machines unless you set PLOYZ_QUALIFY_RESET=1, which accepts a reset and destroys managed containers. Pass a qualification key with PLOYZ_QUALIFY_SSH_KEY or -i in PLOYZ_QUALIFY_SSH_OPTS so ssh and ployz machine init/add use the same identity.
When the informing cluster suite and that run disagree, the real Machines are the authority. Testkit bugs do not block a release.
What Publish does
scripts/promote-release.sh runs on release: published.
- Writes a one-line file (
v0.2.0) on thechannelsbranch:stableorbeta. - Stable only: regenerates
Formula/ployz.rbfromchecksums.txtand pushesgetployz/homebrew-ployz.
Needs repo secret HOMEBREW_TAP_TOKEN (write access to the tap). Channel updates use GITHUB_TOKEN. Publish then dispatches ployz.sh, which deploys install.sh plus the channels branch files to Cloudflare Pages.
The same release: published event runs publish-sdk.yml, which bounces the compile onto main so rust-cache can reuse the previous SDK build, then publishes @ployz/sdk to npm (beta dist-tag on beta tags, latest on stable). @ployz/sdk itself is JavaScript only; each native binding ships as its own package (@ployz/sdk-linux-x64, @ployz/sdk-linux-arm64, @ployz/sdk-darwin-arm64, @ployz/sdk-darwin-x64, built by the workflow's matrix; the linux bindings are cross-linked by cargo-zigbuild against a glibc 2.28 floor, so they are not musl builds) and is listed as an optional dependency, so npm installs just the one matching the host. The optionalDependencies are generated by scripts/pack-sdk-package.sh from the bindings it is handed, so the matrix is the only place the platform list lives, and the bindings publish before @ployz/sdk. npm trusted publishing is configured for getployz/ployz2 workflow publish-sdk.yml (no NPM_TOKEN); each binding package needs the same trusted publisher entry. To publish a tag whose GitHub Release already exists, dispatch publish-sdk.yml from main with that tag (the job checks out the tag).
Install
| 1 | curl -fsSL https://ployz.sh | sh # stable |
| 2 | curl -fsSL https://ployz.sh | sh -s beta # latest published beta |
| 3 | curl -fsSL https://ployz.sh | sh -s 0.2.0 # pin |
| 4 | brew install getployz/ployz/ployz # stable |
latest and stable mean the same thing. nightly is rejected.
The installer reads https://ployz.sh/stable or /beta (one line, vX.Y.Z or vX.Y.Z-beta.N). Missing or invalid channel files fail the install. Pins skip the channel fetch.
Artifacts stay on GitHub Releases. ployz.sh is the pointer plus CLI installer.
Cloudflare
.github/workflows/ployz-sh.yml Direct-Uploads the staged site to the existing ployz-sh Pages project. Installer changes on main deploy immediately. Pointer updates deploy because Publish dispatches this workflow (channels has no workflow file, so a push there cannot). Production always uses --branch=main.
| URL | Body |
|---|---|
https://ployz.sh | install.sh from this repo |
https://ployz.sh/stable | channels branch file stable |
https://ployz.sh/beta | channels branch file beta |
Needs repo secrets CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN (same Pages project as before). Disable the rust repo's ployz-sh workflow so it cannot overwrite this deploy.
Apex and channel URLs must serve these bodies. The installer does not detect or tolerate the old v1 script.
Homebrew
Goreleaser does not upload the tap (skip_upload: true). Bottles 404 if the formula is pushed while the GitHub release is still a draft. The tap updates only after a stable Publish.
Machine daemon
scripts/install.sh on Linux. Same version tokens: latest / stable / beta / pin. Set PLOYZ_VERSION.
Cloud Relay
Linux musl archives ployz-relay_linux_amd64.tar.gz and ployz-relay_linux_arm64.tar.gz are GitHub Release assets. They are not in checksums.txt, Homebrew, or ployz.sh.
The same binary is published as ghcr.io/getployz/ployz-relay:<tag> when the tag workflow runs. TLS stays on the terminator in front. Required env: PLOYZ_RELAY_DIAL_CREDENTIAL. Listen: --listen / PLOYZ_RELAY_LISTEN (default 0.0.0.0:8080).