Skip to content

ci: collapse release and chart workflows into one atomic orchestrator - #823

Open
Yetkin Timocin (ytimocin) wants to merge 1 commit into
feat/multi-arch-imagesfrom
ci/release-orchestrator
Open

ci: collapse release and chart workflows into one atomic orchestrator#823
Yetkin Timocin (ytimocin) wants to merge 1 commit into
feat/multi-arch-imagesfrom
ci/release-orchestrator

Conversation

@ytimocin

Copy link
Copy Markdown
Collaborator

Stacked on #745 — based on feat/multi-arch-images so the diff shows only this change. Retarget to main once #745 merges.

release.yml and chart.yml ran independently with no ordering between them. A chart publish could fail, or never run, while the GitHub Release was already public — advertising charts nobody could pull — and images could be published after the charts referencing them.

One workflow now owns the release. The GitHub Release is created as a draft before any artifact exists, every producer uploads into that draft, and publish-release flips it visible only once every producer that was supposed to run has succeeded. Chart jobs wait on the images they reference. RC gating moves from a workflow-level tag filter to a single prerelease output, so it is derived once instead of respelled per job.

setup                       validate the tag; derive registry, version, prerelease
 └── create-draft-release    create (or reuse) the GitHub Release as a draft
      ├── publish-images     multi-arch push, then verify both platforms
      │    ├── publish-charts-oci     stable only
      │    └── publish-charts-pages   stable only
      └── publish-crds       package the CRDs, upload to the draft
publish-release              needs ALL of the above; verifies assets, then publishes

The publish-release condition is the only subtle part:

Case Result
Stable, all producers green publish
RC, chart jobs skipped by design publish
Stable, chart jobs skipped for any reason do not publish
Run cancelled at any point do not publish

It overrides the implicit success() on needs because the chart jobs are legitimately skipped for RCs, and uses !cancelled() rather than always() so Cancel after the producers finish does not still publish.

Reviewing this: release.yml is effectively a new file — read it whole rather than as a diff. The two jobs with real branching logic live in hack/release/ so they get shellcheck coverage and are testable; hack/release/test-release-scripts.sh exercises them against a stubbed gh (no test framework, no new dependencies) and workflow-lint.yml runs it. The assertion descriptions read as sentences — skim those and skip the plumbing.

Known trade-off. publish-charts-pages still uses stefanprodan/helm-gh-pages, a third-party Docker action holding contents: write whose base image is a floating tag resolved inside its own Dockerfile, so the SHA pin does not pin what executes. This PR increases its criticality: a chart failure previously left the release published anyway, now it blocks the release. I think that is the right direction — failing closed with the release still a draft beats publishing a release with missing charts — and harden-runner in audit mode records its egress meanwhile. Happy to replace it here instead of deferring if maintainers prefer.

Not yet executed end to end. Validation so far is actionlint, shellcheck, the script suite, and a dry run of the tag/asset logic against real GitHub draft releases. A full dry run in a scratch repo is planned before merge.

Part of #693.

release.yml and chart.yml ran independently with no ordering between them.
A chart publish could fail, or simply never run, while the GitHub Release
was already public - leaving a release that advertised charts nobody could
pull - and images could be published after the charts referencing them.

One workflow now owns the release. The GitHub Release is created as a draft
before any artifact exists, every producer uploads into that draft, and a
final publish-release job flips it visible only once each producer that was
supposed to run has succeeded. Chart jobs wait on the images they reference.
RC gating moves from a workflow-level tag filter to a single `prerelease`
output on setup-release.yml, so "is this a release candidate?" is derived
once instead of re-spelled in every consuming job.

The two jobs with real branching logic live in hack/release/ rather than
inline in YAML: they get real shellcheck coverage, they are reviewable as
code, and hack/release/test-release-scripts.sh exercises them against a
stubbed gh CLI. workflow-lint.yml runs both the shellcheck and the tests.

Fixes found while reviewing this change:

- The gh-pages chart index was published with the in-tree Chart.yaml values,
  which are pinned at 0.1.0/v0.1.0. Every release republished "hub-agent
  0.1.0" pointing at image tag v0.1.0, overwriting the previous entry - the
  live index still shows it. chart_version/app_version are now passed, and a
  follow-up step asserts against the branch the action wrote, since unknown
  action inputs are only a warning.
- setup-release.yml interpolated ${{ inputs.tag }} directly into its script,
  so a crafted workflow_dispatch input expanded in the shell before the tag
  regex could reject it. The tag now arrives via step env.
- `gh release create` without --verify-tag invents a missing tag at the head
  of the default branch, so one mistyped dispatch input could cut a complete
  public release from unreviewed main.
- A draft created by hand defaults to prerelease=false, so an RC reusing one
  would publish as the repository's "Latest release". The flag is now
  reconciled at publish time rather than assumed from creation.
- The release asset check matched names only; it now requires state
  "uploaded" and non-zero size, and verifies the bundle against its own
  sha256 before publishing.

Also: per-job least-privilege permissions, the CRD job's token scoped to the
upload step, Helm pinned to the version code-lint.yml already lints with,
and the chart jobs now check out the release tag rather than whatever ref a
dispatch defaulted to.

Part of #693.

Signed-off-by: Yetkin Timocin <ytimocin@microsoft.com>
@ytimocin
Yetkin Timocin (ytimocin) requested a review from a team as a code owner August 13, 2026 21:52
@ytimocin Yetkin Timocin (ytimocin) added process-improvement Any work related to improving project process - code changes, CI / CD or docs improvements. area/ci Issues related to ci labels Aug 13, 2026
@serbrech

Copy link
Copy Markdown
Contributor

lgtm

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Consolidates image, chart, CRD, and GitHub Release publishing into one ordered, fail-closed release workflow.

Changes:

  • Creates and verifies a draft release before publishing it.
  • Gates chart publication on verified images and skips charts for RCs.
  • Adds release recovery documentation and automated script checks.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
.github/workflows/release.yml Implements the unified release orchestrator.
.github/workflows/chart.yml Removes the standalone chart workflow.
.github/workflows/setup-release.yml Exports validated prerelease metadata.
.github/workflows/workflow-lint.yml Checks and tests release scripts.
hack/release/create-draft-release.sh Safely creates or reuses draft releases.
hack/release/publish-release.sh Verifies assets before publication.
hack/release/test-release-scripts.sh Tests release-script failure paths.
hack/release/testdata/gh Provides the test GitHub CLI stub.
RELEASING.md Adds release and recovery procedures.
VERSIONING.md Links to the release runbook.
charts/README.md Documents the new chart publication flow.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci Issues related to ci process-improvement Any work related to improving project process - code changes, CI / CD or docs improvements.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants