As a Giant Swarm engineer, I want to publish our Helm charts to Artifact Hub so that our customers and the open-source community can easily discover, verify, and deploy our solutions.
Status (2026-07-21)
Paused at a one-chart pilot; ready to scale on an opt-in basis.
- Live on Artifact Hub:
hello-world only, as Verified Publisher. (A full 264-chart backfill was run and verified on 2026-07-16, then deliberately rolled back the same day — see history in section B.)
- Design settled: publication is opt-in per repository, driven by a nightly reconciler that now lives in
giantswarm/github.
- Blocking the rollout: (A) a shared Artifact Hub account + secrets, and (B) merging the reconciler PR giantswarm/github#5659.
Why
- Discoverability & trust: Artifact Hub is the de-facto search surface for Helm charts. A curated, Verified Publisher presence increases adoption and signals maintenance quality.
- Defensive namespace ownership: in 2023 a third party listed our public catalogs on Artifact Hub under our name (no READMEs, indexing errors, implied support). We now control the
giantswarm Artifact Hub organization.
Approach
- OCI-first from
gsoci.azurecr.io/charts/giantswarm (aligned with the HelmRelease/OCIRepository migration, giantswarm/giantswarm#34515). GitHub-Pages catalogs are deliberately not registered (legacy path).
- Opt-in per repository: a team sets
artifactHub: true on its repo entry in giantswarm/github repositories/team-*.yaml; only flagged charts are published. The flag replaces the earlier "publish all + denylist" idea and is itself the staged-rollout control.
- Reconciler-only (no per-release CI step): a nightly job resolves each flagged repo to its chart name via the catalog's
giantswarm.io/helmcharts annotation, then registers/deregisters against the Artifact Hub org. private-tagged components are never published. After first registration, Artifact Hub polls the registry itself, so new chart versions need no involvement.
Work items
A. Shared account (workstream A — the main prerequisite)
artifactHub schema flag + nightly artifacthub-sync workflow + tools/artifacthub/reconcile.py.
- Proven mechanics carried over verbatim: register
disabled: true → ORAS-push metadata artifact → enable; dev-version ignore rules; CloudFront cache-bust; ~1 req/s throttle.
- Guardrails: abort on an empty opt-in set or empty gsoci listing; deregistration capped at max(10, 10%) per run; manual runs default to dry-run with a
LIMIT input for tranches.
- Inert until the secrets exist (the workflow no-ops with a notice), so it is safe to merge ahead of workstream A.
hello-world-app is flagged in the PR, so the pilot continues; a live dry-run shows zero diff.
- History: the standalone repo giantswarm/artifacthub-sync ran the full 264-chart backfill (all verified) on 2026-07-16, rolled back the same day to the hello-world pilot — publishing everything is an org-level step the team gates explicitly. Its improvements (LIMIT, cache-bust, strict-JSON parsing) are ported into giantswarm/github#5659; giantswarm/artifacthub-sync#4 and giantswarm/github#5653 are closed, and the standalone repo is archived (2026-07-17).
- When missing in the chart,
abs injects at packaging: artifacthub.io/license (from the repo LICENSE), artifacthub.io/links (Support → repo issues; Upstream from sources:), and a chart-dir README.md (copied from the repo root). Explicit Chart.yaml values always win, and nothing injected is visible outside Artifact Hub, so it is harmless for non-published charts.
- Icon decision revised (2026-07-21): the forced GS-logo icon override was dropped. It was a child of the publish-all strategy; with opt-in publishing it would have rebranded every abs-built chart in Backstage/happa for zero AH benefit. Charts keep their own icons; a team sets
icon: in Chart.yaml when opting in if it wants one. Remaining review point: Support links point to <repo>/issues, which is dead for repos with GitHub issues disabled.
- Add
artifacthub.io/license + artifacthub.io/links to helm/{APP-NAME}/Chart.yaml so new charts are born compliant.
- Maintainers stripped, ready for merge + patch-release (also fixes its verified/dev-filter state).
- The nightly reconcile covers the flagged pilot (
hello-world) — zero-diff steady state.
- Teams flag their repos (
artifactHub: true) at their own pace; each nightly run registers the delta. Tranche size is controlled by ordinary PR review of the flag changes; LIMIT remains available as a brake.
- Pilot validation after giantswarm/app-build-suite#569 merges and
hello-world releases: confirm license / links / README render on the AH page.
Key learnings (from the PoC, 2026-07-15)
- Zero CI work per release: Artifact Hub polls the OCI registry itself, so new versions appear automatically. The metadata artifact is static per chart; the only recurring task is registering new charts.
- Sequencing matters: AH's first tracker pass must already see the metadata artifact (register
disabled: true → push artifact → enable). external-dns-app missed that window in the PoC and stayed unverified until its next release forced a reprocess.
- Dev-tag pollution:
X.Y.Z-dev.… tags share the OCI path and can headline the listing; filtered per chart via ignore: [{name: <chart>, version: ".*-dev\\..*"}] in artifacthub-repo.yml.
- Verified Publisher works via the ORAS-pushed
artifacthub-repo.yml — confirmed on hello-world after its v3.0.3 release (giantswarm/hello-world-app#262).
- Maintainers: intentionally not used — AH only renders them with an email; the org page + Verified badge + Support link cover it.
- API gotchas: no AH service accounts exist (keys are user-bound → shared account needed); always send BOTH
X-API-KEY-ID and X-API-KEY-SECRET headers, else a misleading CSRF 403 ("referer not supplied").
Accepted risks
Unknown co-owner(s) of the AH org — resolved: owner identified (2026-07-16).
giantswarm-<chart> AH repo-name collisions with third-party repos → 409s logged for manual review.
- New charts appear on AH within the cron interval (≤1 day after flagging), not instantly.
Related: giantswarm/roadmap#2427 (Planeteers) — proposing to consolidate here.
As a Giant Swarm engineer, I want to publish our Helm charts to Artifact Hub so that our customers and the open-source community can easily discover, verify, and deploy our solutions.
Status (2026-07-21)
Paused at a one-chart pilot; ready to scale on an opt-in basis.
hello-worldonly, as Verified Publisher. (A full 264-chart backfill was run and verified on 2026-07-16, then deliberately rolled back the same day — see history in section B.)giantswarm/github.Why
giantswarmArtifact Hub organization.Approach
gsoci.azurecr.io/charts/giantswarm(aligned with the HelmRelease/OCIRepository migration, giantswarm/giantswarm#34515). GitHub-Pages catalogs are deliberately not registered (legacy path).artifactHub: trueon its repo entry ingiantswarm/githubrepositories/team-*.yaml; only flagged charts are published. The flag replaces the earlier "publish all + denylist" idea and is itself the staged-rollout control.giantswarm.io/helmchartsannotation, then registers/deregisters against the Artifact Hub org.private-tagged components are never published. After first registration, Artifact Hub polls the registry itself, so new chart versions need no involvement.Work items
A. Shared account (workstream A — the main prerequisite)
artifacthub@giantswarm.io— no Workspace bot user needed; AH signup only needs an email that receives the verification link (group must accept external mail).giantswarmAH org and create an API key under it (replaces the personal key used for the PoC).giantswarm/github(needs Planeteers):ARTIFACTHUB_API_KEY_ID,ARTIFACTHUB_API_KEY_SECRET,ACR_GSOCI_USERNAME,ACR_GSOCI_PASSWORD.B. Reconciler — giantswarm/github#5659 (open)
artifactHubschema flag + nightlyartifacthub-syncworkflow +tools/artifacthub/reconcile.py.disabled: true→ ORAS-push metadata artifact → enable; dev-version ignore rules; CloudFront cache-bust; ~1 req/s throttle.LIMITinput for tranches.hello-world-appis flagged in the PR, so the pilot continues; a live dry-run shows zero diff.C. Package-time metadata — giantswarm/app-build-suite#569 (open)
absinjects at packaging:artifacthub.io/license(from the repoLICENSE),artifacthub.io/links(Support → repo issues; Upstream fromsources:), and a chart-dirREADME.md(copied from the repo root). ExplicitChart.yamlvalues always win, and nothing injected is visible outside Artifact Hub, so it is harmless for non-published charts.icon:inChart.yamlwhen opting in if it wants one. Remaining review point: Support links point to<repo>/issues, which is dead for repos with GitHub issues disabled.D. Scaffold — giantswarm/template-app#65 (open)
artifacthub.io/license+artifacthub.io/linkstohelm/{APP-NAME}/Chart.yamlso new charts are born compliant.E. Cleanup — giantswarm/external-dns-app#470 (open)
Rollout sequence (once A + giantswarm/github#5659 merge)
hello-world) — zero-diff steady state.artifactHub: true) at their own pace; each nightly run registers the delta. Tranche size is controlled by ordinary PR review of the flag changes;LIMITremains available as a brake.hello-worldreleases: confirm license / links / README render on the AH page.Key learnings (from the PoC, 2026-07-15)
disabled: true→ push artifact → enable).external-dns-appmissed that window in the PoC and stayed unverified until its next release forced a reprocess.X.Y.Z-dev.…tags share the OCI path and can headline the listing; filtered per chart viaignore: [{name: <chart>, version: ".*-dev\\..*"}]inartifacthub-repo.yml.artifacthub-repo.yml— confirmed onhello-worldafter its v3.0.3 release (giantswarm/hello-world-app#262).X-API-KEY-IDandX-API-KEY-SECRETheaders, else a misleading CSRF 403 ("referer not supplied").Accepted risks
Unknown co-owner(s) of the AH org— resolved: owner identified (2026-07-16).giantswarm-<chart>AH repo-name collisions with third-party repos → 409s logged for manual review.Related: giantswarm/roadmap#2427 (Planeteers) — proposing to consolidate here.