Skip to content

Commit 4a163b8

Browse files
feat(helm): add OCI registry publishing workflow for GHCR (#226)
* feat(helm): add OCI registry publishing workflow for GHCR Publishes charts to ghcr.io on version tags. Includes test trigger on feat/helm-oci-registry branch. * fix(helm): publish all charts with synchronized versions Updates all chart versions and fhir dependency version to enable nuts-knooppunt packaging. * feat(helm): prefix chart names with 'helm-' to distinguish from Docker images * fix(helm): update fhir dependency repository to OCI for user installations * chore(helm): re-add test branch trigger for validation * fix(helm): reorder workflow to publish standalone charts before dependencies Resolves chicken-and-egg problem where helm dependency update failed because helm-fhir wasn't published yet. Now: 1. Package and push standalone charts (fhir, pep) first 2. Update nuts-knooppunt to use OCI dependencies 3. Run helm dependency update (helm-fhir now exists on GHCR) 4. Package and push helm-nuts-knooppunt * chore(helm): remove test branch trigger from workflow * refactor(helm): use Chart.yaml as source of truth for versions - Rename charts to helm-* prefix in Chart.yaml - Update fhir dependency to OCI registry in nuts-knooppunt Chart.yaml - Remove version override logic from workflow - Chart versions now managed manually in Chart.yaml files * chore(helm): re-add test branch trigger * chore(helm): remove unused version extraction step * chore(helm): removed test branch * docs(helm): add README explaining versioning and publishing workflow * chore(helm): update Chart.lock and add concurrency comment * refactor(helm): implement automated chart versioning Split Helm chart publishing into 3 separate workflows: - nuts-knooppunt: coupled versioning from git tags - fhir/pep: independent versioning on path changes Changes: - Auto-version nuts-knooppunt chart from git tags - Add PEP as optional dependency - Set version/appVersion to 0.0.0 placeholders - Empty image.tag to use Chart.AppVersion - Update README with versioning strategies Addresses feedback on PR #226 requiring deterministic version management and reducing manual sync errors * Apply suggestions from code review `pep` was missing from some comments Co-authored-by: Copilot <[email protected]> * chore(helm): bump helm-pep and pep chart versions to 0.1.1 - testing CI * chore(helm): remove feat/helm-oci-registry branch from publish workflows as tests succeeded * docs(helm): clarify versioning strategies and fix fhir appVersion - Fix helm-fhir appVersion: 1.16.0 -> 7.2.0 (match actual HAPI version) - Clarify automatic (nuts-knooppunt) vs manual (fhir/pep) versioning - Explain independent release cycles (PEP changes infrequently, FHIR follows HAPI) - Add critical warning about chart version bumps (OCI immutability) - Add semantic versioning guide (patch/minor/major) - Add concrete examples for HAPI upgrade and chart config fixes --------- Co-authored-by: Copilot <[email protected]>
1 parent 9368c1e commit 4a163b8

File tree

9 files changed

+352
-14
lines changed

9 files changed

+352
-14
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
name: "Publish Helm Chart - fhir"
3+
4+
on:
5+
push:
6+
branches:
7+
- main
8+
paths:
9+
- "helm/fhir/**"
10+
workflow_dispatch:
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
publish-fhir:
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
packages: write
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Helm
27+
uses: azure/setup-helm@v4
28+
with:
29+
version: "3.14.0"
30+
31+
- name: Login to GitHub Container Registry
32+
uses: docker/login-action@v3
33+
with:
34+
registry: ghcr.io
35+
username: ${{ github.actor }}
36+
password: ${{ secrets.GITHUB_TOKEN }}
37+
38+
- name: Package and push helm-fhir chart
39+
run: |
40+
# Package helm-fhir
41+
helm package helm/fhir -d .helm-packages
42+
43+
# Push to GHCR
44+
helm push .helm-packages/helm-fhir-*.tgz oci://ghcr.io/${{ github.repository_owner }}
45+
46+
- name: Output published chart
47+
run: |
48+
FHIR_VERSION=$(grep "^version:" helm/fhir/Chart.yaml | awk '{print $2}')
49+
50+
echo "Published Helm chart:"
51+
echo " - oci://ghcr.io/${{ github.repository_owner }}/helm-fhir:$FHIR_VERSION"
52+
echo ""
53+
echo "Install with:"
54+
echo " helm install my-fhir oci://ghcr.io/${{ github.repository_owner }}/helm-fhir --version $FHIR_VERSION"
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
name: "Publish Helm Chart - nuts-knooppunt"
3+
4+
on:
5+
push:
6+
tags:
7+
- "v*"
8+
workflow_dispatch:
9+
10+
# cancel build action if superseded by new commit on same branch (not needed for tag builds, leaving it in when it also builds on branches)
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
publish-knooppunt:
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
20+
packages: write
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
25+
- name: Set up Helm
26+
uses: azure/setup-helm@v4
27+
with:
28+
version: "3.14.0"
29+
30+
- name: Login to GitHub Container Registry
31+
uses: docker/login-action@v3
32+
with:
33+
registry: ghcr.io
34+
username: ${{ github.actor }}
35+
password: ${{ secrets.GITHUB_TOKEN }}
36+
37+
- name: Extract version from tag
38+
id: version
39+
run: |
40+
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
41+
VERSION=${GITHUB_REF#refs/tags/v}
42+
else
43+
# For workflow_dispatch, use version from Chart.yaml
44+
VERSION=$(grep "^version:" helm/nuts-knooppunt/Chart.yaml | awk '{print $2}')
45+
fi
46+
echo "version=$VERSION" >> $GITHUB_OUTPUT
47+
echo "Extracted version: $VERSION"
48+
49+
- name: Update nuts-knooppunt chart version
50+
run: |
51+
VERSION="${{ steps.version.outputs.version }}"
52+
53+
# Update nuts-knooppunt chart version/appVersion from git tag
54+
sed -i "s/^version:.*/version: $VERSION/" helm/nuts-knooppunt/Chart.yaml
55+
sed -i "s/^appVersion:.*/appVersion: \"$VERSION\"/" helm/nuts-knooppunt/Chart.yaml
56+
57+
echo "Updated nuts-knooppunt chart to version $VERSION"
58+
59+
- name: Update chart dependencies
60+
run: |
61+
cd helm/nuts-knooppunt
62+
# Pull dependencies (helm-fhir, helm-pep, nuts-node-chart) from their registries
63+
helm dependency update
64+
65+
- name: Package and push nuts-knooppunt chart
66+
run: |
67+
# Package nuts-knooppunt (with resolved dependencies)
68+
helm package helm/nuts-knooppunt -d .helm-packages
69+
70+
# Push to GHCR
71+
helm push .helm-packages/helm-nuts-knooppunt-*.tgz oci://ghcr.io/${{ github.repository_owner }}
72+
73+
- name: Output published chart
74+
run: |
75+
VERSION="${{ steps.version.outputs.version }}"
76+
77+
echo "Published Helm chart:"
78+
echo " - oci://ghcr.io/${{ github.repository_owner }}/helm-nuts-knooppunt:$VERSION"
79+
echo ""
80+
echo "Install with:"
81+
echo " helm install my-knooppunt oci://ghcr.io/${{ github.repository_owner }}/helm-nuts-knooppunt --version $VERSION"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
name: "Publish Helm Chart - pep"
3+
4+
on:
5+
push:
6+
branches:
7+
- main
8+
paths:
9+
- "helm/pep/**"
10+
workflow_dispatch:
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
publish-pep:
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
packages: write
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Helm
27+
uses: azure/setup-helm@v4
28+
with:
29+
version: "3.14.0"
30+
31+
- name: Login to GitHub Container Registry
32+
uses: docker/login-action@v3
33+
with:
34+
registry: ghcr.io
35+
username: ${{ github.actor }}
36+
password: ${{ secrets.GITHUB_TOKEN }}
37+
38+
- name: Package and push helm-pep chart
39+
run: |
40+
# Package helm-pep
41+
helm package helm/pep -d .helm-packages
42+
43+
# Push to GHCR
44+
helm push .helm-packages/helm-pep-*.tgz oci://ghcr.io/${{ github.repository_owner }}
45+
46+
- name: Output published chart
47+
run: |
48+
PEP_VERSION=$(grep "^version:" helm/pep/Chart.yaml | awk '{print $2}')
49+
50+
echo "Published Helm chart:"
51+
echo " - oci://ghcr.io/${{ github.repository_owner }}/helm-pep:$PEP_VERSION"
52+
echo ""
53+
echo "Install with:"
54+
echo " helm install my-pep oci://ghcr.io/${{ github.repository_owner }}/helm-pep --version $PEP_VERSION"

helm/README.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Helm Charts
2+
3+
This directory contains Helm charts for nuts-knooppunt and its components.
4+
5+
## Available Charts
6+
7+
- `helm-nuts-knooppunt` - Main chart with fhir, pep, and nuts-node dependencies
8+
- `helm-fhir` - HAPI FHIR server (standalone)
9+
- `helm-pep` - Policy Enforcement Point (standalone)
10+
11+
## Version Management
12+
13+
Different charts have different versioning strategies:
14+
15+
- **helm-nuts-knooppunt**: Automatic versioning (set by git tag)
16+
- **helm-fhir**: Manual versioning (set in Chart.yaml)
17+
- **helm-pep**: Manual versioning (set in Chart.yaml)
18+
19+
**Why automatic for nuts-knooppunt?**
20+
21+
This chart is only published on git tags, which by definition indicate app changes. Automatically coupling chart version to git tag simplifies versioning: `helm install --version 0.2.0` always deploys app v0.2.0.
22+
23+
**Why manual for fhir/pep?**
24+
25+
These components have independent release cycles from nuts-knooppunt:
26+
- **PEP**: Reference implementation, changes infrequently
27+
- **FHIR**: Third-party HAPI server, follows HAPI release schedule
28+
29+
Following Helm best practices (Bitnami, Prometheus, etc.), chart version is managed manually and tracks chart development separately from app version. This allows:
30+
- Chart bug fixes without app version changes (0.1.0 → 0.1.1)
31+
- App upgrades with chart version bump (0.2.0 → 0.3.0 when upgrading HAPI 7.2.0 → 7.4.0)
32+
- Flexibility to release chart improvements independent of app releases
33+
34+
### Releasing nuts-knooppunt
35+
36+
The nuts-knooppunt chart version is coupled to the application version.
37+
38+
1. Go to GitHub → [Releases](https://github.com/nuts-foundation/nuts-knooppunt/releases) → "Draft a new release"
39+
2. Choose a tag (e.g., `v0.2.0`) or create a new one
40+
3. Add release title and notes describing changes
41+
4. Click "Publish release"
42+
43+
GitHub Actions automatically:
44+
- Extracts version from tag (`v0.2.0``0.2.0`)
45+
- Updates `helm/nuts-knooppunt/Chart.yaml` with `version` and `appVersion`
46+
- Pulls dependencies (helm-fhir, helm-pep, nuts-node-chart) from their registries
47+
- Packages and publishes helm-nuts-knooppunt to GHCR
48+
49+
**Note:** The workflow runs on any git tag matching `v*`.
50+
51+
**Result:** `helm install --version 0.2.0` deploys exactly application v0.2.0.
52+
53+
### Updating helm-fhir or helm-pep
54+
55+
These charts are published automatically when their directories change on the `main` branch.
56+
57+
**⚠️ CRITICAL: Always bump chart version when changing image tags or config. OCI registries are immutable - publishing the same version twice overwrites the existing chart.**
58+
59+
**Semantic versioning guide:**
60+
- **Patch (0.1.0 → 0.1.1)**: Chart bug fixes, config tweaks, same app version
61+
- **Minor (0.1.0 → 0.2.0)**: New app version, backwards compatible
62+
- **Major (0.1.0 → 1.0.0)**: Breaking chart changes (renamed values, removed features)
63+
64+
**Example: Upgrading HAPI FHIR**
65+
66+
1. Update `helm/fhir/Chart.yaml`:
67+
```yaml
68+
version: 0.2.0 # Bump minor (new HAPI version)
69+
appVersion: "7.4.0" # New HAPI version
70+
```
71+
72+
2. Update `helm/fhir/values.yaml`:
73+
```yaml
74+
image:
75+
tag: v7.4.0 # New HAPI FHIR image
76+
```
77+
78+
3. Update `helm/nuts-knooppunt/Chart.yaml` dependency:
79+
```yaml
80+
dependencies:
81+
- name: helm-fhir
82+
version: "0.2.0" # Reference new chart version
83+
```
84+
85+
4. Create PR, merge to `main` → workflow automatically publishes helm-fhir:0.2.0
86+
87+
5. Create new nuts-knooppunt release (e.g., `v0.2.1`) to include the new FHIR version
88+
89+
**Example: Chart config fix (no HAPI upgrade)**
90+
91+
1. Update `helm/fhir/Chart.yaml`:
92+
```yaml
93+
version: 0.1.1 # Bump patch (config fix only)
94+
appVersion: "7.2.0" # Same HAPI version
95+
```
96+
97+
2. Fix config in templates or values.yaml
98+
99+
3. Merge to `main` → workflow publishes helm-fhir:0.1.1
100+
101+
**Same process for helm-pep**: Always bump chart version when changing anything.
102+
103+
## Published Charts
104+
105+
Charts are available at GitHub Container Registry:
106+
```
107+
oci://ghcr.io/nuts-foundation/helm-nuts-knooppunt
108+
oci://ghcr.io/nuts-foundation/helm-fhir
109+
oci://ghcr.io/nuts-foundation/helm-pep
110+
```
111+
112+
## Installation
113+
114+
```bash
115+
# Install specific release version
116+
helm install my-knooppunt oci://ghcr.io/nuts-foundation/helm-nuts-knooppunt --version 0.2.0
117+
118+
# Override specific values
119+
helm install my-knooppunt oci://ghcr.io/nuts-foundation/helm-nuts-knooppunt \
120+
--version 0.2.0 \
121+
--set replicaCount=3
122+
123+
# Use custom image tag (not recommended - breaks version coupling)
124+
helm install my-knooppunt oci://ghcr.io/nuts-foundation/helm-nuts-knooppunt \
125+
--version 0.2.0 \
126+
--set image.tag=custom-build
127+
```
128+
129+
## Development
130+
131+
For local development and testing:
132+
133+
```bash
134+
# Package charts locally
135+
helm package helm/fhir -d .helm-packages
136+
helm package helm/pep -d .helm-packages
137+
helm package helm/nuts-knooppunt -d .helm-packages
138+
139+
# Install from local package
140+
helm install my-knooppunt .helm-packages/helm-nuts-knooppunt-*.tgz
141+
```

helm/fhir/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
apiVersion: v2
2-
name: fhir
2+
name: helm-fhir
33
description: A Helm chart for Kubernetes
44

55
# A chart can be either an 'application' or a 'library' chart.
@@ -21,4 +21,4 @@ version: 0.1.0
2121
# incremented each time you make changes to the application. Versions are not expected to
2222
# follow Semantic Versioning. They should reflect the version the application is using.
2323
# It is recommended to use it with quotes.
24-
appVersion: "1.16.0"
24+
appVersion: "7.2.0"

helm/nuts-knooppunt/Chart.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
dependencies:
2-
- name: fhir
3-
repository: file://../fhir
2+
- name: helm-fhir
3+
repository: oci://ghcr.io/nuts-foundation
44
version: 0.1.0
55
- name: nuts-node-chart
66
repository: https://nuts-foundation.github.io/nuts-node/
77
version: 0.0.6
8-
digest: sha256:f2f74a65adf4eb1c904fda043fcf11ad7d29803c368575c623b064be88921fb4
9-
generated: "2025-10-31T13:12:41.463572+01:00"
8+
digest: sha256:6e7f70c7d8edae18899db995121e561da1f37853cb993649a108b47e746f7ec4
9+
generated: "2025-11-03T12:13:17.673569+01:00"

helm/nuts-knooppunt/Chart.yaml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
apiVersion: v2
2-
name: nuts-knooppunt
2+
name: helm-nuts-knooppunt
33
description: Helm chart for nuts-knooppunt
44

55
# A chart can be either an 'application' or a 'library' chart.
@@ -15,19 +15,25 @@ type: application
1515
# This is the chart version. This version number should be incremented each time you make changes
1616
# to the chart and its templates, including the app version.
1717
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18-
version: 0.1.3
18+
# NOTE: Automatically set by CI/CD from git tag version.
19+
version: 0.0.0
1920

2021
# This is the version number of the application being deployed. This version number should be
2122
# incremented each time you make changes to the application. Versions are not expected to
2223
# follow Semantic Versioning. They should reflect the version the application is using.
2324
# It is recommended to use it with quotes.
24-
appVersion: "1.16.0"
25+
# NOTE: Automatically set by CI/CD from git tag version.
26+
appVersion: "0.0.0"
2527

2628
dependencies:
27-
- name: fhir
29+
- name: helm-fhir
2830
condition: fhir.enabled
29-
repository: file://../fhir
31+
repository: oci://ghcr.io/nuts-foundation
3032
version: "0.1.0"
33+
- name: helm-pep
34+
condition: pep.enabled
35+
repository: oci://ghcr.io/nuts-foundation
36+
version: "0.1.1"
3137
- name: nuts-node-chart
3238
alias: nuts
3339
condition: nuts.enabled

0 commit comments

Comments
 (0)