Skip to content

Commit 4352ce7

Browse files
committed
feat(helm): also publish the chart to a classic HTTP repo
I claimed earlier that OCI-only was defensible in 2026. That was wrong, and checking rather than reasoning settled it: Bitnami, cert-manager, ingress-nginx, prometheus-community, Grafana, Argo and external-secrets all still serve a live index.yaml. Dual-publish is the actual convention, and external-secrets -- the workflow this one is modelled on -- does both. Adds a chart-releaser job that maintains index.yaml on a pages branch and attaches each packaged chart to a GitHub release. It is a separate job from the OCI publish because it needs contents: write to cut that release, and that permission has no business sitting in the job that holds the signing identity. Three details worth stating: - mark_as_latest is false. A chart release must never take the "Latest" badge from the application release it packages. - Releases are named helm-chart-<version> so they stay distinguishable from the vX.Y.Z app releases in the same list. - skip_existing mirrors the OCI job: re-running on a published version is a no-op rather than an overwrite. The job no-ops with a warning until a gh-pages branch exists, because creating that branch and enabling Pages are one-time manual steps no workflow can perform for itself, and main's CI must not fail on their absence. No documentation yet. index.yaml is only reachable once the branch, Pages, and DNS are in place, and pointing users at a hostname that does not resolve is the exact failure this whole PR exists to remove.
1 parent 2b33120 commit 4352ce7

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

.github/workflows/helm.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,73 @@ jobs:
374374
echo "helm install sim oci://${REPOSITORY} --version ${VERSION}"
375375
echo '```'
376376
} >> "$GITHUB_STEP_SUMMARY"
377+
378+
# The classic HTTP repo, published alongside the OCI artifact above. Both is
379+
# what the ecosystem actually does: Bitnami, cert-manager, ingress-nginx,
380+
# prometheus-community, Grafana, Argo and external-secrets all still serve an
381+
# index.yaml, because plenty of clusters, GitOps configs and mirroring tools
382+
# only speak `helm repo add`. OCI is the modern path, not yet the only one.
383+
#
384+
# Separate from the OCI job on purpose: chart-releaser needs `contents: write`
385+
# to cut a release and push the index, and there is no reason to hand that to
386+
# the job holding the signing identity.
387+
publish-http:
388+
name: Publish chart to the Helm repo
389+
needs: [chart, install]
390+
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'simstudioai/sim'
391+
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-2vcpu-ubuntu-2404' || 'ubuntu-latest' }}
392+
timeout-minutes: 15
393+
permissions:
394+
contents: write # Cut the chart release and push index.yaml to the pages branch.
395+
steps:
396+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
397+
with:
398+
# chart-releaser diffs against the previous tag to decide which charts
399+
# changed, so it needs the full history rather than a shallow clone.
400+
fetch-depth: 0
401+
# chart-releaser authenticates with CR_TOKEN, not the checkout credential.
402+
persist-credentials: false
403+
404+
# Creating the pages branch and turning on GitHub Pages are one-time
405+
# manual steps that no workflow can do for itself. Skip loudly rather than
406+
# failing main when they have not happened yet -- the OCI publish is
407+
# independent and must not be held hostage to this.
408+
- name: Check the pages branch exists
409+
id: pages
410+
run: |
411+
set -euo pipefail
412+
if git ls-remote --exit-code --heads origin gh-pages >/dev/null 2>&1; then
413+
echo "exists=true" >> "$GITHUB_OUTPUT"
414+
else
415+
echo "exists=false" >> "$GITHUB_OUTPUT"
416+
echo "::warning::No gh-pages branch, so the HTTP chart repo was not updated. Create it and point GitHub Pages at it to activate this job. The OCI publish is unaffected."
417+
fi
418+
419+
- name: Configure Git
420+
if: steps.pages.outputs.exists == 'true'
421+
env:
422+
ACTOR: ${{ github.actor }}
423+
run: |
424+
set -euo pipefail
425+
git config user.name "${ACTOR}"
426+
git config user.email "${ACTOR}@users.noreply.github.com"
427+
428+
# chart-releaser writes index.yaml to the pages branch and attaches the
429+
# .tgz to a GitHub release, which is where index.yaml points -- so the
430+
# packages stay reachable no matter which domain serves the index.
431+
- name: Run chart-releaser
432+
if: steps.pages.outputs.exists == 'true'
433+
uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
434+
with:
435+
charts_dir: helm
436+
# Re-running on an already-released version must be a no-op, the same
437+
# way the OCI publish above refuses to move a published version.
438+
skip_existing: true
439+
# A chart release must never take the "Latest" badge from the
440+
# application release it packages.
441+
mark_as_latest: false
442+
env:
443+
CR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
444+
# Keeps chart releases visually distinct from the vX.Y.Z app releases
445+
# they share the list with.
446+
CR_RELEASE_NAME_TEMPLATE: "helm-chart-{{ .Version }}"

0 commit comments

Comments
 (0)