Skip to content

Publish Helm Charts (OCI) #8

Publish Helm Charts (OCI)

Publish Helm Charts (OCI) #8

Workflow file for this run

name: Publish Helm Charts (OCI)
on:
release:
types: [published]
concurrency:
group: publish-oci
cancel-in-progress: false
permissions: {}
env:
REGISTRY: ghcr.io
REGISTRY_PATH: ghcr.io/countly/helm
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
lint:
name: Lint Charts
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- uses: actions/checkout@v5
- name: Install Helm
uses: azure/setup-helm@v4
with:
version: v3.17.0
- name: Lint all charts
run: |
for chart in charts/*/; do
echo "Linting ${chart}..."
helm lint "${chart}" --strict
done
publish:
name: Publish and Sign Charts
runs-on: ubuntu-latest
timeout-minutes: 10
needs: lint
permissions:
contents: write
packages: write
id-token: write
steps:
- uses: actions/checkout@v5
- name: Install Helm
uses: azure/setup-helm@v4
with:
version: v3.17.0
- name: Install Cosign
uses: sigstore/cosign-installer@v4.1.0
- name: Install Syft
uses: anchore/sbom-action/download-syft@v0
- name: Login to GHCR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_ACTOR: ${{ github.actor }}
run: |
echo "${GITHUB_TOKEN}" | helm registry login ${REGISTRY} -u "${GH_ACTOR}" --password-stdin
echo "${GITHUB_TOKEN}" | cosign login ${REGISTRY} -u "${GH_ACTOR}" --password-stdin
- name: Package, push, sign, and attach SBOM
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
mkdir -p /tmp/helm-packages
# Derive chart version from release tag (strip leading 'v' if present)
chart_version="${RELEASE_TAG#v}"
if [ -z "${chart_version}" ]; then
echo "ERROR: Could not derive version from release tag '${RELEASE_TAG}'"
exit 1
fi
echo "Publishing charts at version: ${chart_version}"
for chart_dir in charts/*/; do
chart_name=$(basename "${chart_dir}")
pkg="/tmp/helm-packages/${chart_name}-${chart_version}.tgz"
echo "::group::${chart_name}:${chart_version}"
# Package with version from release tag (includes prerelease suffix)
helm package "${chart_dir}" --version "${chart_version}" --destination /tmp/helm-packages/
# Push with retry (transient GHCR failures)
max_retries=3
push_output=""
push_success=false
for attempt in $(seq 1 $max_retries); do
push_output=$(helm push "${pkg}" "oci://${REGISTRY_PATH}" 2>&1) && { push_success=true; break; }
echo "Push attempt ${attempt}/${max_retries} failed, retrying in 5s..."
sleep 5
done
if [ "${push_success}" != "true" ]; then
echo "ERROR: helm push failed for ${chart_name} after ${max_retries} attempts"
echo "${push_output}"
exit 1
fi
echo "${push_output}"
digest=$(echo "${push_output}" | grep -oE 'sha256:[a-f0-9]{64}' | tail -1)
if [ -z "${digest}" ]; then
echo "ERROR: Could not extract digest for ${chart_name}"
exit 1
fi
ref="${REGISTRY_PATH}/${chart_name}@${digest}"
echo "Digest: ${digest}"
# Sign the OCI artifact (keyless via Sigstore OIDC)
echo "Signing ${chart_name}..."
cosign sign --yes "${ref}"
# Generate SBOM (CycloneDX JSON)
sbom_file="/tmp/helm-packages/${chart_name}-${chart_version}.sbom.cdx.json"
echo "Generating SBOM for ${chart_name}..."
syft dir:"${chart_dir}" -o cyclonedx-json="${sbom_file}"
# Attest SBOM as signed in-toto attestation (replaces deprecated cosign attach sbom)
cosign attest --yes --predicate "${sbom_file}" --type cyclonedx "${ref}"
echo "::endgroup::"
done
- name: Summary and release notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
chart_version="${RELEASE_TAG#v}"
# Build chart listing
chart_list=""
for chart_dir in charts/*/; do
chart_name=$(basename "${chart_dir}")
chart_list="${chart_list}
- \`oci://${REGISTRY_PATH}/${chart_name}:${chart_version}\` — signed + SBOM"
done
# Write job summary
{
echo "## Published Charts"
echo ""
echo "All charts are signed with Cosign (keyless/Sigstore) and include SBOM attestations."
echo "${chart_list}"
} >> "$GITHUB_STEP_SUMMARY"
# Append OCI chart links to release notes
existing_body=$(gh release view "${RELEASE_TAG}" --json body -q '.body')
{
echo "${existing_body}"
echo ""
echo "## OCI Charts"
echo ""
echo '```bash'
echo "helm pull oci://${REGISTRY_PATH}/<chart-name> --version <version>"
echo '```'
echo "${chart_list}"
} | gh release edit "${RELEASE_TAG}" --notes-file -