Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions .github/actions/publish-helm-chart/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# publish-helm-chart

Packages a Helm chart and pushes it to ChartMuseum. Handles multi-version publishes, in-place `Chart.yaml` / `values.yaml` edits via yq, and optional latest-semver re-push for stable release streams.

## Inputs

| Name | Description | Required | Default |
|------|-------------|----------|---------|
| `chart-name` | Written to `.name` in `Chart.yaml`; also determines the packaged tarball filename | yes | — |
| `chart-description` | Optional value written to `.description` in `Chart.yaml`. Preserved when empty | no | `""` |
| `app-version` | Passed as `--app-version` to `helm package`. When empty, the chart's existing `appVersion` is used | no | `""` |
| `chart-versions` | JSON array of chart versions. Each entry is packaged and pushed as `<chart-name>-<version>.tgz`. Examples: `'["1.2.3"]'`, `'["0.0.0-latest","0.0.0-abc1234"]'` | yes | — |
| `chart-directory` | Path to the Helm chart source directory | no | `chart` |
| `values-edits` | Newline-separated `jsonpath=value` pairs applied via yq to `<chart-directory>/values.yaml`. Values are written as strings | no | `""` |
| `helm-version` | Helm CLI version to install | no | `v4.1.4` |
| `republish-latest` | When `"true"`, after pushing, re-push the highest semver so it becomes the most recently uploaded entry (for stable release streams) | no | `"false"` |
| `chart-museum-url` | ChartMuseum base URL | no | `https://charts.loft.sh/` |
| `chart-museum-user` | ChartMuseum username | yes | — |
| `chart-museum-password` | ChartMuseum password | yes | — |

## Usage

### Head chart on push-to-main

```yaml
name: Push head images

on:
push:
branches: [main]

jobs:
publish-head-chart:
runs-on: ubuntu-24.04
permissions:
contents: read
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: loft-sh/github-actions/.github/actions/publish-helm-chart@publish-helm-chart/v2
with:
chart-name: vcluster-head
app-version: head-${{ github.sha }}
chart-versions: '["0.0.0-latest","0.0.0-${{ github.sha }}"]'
chart-museum-user: ${{ secrets.CHART_MUSEUM_USER }}
chart-museum-password: ${{ secrets.CHART_MUSEUM_PASSWORD }}
```

### Release chart (custom ref + dual product)

```yaml
jobs:
publish-release-chart:
runs-on: ubuntu-24.04
strategy:
matrix:
product:
- {name: loft, description: "Loft chart"}
- {name: vcluster-platform, description: "vCluster Platform chart"}
permissions:
contents: read
timeout-minutes: 15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event.release.tag_name }}
persist-credentials: false
- uses: loft-sh/github-actions/.github/actions/publish-helm-chart@publish-helm-chart/v2
with:
chart-name: ${{ matrix.product.name }}
chart-description: ${{ matrix.product.description }}
chart-versions: '["${{ inputs.release_version }}"]'
values-edits: |
.product=${{ matrix.product.name }}
republish-latest: "true"
chart-museum-user: ${{ secrets.CHART_MUSEUM_USER }}
chart-museum-password: ${{ secrets.CHART_MUSEUM_PASSWORD }}
```

## Notes

The caller owns `actions/checkout` — so to publish a specific ref (e.g. a release tag), pass it to `actions/checkout` directly rather than through this action.

## Testing

```bash
make test-publish-helm-chart
```

Runs the bats suite in `test/run.bats` against `run.sh` with stubbed `helm` and `yq` binaries. Requires `mikefarah/yq` on `PATH` for the real-yq assertions.
84 changes: 84 additions & 0 deletions .github/actions/publish-helm-chart/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: 'Publish Helm chart'
description: "Package a Helm chart and push it to ChartMuseum. Supports multi-version publishes, values.yaml edits, and latest-semver re-push for stable release streams."
branding:
icon: "package"
color: "blue"

inputs:
chart-name:
description: "Helm chart name. Written to .name in Chart.yaml; also determines the packaged tarball filename."
required: true
chart-description:
description: "Optional value written to .description in Chart.yaml. When empty, the existing description is preserved."
required: false
default: ""
app-version:
description: "Optional value passed as --app-version to `helm package`. When empty, the chart's existing appVersion is used."
required: false
default: ""
chart-versions:
description: "JSON array of chart versions to publish. Each entry is packaged and pushed as <chart-name>-<version>.tgz. Examples: '[\"1.2.3\"]' or '[\"0.0.0-latest\",\"0.0.0-abc1234\"]'."
required: true
chart-directory:
description: "Path to the Helm chart source directory."
required: false
default: chart
values-edits:
description: "Optional newline-separated `jsonpath=value` pairs applied via yq to <chart-directory>/values.yaml. Values are written as strings."
required: false
default: ""
helm-version:
description: "Helm CLI version to install."
required: false
# renovate: datasource=github-releases depName=helm/helm
default: v4.1.4
republish-latest:
description: "When true, after pushing, query ChartMuseum for the highest semver of <chart-name> and re-push it so it becomes the most recently uploaded entry. Use for stable release publishing into a multi-line release stream."
required: false
default: "false"
chart-museum-url:
description: "ChartMuseum base URL."
required: false
default: https://charts.loft.sh/
chart-museum-user:
description: "ChartMuseum username."
required: true
chart-museum-password:
description: "ChartMuseum password."
required: true

runs:
using: "composite"
steps:
- name: Set up Helm
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: ${{ inputs.helm-version }}

- name: Install helm-push plugin
# --verify=false: Helm v4 verifies plugin sources by default; the
# chartmuseum/helm-push plugin does not ship a verification manifest,
# so the install fails without this flag. The flag is a no-op on v3.
shell: bash
run: helm plugin install --verify=false https://github.com/chartmuseum/helm-push.git

- name: Set up yq
uses: dcarbone/install-yq-action@4075b4dca348d74bd83f2bf82d30f25d7c54539b # v1.3.1
with:
# renovate: datasource=github-releases depName=mikefarah/yq
version: v4.52.5

- name: Publish chart
shell: bash
env:
CHART_DIRECTORY: ${{ inputs.chart-directory }}
CHART_NAME: ${{ inputs.chart-name }}
CHART_DESCRIPTION: ${{ inputs.chart-description }}
APP_VERSION: ${{ inputs.app-version }}
CHART_VERSIONS_JSON: ${{ inputs.chart-versions }}
VALUES_EDITS: ${{ inputs.values-edits }}
REPUBLISH_LATEST: ${{ inputs.republish-latest }}
CHART_MUSEUM_URL: ${{ inputs.chart-museum-url }}
CHART_MUSEUM_USER: ${{ inputs.chart-museum-user }}
CHART_MUSEUM_PASSWORD: ${{ inputs.chart-museum-password }}
run: ${{ github.action_path }}/run.sh
125 changes: 0 additions & 125 deletions .github/workflows/publish-helm-chart.yaml

This file was deleted.

6 changes: 3 additions & 3 deletions .github/workflows/test-publish-helm-chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: Test publish-helm-chart
on:
pull_request:
paths:
- '.github/scripts/publish-helm-chart/**'
- '.github/workflows/publish-helm-chart.yaml'
- '.github/actions/publish-helm-chart/**'
- '.github/workflows/test-publish-helm-chart.yaml'

permissions: {}

Expand All @@ -22,4 +22,4 @@ jobs:
version: v4.52.5
- uses: bats-core/bats-action@77d6fb60505b4d0d1d73e48bd035b55074bbfb43 # 4.0.0
with:
tests: .github/scripts/publish-helm-chart/test
tests: .github/actions/publish-helm-chart/test
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ test-ci-test-notify: ## run ci-test-notify bats tests
bats $(ACTIONS_DIR)/ci-test-notify/test/build-payload.bats

test-publish-helm-chart: ## run publish-helm-chart bats tests (requires mikefarah/yq on PATH)
bats $(SCRIPTS_DIR)/publish-helm-chart/test/run.bats
bats $(ACTIONS_DIR)/publish-helm-chart/test/run.bats

test-govulncheck: ## run govulncheck bats tests
bats $(ACTIONS_DIR)/govulncheck/test/run.bats
Expand Down
Loading
Loading