Skip to content

Commit 8fd5747

Browse files
authored
ci(helm): add OCI chart release workflow (#1196)
* ci(helm): add OCI chart release workflow Publishes the Helm chart to ghcr.io/nvidia/openshell/helm-chart via helm push on every tag (versioned + :latest) and main push (:0.0.0-dev overwrite + :0.0.0-dev.<sha> per-commit pin). Renames Chart.yaml name to helm-chart to match the target OCI path. * ci(helm): use full sha in dev pinned chart version The container images pushed by docker-build.yml are tagged with the full $GITHUB_SHA, not a 7-char prefix. Match the chart's pinned version (0.0.0-dev.<full-sha>) so the chart tag and the image tag the chart resolves to are identical. * docs(readme): add helm chart install instructions Document the OCI chart at ghcr.io/nvidia/openshell/helm-chart with examples for tagged, floating dev, and SHA-pinned dev installs, and flag the Kubernetes deployment path as experimental. * docs(helm): split chart details into chart README Move the dev tag conventions and configuration pointers into a new README under deploy/helm/openshell/ and shorten the top-level README section to the install command (no --version, defaults to latest tagged semver) plus a link to the chart README.
1 parent df8ac94 commit 8fd5747

6 files changed

Lines changed: 183 additions & 4 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Release Helm OCI
5+
description: >
6+
Patch chart version/appVersion, refuse duplicate OCI versions on public
7+
releases, package the chart, and push to GHCR OCI.
8+
9+
inputs:
10+
chart-version:
11+
description: >
12+
Chart.yaml version and OCI tag — SemVer without leading v
13+
(e.g. 0.6.0 for tag releases, 0.0.0-dev for dev).
14+
required: true
15+
app-version:
16+
description: >
17+
Chart.yaml appVersion and default image tag
18+
(e.g. 0.6.0 for tag releases, dev for dev).
19+
required: true
20+
release-kind:
21+
description: "dev or public — controls the duplicate-version guard."
22+
required: true
23+
pin-sha:
24+
description: >
25+
Full commit SHA. When set on dev releases, a second chart is also pushed
26+
as 0.0.0-dev.<sha> with appVersion set to the same SHA, enabling exact
27+
version pinning alongside the floating 0.0.0-dev tag. Both chart version
28+
and appVersion use the full SHA so the chart tag matches the image tag
29+
pushed by docker-build.yml.
30+
required: false
31+
default: ""
32+
33+
runs:
34+
using: composite
35+
steps:
36+
- name: Log in to GHCR
37+
uses: docker/login-action@v3
38+
with:
39+
registry: ghcr.io
40+
username: ${{ github.actor }}
41+
password: ${{ github.token }}
42+
43+
- name: Install Helm
44+
uses: azure/setup-helm@v4
45+
46+
- name: Stage chart and patch version
47+
id: prep
48+
env:
49+
CHART_VERSION: ${{ inputs.chart-version }}
50+
APP_VERSION: ${{ inputs.app-version }}
51+
shell: bash
52+
run: |
53+
set -euo pipefail
54+
CHART_DIR="${RUNNER_TEMP}/chart-build"
55+
cp -a deploy/helm/openshell/. "${CHART_DIR}"
56+
sed -i "s/^version:.*/version: ${CHART_VERSION}/" "${CHART_DIR}/Chart.yaml"
57+
sed -i "s/^appVersion:.*/appVersion: \"${APP_VERSION}\"/" "${CHART_DIR}/Chart.yaml"
58+
echo "chart_dir=${CHART_DIR}" >> "$GITHUB_OUTPUT"
59+
echo "chart_version=${CHART_VERSION}" >> "$GITHUB_OUTPUT"
60+
61+
- name: Refuse duplicate chart version
62+
if: inputs.release-kind == 'public'
63+
env:
64+
CHART_VERSION: ${{ steps.prep.outputs.chart_version }}
65+
shell: bash
66+
run: |
67+
set -euo pipefail
68+
OCI_CHART="oci://ghcr.io/nvidia/openshell/helm-chart"
69+
if helm show chart "${OCI_CHART}" --version "${CHART_VERSION}" >/dev/null 2>&1; then
70+
echo "::error::Chart ${CHART_VERSION} is already published. Use a new tag or delete the existing package first."
71+
exit 1
72+
fi
73+
74+
- name: Package Helm chart
75+
env:
76+
CHART_DIR: ${{ steps.prep.outputs.chart_dir }}
77+
shell: bash
78+
run: |
79+
set -euo pipefail
80+
helm package "${CHART_DIR}" --destination /tmp
81+
ls /tmp/helm-chart-*.tgz
82+
83+
- name: Push Helm chart to GHCR OCI
84+
shell: bash
85+
run: |
86+
set -euo pipefail
87+
helm push /tmp/helm-chart-*.tgz oci://ghcr.io/nvidia/openshell
88+
89+
- name: Push SHA-pinned chart
90+
if: inputs.pin-sha != ''
91+
env:
92+
PIN_SHA: ${{ inputs.pin-sha }}
93+
CHART_DIR: ${{ steps.prep.outputs.chart_dir }}
94+
shell: bash
95+
run: |
96+
set -euo pipefail
97+
SHA_CHART_DIR="${RUNNER_TEMP}/chart-build-sha"
98+
cp -a "${CHART_DIR}/." "${SHA_CHART_DIR}"
99+
sed -i "s/^version:.*/version: 0.0.0-dev.${PIN_SHA}/" "${SHA_CHART_DIR}/Chart.yaml"
100+
sed -i "s/^appVersion:.*/appVersion: \"${PIN_SHA}\"/" "${SHA_CHART_DIR}/Chart.yaml"
101+
helm package "${SHA_CHART_DIR}" --destination /tmp/sha-pin
102+
helm push /tmp/sha-pin/helm-chart-*.tgz oci://ghcr.io/nvidia/openshell

.github/workflows/release-dev.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,23 @@ jobs:
883883
release/openshell-gateway-checksums-sha256.txt
884884
release/openshell-sandbox-checksums-sha256.txt
885885
886+
release-helm:
887+
name: Release Helm Chart (OCI, dev)
888+
needs: [tag-ghcr-dev]
889+
runs-on: ubuntu-latest
890+
timeout-minutes: 10
891+
permissions:
892+
packages: write
893+
steps:
894+
- uses: actions/checkout@v6
895+
896+
- uses: ./.github/actions/release-helm-oci
897+
with:
898+
chart-version: 0.0.0-dev
899+
app-version: dev
900+
release-kind: dev
901+
pin-sha: ${{ github.sha }}
902+
886903
trigger-wheel-publish:
887904
name: Trigger Wheel Publish
888905
needs: [compute-versions, release-dev]

.github/workflows/release-tag.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,24 @@ jobs:
877877
working-directory: ./fern
878878
run: fern generate --docs
879879

880+
release-helm:
881+
name: Release Helm Chart (OCI)
882+
needs: [compute-versions, tag-ghcr-release]
883+
runs-on: ubuntu-latest
884+
timeout-minutes: 10
885+
permissions:
886+
packages: write
887+
steps:
888+
- uses: actions/checkout@v6
889+
with:
890+
ref: ${{ inputs.tag || github.ref }}
891+
892+
- uses: ./.github/actions/release-helm-oci
893+
with:
894+
chart-version: ${{ needs.compute-versions.outputs.semver }}
895+
app-version: ${{ needs.compute-versions.outputs.semver }}
896+
release-kind: public
897+
880898
trigger-wheel-publish:
881899
name: Trigger Wheel Publish
882900
needs: [compute-versions, release]

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ uv tool install -U openshell
3535

3636
Both methods install the latest stable release by default. To install a specific version, set `OPENSHELL_VERSION` (binary) or pin the version with `uv tool install openshell==<version>`. A [`dev` release](https://github.com/NVIDIA/OpenShell/releases/tag/dev) is also available that tracks the latest commit on `main`.
3737

38+
**Helm chart:**
39+
40+
> **Experimental** — the Kubernetes deployment path is under active development. Expect rough edges and breaking changes.
41+
42+
Deploy the OpenShell gateway into a Kubernetes cluster from the OCI chart published to GHCR:
43+
44+
```bash
45+
helm install openshell oci://ghcr.io/nvidia/openshell/helm-chart
46+
```
47+
48+
See [`deploy/helm/openshell/README.md`](deploy/helm/openshell/README.md) for available versions, dev tag conventions, and configuration.
49+
3850
### Create a sandbox
3951

4052
```bash

deploy/helm/openshell/Chart.yaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
apiVersion: v2
5-
name: openshell
5+
# Chart name determines the OCI image name: ghcr.io/nvidia/openshell/helm-chart:<version>
6+
name: helm-chart
67
description: runtime environment for autonomous agents
78
type: application
8-
# Updated to the release version by CI. The appVersion doubles as the default
9-
# image tag (image.tag defaults to appVersion when empty), so a released chart
10-
# automatically pulls the matching gateway and supervisor images.
9+
# version and appVersion are patched to the release semver by CI before helm package.
10+
# appVersion doubles as the default image tag (image.tag defaults to appVersion when
11+
# empty), so a released chart automatically pulls the matching gateway and supervisor images.
1112
version: 0.0.0
1213
appVersion: "0.0.0"

deploy/helm/openshell/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# OpenShell Helm Chart
2+
3+
> **Experimental** — the Kubernetes deployment path is under active development. Expect rough edges and breaking changes.
4+
5+
This chart deploys the OpenShell gateway into a Kubernetes cluster. It is published as an OCI artifact to GHCR at `oci://ghcr.io/nvidia/openshell/helm-chart`.
6+
7+
## Install
8+
9+
```bash
10+
helm install openshell oci://ghcr.io/nvidia/openshell/helm-chart --version <version>
11+
```
12+
13+
## Available versions
14+
15+
| Tag | Source | Notes |
16+
| --- | --- | --- |
17+
| `<semver>` (e.g. `0.6.0`) | Tagged GitHub release | Tracks the matching gateway and supervisor image versions. Recommended for production. |
18+
| `0.0.0-dev` | Latest commit on `main` | Floating tag, overwritten on every push. `appVersion` is `dev`, so images resolve to the `:dev` tag. |
19+
| `0.0.0-dev.<commit-sha>` | A specific commit on `main` | Per-commit pin. Chart version and `appVersion` both use the full 40-character commit SHA, which matches the image tag pushed by CI. |
20+
21+
The `dev` tags are intended for testing changes ahead of a release. Production deployments should pin to a tagged release.
22+
23+
## Configuration
24+
25+
See [`values.yaml`](values.yaml) for configurable values. Selected overlays:
26+
27+
- [`values-gateway.yaml`](values-gateway.yaml) — gateway-only configuration
28+
- [`values-cert-manager.yaml`](values-cert-manager.yaml) — cert-manager integration
29+
- [`values-keycloak.yaml`](values-keycloak.yaml) — Keycloak OIDC integration

0 commit comments

Comments
 (0)