Skip to content

Make release channels (stable + candidate) a first-class, user-consumable feature #151

Description

@ajdelaguila

Summary

The staged-promotion pipeline already builds and promotes candidate → stable
internally, but "release channels" are not yet a documented, user-consumable
feature. Ship channels as a first-class capability in 0.6.0: stable +
candidate fully operational for external consumers, documented, and
discoverable.

This was split out of the v0.5.0 announcement review: the bullet claiming "users
can publish and test candidates independently before promoting to stable" was
dropped from the 0.5.0 announcement because that user-facing story is not yet
true (see Gap analysis).

Current state (what already works as of v0.5.0)

  • RC images are published. .github/workflows/rc-publish.yml builds each
    candidate as ghcr.io/knaisoma/data-olympus:X.Y.Z-rc.N plus a moving :rc
    channel tag, and cuts a GitHub pre-release. Image-only: RCs are never
    pushed to PyPI and never move :latest. (Tag 0.5.0-rc.2 exists.)
  • Byte-identical promotion. .github/workflows/tag-release.yml re-tags the
    verified RC digest to vX.Y.Z + :latest (tag-release.yml:123), so what
    ships as stable is exactly the image that was verified as a candidate.
  • Channel moves without rebuild. .github/workflows/set-channel.yml
    re-points a moving channel tag (e.g. :kndev) at an existing digest; drives
    RC canary / promotion / rollback on kn-dev via Keel.
  • PyPI is stable-only. publish-pypi.yml uploads only on v* release tags;
    RCs never reach PyPI.
  • Smoke test exists. data-olympus verify runs liveness / readiness /
    search round-trip / enforcement against a live target and returns distinct
    exit codes for unreachable vs check-failed (added v0.4.2).

Gap analysis (why it is not user-facing yet)

  1. Undocumented for users. There is no "release channels" section anywhere.
    docs/operations.md §3.1 mentions "a mutable channel tag" generically but
    never names :rc, never explains stable vs candidate, and never shows the
    deploy-candidate → verify → promote flow.
  2. Default trial path has no candidates. docs/quickstart.md steers users
    to uvx data-olympus / uv tool install (PyPI), but PyPI carries no RCs.
    Only Docker/Kubernetes deployers can consume candidates today, and only if
    they already know the :rc tag exists.
  3. Framing reversal to make deliberately. The v0.4.2 notes call this
    pipeline "internal tooling [that] does not change how you run the server."
    Promoting it to a user-facing feature is a positioning change that the 0.6.0
    notes must state explicitly and supersede.
  4. No published channel contract. The channel tag names (:latest, :rc,
    X.Y.Z-rc.N, vX.Y.Z) are convention, not a documented, stable contract
    users can pin against.

Goal for 0.6.0

Stable and candidate channels are fully operational, documented, and
consumable by external users
, with a published contract for what each channel
means and how to subscribe, pin, verify, and promote.

Scope / work items

Docs

  • New "Release channels" section in docs/operations.md: define stable
    vs candidate; publish the channel tag contract (:latest = current
    stable, vX.Y.Z = immutable stable, :rc = current candidate,
    X.Y.Z-rc.N = immutable candidate); show the deploy-candidate →
    data-olympus verify → promote-to-stable flow with copy-pasteable
    Kubernetes snippets.
  • Cross-link from README.md and add a short "Trying release candidates"
    subsection to docs/quickstart.md.
  • Document rollback (pin the previous vX.Y.Z, or move a channel back
    to the prior digest à la set-channel).
  • Document the byte-identical promotion guarantee explicitly.

Contract / mechanics

  • Decide and document the candidate consumption path(s). Docker :rc
    channel already works; decide whether PyPI PEP 440 pre-releases
    (X.Y.Zrc N, installed via --prerelease) are also in scope. If yes,
    extend rc-publish.yml to publish the pre-release to PyPI and document the
    uvx/uv install story; if no, say so explicitly in the channel docs so
    the boundary is unambiguous.
  • Ratify the stable channel name in the contract: either document
    :latest as the stable channel or introduce an explicit :stable alias
    (preferred for a governance service, to avoid :latest ambiguity).
  • Make GitHub pre-releases the canonical candidate changelog surface and
    link them from the channel docs.

Verification / CI

  • Document verify as the supported gate a user runs against a deployed
    candidate before promoting, including the exit-code contract.
  • Optional: a documented one-liner (or nox/make target) that deploys :rc
    to a scratch namespace and runs verify against it.

Positioning

  • 0.6.0 release notes introduce channels as a user feature and
    explicitly supersede the v0.4.2 "internal tooling" framing.

Acceptance criteria

  • A new user can, from the docs alone, deploy a candidate, run verify, and
    promote to stable without reading any CI YAML.
  • The channel tag contract is written down and stable.
  • The candidate consumption path (Docker and/or PyPI) is unambiguous and matches
    what CI actually publishes.
  • 0.6.0 release notes position channels as user-facing and retract the
    "internal only" statement.

Out of scope (candidate follow-ups)

  • Additional channels beyond stable/candidate (nightly / edge).
  • Automated canary analysis or progressive rollout.

Context: split out of the v0.5.0 release announcement review. The "publish and
test candidates independently" bullet was dropped from the 0.5.0 announcement;
this issue tracks making the capability real for 0.6.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or requestroadmapRoadmap item

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions