Skip to content

Commit 0be8594

Browse files
authored
feat: Add publish-helm-chart action (#73)
1 parent d03a61e commit 0be8594

3 files changed

Lines changed: 163 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ particular step in a workflow.
2323
- [build-container-image](./build-container-image/README.md)
2424
- [build-product-image](./build-product-image/README.md)
2525
- [free-disk-space](./free-disk-space/README.md)
26+
- [publish-helm-chart](./publish-helm-chart/README.md)
2627
- [publish-image](./publish-image/README.md)
2728
- [publish-image-index-manifest](./publish-image-index-manifest/README.md)
2829
- [run-integration-test](./run-integration-test/README.md)

publish-helm-chart/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# `publish-helm-chart`
2+
3+
> Manifest: [publish-helm-chart/action.yml][publish-helm-chart]
4+
5+
This action packages, publishes, and signs a Helm chart.
6+
It needs the `id-token: write` permission to be able to sign the Helm chart with a GitHub OIDC token.
7+
8+
## Inputs and Outputs
9+
10+
> [!TIP]
11+
> For descriptions of the inputs and outputs, see the complete [publish-helm-chart] action.
12+
13+
### Inputs
14+
15+
| Input | Required | Description |
16+
| ------------------------- | -------- | --------------------------------------------------------------- |
17+
| `chart-registry-uri` | Yes | The URI of the Helm Chart registry |
18+
| `chart-registry-username` | Yes | The username used to login to the Helm Chart registry |
19+
| `chart-registry-password` | Yes | The password used to login to the Helm Chart registry |
20+
| `chart-repository` | Yes | Path to the Helm chart, for example `sdp-charts/kafka-operator` |
21+
| `chart-directory` | Yes | The directory where the Chart.yaml file is located |
22+
| `chart-version` | Yes | The Helm Chart version |
23+
| `app-version` | Yes | The app version to set in the Helm Chart |
24+
| `helm-version` | No | The version of helm |
25+
26+
### Outputs
27+
28+
None.
29+
30+
[publish-helm-chart]: ./action.yaml

publish-helm-chart/action.yaml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
name: Publish Helm Chart
3+
description: This action creates, publishes, and signs a Helm Chart
4+
inputs:
5+
chart-registry-uri:
6+
description: The URI of the Helm Chart registry
7+
required: true
8+
chart-registry-username:
9+
description: The username used to login to the Helm Chart registry
10+
required: true
11+
chart-registry-password:
12+
description: The password used to login to the Helm Chart registry
13+
required: true
14+
chart-repository:
15+
description: Path to the Helm chart, for example `sdp-charts`
16+
required: true
17+
helm-version:
18+
description: Version of helm
19+
# See https://github.com/helm/helm/releases for latest version
20+
default: v3.18.6
21+
chart-version:
22+
description: The Helm Chart version
23+
required: true
24+
chart-directory:
25+
description: The directory where the Chart.yaml file is located
26+
required: true
27+
app-version:
28+
description: The app version to set in the Helm Chart
29+
required: true
30+
runs:
31+
using: composite
32+
steps:
33+
- name: Set up Cosign
34+
uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1
35+
36+
- name: Set up Helm
37+
# We cannot use a path to point to the local action
38+
# See https://github.com/orgs/community/discussions/74934
39+
uses: stackabletech/actions/setup-k8s-tools@7279ffd852a8013df52028de0d99eef68700f803 # TODO: Pin this to the latest tag
40+
with:
41+
helm-version: ${{ inputs.helm-version }}
42+
43+
- name: Log into Container Registry (${{ inputs.chart-registry-uri }}) using Helm
44+
env:
45+
CHART_REGISTRY_USERNAME: ${{ inputs.chart-registry-username }}
46+
CHART_REGISTRY_PASSWORD: ${{ inputs.chart-registry-password }}
47+
CHART_REGISTRY_URI: ${{ inputs.chart-registry-uri }}
48+
GITHUB_DEBUG: ${{ runner.debug }}
49+
shell: bash
50+
run: |
51+
set -euo pipefail
52+
[ -n "$GITHUB_DEBUG" ] && set -x
53+
54+
helm registry login --username "$CHART_REGISTRY_USERNAME" --password "$CHART_REGISTRY_PASSWORD" "$CHART_REGISTRY_URI"
55+
56+
- name: Log into Container Registry (${{ inputs.chart-registry-uri }}) using Docker
57+
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
58+
with:
59+
registry: ${{ inputs.chart-registry-uri }}
60+
username: ${{ inputs.chart-registry-username }}
61+
password: ${{ inputs.chart-registry-password }}
62+
63+
- name: Package Helm Chart
64+
env:
65+
CHART_DIRECTORY: ${{ inputs.chart-directory }}
66+
CHART_VERSION: ${{ inputs.chart-version }}
67+
APP_VERSION: ${{ inputs.app-version }}
68+
GITHUB_DEBUG: ${{ runner.debug }}
69+
shell: bash
70+
run: |
71+
set -euo pipefail
72+
[ -n "$GITHUB_DEBUG" ] && set -x
73+
74+
# Set the Helm Chart version
75+
# yq ".version = \"$CHART_VERSION\"" < "$CHART_DIRECTORY/Chart.yaml" > "$CHART_DIRECTORY/Chart.new.yaml"
76+
# mv "$CHART_DIRECTORY/Chart.new.yaml" "$CHART_DIRECTORY/Chart.yaml"
77+
78+
# Create temporary directory to store the Helm Chart
79+
TEMP_CHART_DIR=$(mktemp -d)
80+
echo "TEMP_CHART_DIR=$TEMP_CHART_DIR" | tee -a "$GITHUB_ENV"
81+
82+
# Package the Helm Chart
83+
helm package \
84+
--destination "$TEMP_CHART_DIR" \
85+
--version "$CHART_VERSION" \
86+
--app-version "$APP_VERSION" \
87+
"$CHART_DIRECTORY"
88+
89+
- name: Publish Helm Chart
90+
env:
91+
CHART_REGISTRY_URI: ${{ inputs.chart-registry-uri }}
92+
CHART_REPOSITORY: ${{ inputs.chart-repository }}
93+
CHART_DIRECTORY: ${{ inputs.chart-directory }}
94+
CHART_VERSION: ${{ inputs.chart-version }}
95+
GITHUB_DEBUG: ${{ runner.debug }}
96+
shell: bash
97+
run: |
98+
set -euo pipefail
99+
[ -n "$GITHUB_DEBUG" ] && set -x
100+
101+
CHART_NAME=$(echo "$CHART_DIRECTORY" | awk -F/ '{print $NF}')
102+
CHART_ARTIFACT="${TEMP_CHART_DIR}/${CHART_NAME}-${CHART_VERSION}.tgz"
103+
echo "CHART_NAME=$CHART_NAME" | tee -a "$GITHUB_ENV"
104+
105+
# Capture the stdout output to extract the digest. It is sad that Helm doesn't provide
106+
# structured output, eg. in JSON. There is a 2-year old open issue about it:
107+
# https://github.com/helm/helm/issues/11735
108+
HELM_OUTPUT=$(helm push "$CHART_ARTIFACT" "oci://${CHART_REGISTRY_URI}/${CHART_REPOSITORY}" 2>&1)
109+
110+
# Yuck
111+
CHART_DIGEST=$(echo "$HELM_OUTPUT" | awk '/^Digest: sha256:[0-9a-f]{64}$/ { print $2 }')
112+
113+
if [ -z "$CHART_DIGEST" ]; then
114+
echo "Could not find digest of Helm Chart"
115+
exit 1
116+
fi
117+
118+
echo "CHART_DIGEST=$CHART_DIGEST" | tee -a "$GITHUB_ENV"
119+
120+
- name: Sign Helm Chart
121+
env:
122+
CHART_REGISTRY_URI: ${{ inputs.chart-registry-uri }}
123+
CHART_REPOSITORY: ${{ inputs.chart-repository }}
124+
GITHUB_DEBUG: ${{ runner.debug }}
125+
shell: bash
126+
run: |
127+
set -euo pipefail
128+
[ -n "$GITHUB_DEBUG" ] && set -x
129+
130+
# This generates a signature and publishes it to the registry, next to the chart artifact
131+
# Uses the keyless signing flow with Github Actions as identity provider
132+
cosign sign --yes "${CHART_REGISTRY_URI}/${CHART_REPOSITORY}/${CHART_NAME}@${CHART_DIGEST}"

0 commit comments

Comments
 (0)