Skip to content

Latest commit

 

History

History
119 lines (91 loc) · 4.17 KB

File metadata and controls

119 lines (91 loc) · 4.17 KB

Release pipeline

Releases are fully automated and nobody dispatches a workflow by hand. One Publish: true trailer on a version-bumping commit runs the whole chain: version, tag, linux binaries, darwin and windows binaries, then every downstream package format.

The chain

Three workflows, each triggered by the previous one completing. There is no shared orchestrator -- workflow_run is the join.

flowchart LR
    dev(["hyperi-ci push --publish"]) --> ci

    subgraph gh["GitHub Actions"]
        ci["CI<br/>ci.yml"]
        cross["Cross-build<br/>cross-build.yml"]
        pkg["Package<br/>package.yml"]
    end

    r2[(R2: downloads.hyperi.io)]
    taps[(homebrew-tap<br/>scoop-bucket)]

    ci -->|workflow_run| cross
    cross -->|workflow_run| pkg
    ci -->|linux binaries| r2
    cross -->|darwin + windows binaries| r2
    pkg -->|tarballs, deb, rpm, installers| r2
    pkg -->|formula, manifest| taps

    classDef actor fill:#56B4E9,stroke:#0072B2,color:#000
    classDef store fill:#F0E442,stroke:#E69F00,color:#000
    class dev actor
    class r2,taps store
Loading

What each stage does

CI (.github/workflows/ci.yml) delegates entirely to hyperi-io/hyperi-ci/.github/workflows/rust-ci.yml. It runs quality, test and build, and -- only when HEAD carries the Publish: true trailer -- derives the next version with semantic-release, tags it, and uploads the linux binaries to R2.

Cross-build (.github/workflows/cross-build.yml) builds the darwin and windows targets that fall outside hyperi-ci's linux matrix, and writes them to the same R2 path layout. Windows is EXPERIMENTAL and not in the formal test path.

Package (.github/workflows/package.yml) turns raw binaries into distributable artefacts: linux tarballs with checksums, .deb and .rpm via nfpm, the rendered Homebrew formula and Scoop manifest pushed into the sibling tap and bucket repos, and the static install scripts.

Why the chain uses workflow_run, not tag pushes

The obvious wiring -- trigger Cross-build on push: tags: v* -- does not fire. semantic-release commits the version bump with a [skip ci] suffix, and GitHub suppresses the tag-push event for those commits. Cross-build therefore listens for CI COMPLETION instead, and derives the tag itself by reading the most recent v* tag.

The tag-push trigger is still declared as a fallback for tags created outside semantic-release (manual tagging, a foreign release tool). Both paths land in the same resolve-tag job.

Because Package runs off Cross-build's completion rather than a shared artefact handoff, its linux tarball jobs POLL R2 for the raw binary before proceeding. That tolerates hyperi-ci's publish step being slower than the cross-build.

Versioning

semantic-release owns the version. .releaserc.yaml maps conventional-commit types to bumps: feat minor, fix/perf/security patch, everything else no release. scripts/release-prepare.py syncs the version into VERSION, Cargo.toml and Cargo.lock during the prepare step, and those files plus CHANGELOG.md are committed back.

Never hand-edit CHANGELOG.md or bump a version manually -- both are generated.

Packaging templates

The install scripts and package manifests are rendered from templates rather than hand-maintained per release. packaging/render.sh produces the static installers once; packaging/render-release.sh <version> re-renders the per-version manifests with the release's SHA-256 values baked in.

The framework is reusable across Rust CLI projects and is documented on its own: packaging/README.md.

Verifying a release landed

$ curl -fsI https://downloads.hyperi.io/macbash/latest/macbash-linux-amd64 | head -1
HTTP/2 200

Then check the installer path end to end:

$ curl -fsSL https://downloads.hyperi.io/macbash/install.sh | sh -s -- --user
$ macbash --version