mirror-chart #26616
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Mirror External Helm Chart | |
| # Mirrors a single upstream chart version into oci://ghcr.io/fredericrous/charts. | |
| # | |
| # Fired by repository_dispatch from fredericrous/homelab's mirror-discover | |
| # workflow, which walks HelmRelease + HelmRepository CRDs and sends one | |
| # event per (chart, version, upstream) tuple. workflow_dispatch is also | |
| # kept for ad-hoc manual mirroring. | |
| # | |
| # Idempotent: if the chart@version already exists in the target OCI | |
| # registry, the run skips the pull+push and exits successfully. | |
| on: | |
| repository_dispatch: | |
| types: [mirror-chart] | |
| workflow_dispatch: | |
| inputs: | |
| chart: | |
| description: 'Chart name (e.g. tetragon)' | |
| required: true | |
| type: string | |
| version: | |
| description: 'Chart version (e.g. 1.7.0)' | |
| required: true | |
| type: string | |
| upstream: | |
| description: 'Upstream Helm repo URL (e.g. https://helm.cilium.io)' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: read | |
| packages: write | |
| jobs: | |
| mirror: | |
| name: Pull from upstream, push to OCI | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Resolve inputs | |
| id: in | |
| run: | | |
| if [ "${{ github.event_name }}" = "repository_dispatch" ]; then | |
| chart='${{ github.event.client_payload.chart }}' | |
| version='${{ github.event.client_payload.version }}' | |
| upstream='${{ github.event.client_payload.upstream }}' | |
| else | |
| chart='${{ inputs.chart }}' | |
| version='${{ inputs.version }}' | |
| upstream='${{ inputs.upstream }}' | |
| fi | |
| for v in chart version upstream; do | |
| if [ -z "${!v}" ]; then | |
| echo "::error::missing input: $v" | |
| exit 1 | |
| fi | |
| done | |
| echo "chart=$chart" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "upstream=$upstream" >> "$GITHUB_OUTPUT" | |
| echo "Mirroring ${chart}@${version} from ${upstream}" | |
| - name: Set up Helm | |
| uses: azure/setup-helm@v4 | |
| with: | |
| version: v3.13.3 | |
| - name: Log in to GHCR | |
| run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin | |
| - name: Mirror chart | |
| env: | |
| CHART: ${{ steps.in.outputs.chart }} | |
| VERSION: ${{ steps.in.outputs.version }} | |
| UPSTREAM: ${{ steps.in.outputs.upstream }} | |
| run: | | |
| set -euo pipefail | |
| target="oci://ghcr.io/${{ github.repository_owner }}/charts" | |
| # Skip if this version already exists in the target OCI registry. | |
| # `helm show chart` on the OCI ref succeeds only if the artifact | |
| # is present. | |
| if helm show chart "${target}/${CHART}" --version "${VERSION}" >/dev/null 2>&1; then | |
| echo "${CHART}@${VERSION} already mirrored — skipping" | |
| exit 0 | |
| fi | |
| workdir=$(mktemp -d) | |
| if ! helm pull "${CHART}" --repo "${UPSTREAM}" --version "${VERSION}" --destination "${workdir}"; then | |
| echo "::error::helm pull failed for ${CHART}@${VERSION} from ${UPSTREAM}" | |
| exit 1 | |
| fi | |
| # Some charts publish versions as `v1.2.3` (leading `v`), which | |
| # makes the tgz filename `<chart>-v1.2.3.tgz` rather than | |
| # `<chart>-1.2.3.tgz`. Glob-match so both conventions work. | |
| tgz=$(ls "${workdir}"/${CHART}-*.tgz 2>/dev/null | head -1 || true) | |
| if [ -z "${tgz}" ] || [ ! -f "${tgz}" ]; then | |
| echo "::error::no tgz found in ${workdir} after pull (expected ${CHART}-*.tgz)" | |
| exit 1 | |
| fi | |
| if ! helm push "${tgz}" "${target}"; then | |
| echo "::error::helm push failed for ${CHART}@${VERSION}" | |
| exit 1 | |
| fi | |
| echo "mirrored → ${target}/${CHART}:${VERSION}" |