Releases are automated via GitHub Actions. Push a version tag to trigger the full pipeline: build, checksum, publish to GitHub Releases, and upload to Cloudflare R2. The resulting artifacts power self-update and the install script.
Release process
1. Tag the release
git tag v0.2.1
git push origin v0.2.1
The v* tag pattern triggers the release workflow.
2. Build (automated)
The workflow builds for four targets in parallel:
| Target | OS | Architecture | Runner |
|---|---|---|---|
x86_64-unknown-linux-gnu | Linux | x86_64 | ubuntu-latest |
aarch64-unknown-linux-gnu | Linux | ARM64 | ubuntu-latest (cross) |
x86_64-apple-darwin | macOS | x86_64 | macos-latest |
aarch64-apple-darwin | macOS | ARM64 | macos-latest |
Linux ARM64 uses cross for cross-compilation.
3. Package
Each build produces:
nyzhi-<platform>-<arch>.tar.gz— compressed tarball containing thenyzbinarynyzhi-<platform>-<arch>.sha256— SHA256 checksum file
4. Publish
The publish job:
- Downloads all build artifacts
- Validates all checksums (must be 64-character hex strings)
- Creates a GitHub Release with auto-generated release notes
- Uploads tarballs and checksums to the release
5. Upload to R2
Tarballs are uploaded to Cloudflare R2 for the install script:
nyzhi-releases/releases/v<version>/nyzhi-<platform>-<arch>.tar.gz
6. Update latest.json
A latest.json manifest is uploaded to R2:
{
"version": "0.2.1",
"date": "2025-02-22T12:00:00Z",
"sha256": {
"darwin-aarch64": "<hash>",
"darwin-x86_64": "<hash>",
"linux-x86_64": "<hash>",
"linux-aarch64": "<hash>"
}
}
This is what nyz update and the install script check to determine the latest version and verify downloads. See self-update for how updates work.
7. Upload install script
The install script (infra/releases-worker/install.sh) is uploaded to R2 so that curl -fsSL https://get.nyzhi.com | sh always gets the latest version.
Required secrets
Configure these in your GitHub repository settings:
| Secret | Purpose |
|---|---|
CLOUDFLARE_API_TOKEN | Cloudflare API token with R2 write access |
CLOUDFLARE_ACCOUNT_ID | Your Cloudflare account ID |
Workflow file
The release workflow is at .github/workflows/release.yml. Key characteristics:
- Pinned actions — All GitHub Actions are pinned to specific commit SHAs for supply-chain security
- Checksum validation — Checksums are validated after download and before upload to R2
- Stable toolchain — Uses
dtolnay/rust-toolchainwith the stable channel
Version bumping
The version is defined in the workspace Cargo.toml:
[workspace.package]
version = "0.2.1"
To release a new version:
- Update the version in
Cargo.toml - Run
cargo checkto updateCargo.lock - Commit:
git commit -am "release: v0.2.2" - Tag:
git tag v0.2.2 - Push:
git push origin main v0.2.2
Install script
The install script at infra/releases-worker/install.sh handles:
- Platform detection (Linux/macOS, x86_64/ARM64)
- Version checking (skips if already up to date)
- Download with progress bar
- SHA256 verification
- Backup of existing binary
- Atomic installation
- Post-install verification (runs
nyz --version, rolls back on failure) - PATH setup (zsh, bash, fish)
- Uninstall support (
--uninstallflag)
The script is wrapped in a main() function so that partial downloads (truncated curl) cannot execute incomplete code.
R2 bucket structure
nyzhi-releases/
install.sh # install script
releases/
latest.json # version manifest
v0.2.1/
nyzhi-darwin-aarch64.tar.gz
nyzhi-darwin-x86_64.tar.gz
nyzhi-linux-x86_64.tar.gz
nyzhi-linux-aarch64.tar.gz
v0.2.0/
...