From 7a0cbe5cb892194ca4e247437881c5ad837ea230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20=C5=9Eafak?= <3928300+esafak@users.noreply.github.com> Date: Wed, 26 Aug 2026 10:49:46 -0400 Subject: [PATCH 1/4] Fix Helm chart version synchronization --- .github/workflows/helm-chart.yml | 19 +++++++++++-------- charts/garnet/Chart.yaml | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml index 7b40891ae9f..a346838a4c0 100644 --- a/.github/workflows/helm-chart.yml +++ b/.github/workflows/helm-chart.yml @@ -6,7 +6,8 @@ on: branches: - main paths: - - 'charts/*/Chart.yaml' + - 'charts/**' + - 'Version.props' permissions: contents: write @@ -48,10 +49,16 @@ jobs: tar -xvf "${FILENAME}" sudo mv helm-docs /usr/local/bin - - name: Set helm chart appVersion from Version.props + - name: Verify helm chart version matches Version.props run: | - export VERSION_PROPS=$(awk -F'[<>]' '/VersionPrefix/{print $3}' Version.props | tr -d '\n') - sed -i -e 's#Version.props#"'${VERSION_PROPS}'"#g' charts/garnet/Chart.yaml + VERSION_PROPS=$(awk -F'[<>]' '//{print $3}' Version.props | tr -d '\n') + CHART_VERSION=$(awk '$1 == "version:" {print $2}' charts/garnet/Chart.yaml) + CHART_APP_VERSION=$(awk '$1 == "appVersion:" {print $2}' charts/garnet/Chart.yaml) + + if [[ "${CHART_VERSION}" != "${VERSION_PROPS}" || "${CHART_APP_VERSION}" != "${VERSION_PROPS}" ]]; then + echo "Chart version (${CHART_VERSION}) and appVersion (${CHART_APP_VERSION}) must match Version.props (${VERSION_PROPS})" + exit 1 + fi - name: Helm lint, helm-docs and helm package run: | @@ -65,10 +72,6 @@ jobs: helm package "${chart}" --dependency-update --destination .cr-release-packages done - - name: Discard changes on the charts/garnet/Chart.yaml file - run: | - git checkout -- charts/garnet/Chart.yaml - - name: Commit and Push to Branch (no PR) run: | git config user.name "github-actions[bot]" diff --git a/charts/garnet/Chart.yaml b/charts/garnet/Chart.yaml index 75da92de212..57cb2bcd969 100644 --- a/charts/garnet/Chart.yaml +++ b/charts/garnet/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: garnet description: A Helm chart for Microsoft Garnet type: application -version: 0.2.2 -appVersion: Version.props +version: 2.1.5 +appVersion: 2.1.5 home: https://github.com/microsoft/garnet icon: https://avatars.githubusercontent.com/u/6154722?s=200&v=4 From 5e67d73e0d1a779acc5d500da2455c6e77b308a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20=C5=9Eafak?= <3928300+esafak@users.noreply.github.com> Date: Wed, 26 Aug 2026 10:57:14 -0400 Subject: [PATCH 2/4] Use dynamic release badge in Helm chart docs --- charts/garnet/README.md | 2 +- charts/garnet/README.md.gotmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/garnet/README.md b/charts/garnet/README.md index a418118cff5..55782cdf1ac 100644 --- a/charts/garnet/README.md +++ b/charts/garnet/README.md @@ -1,6 +1,6 @@ # garnet -![Version: 0.2.2](https://img.shields.io/badge/Version-0.2.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.0.65](https://img.shields.io/badge/AppVersion-1.0.65-informational?style=flat-square) +[![Garnet release](https://img.shields.io/github/v/release/microsoft/garnet?sort=semver)](https://github.com/microsoft/garnet/releases/latest) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) A Helm chart for Microsoft Garnet diff --git a/charts/garnet/README.md.gotmpl b/charts/garnet/README.md.gotmpl index db5f1153da9..af87f963314 100644 --- a/charts/garnet/README.md.gotmpl +++ b/charts/garnet/README.md.gotmpl @@ -1,7 +1,7 @@ {{ template "chart.header" . }} {{ template "chart.deprecationWarning" . }} -{{ template "chart.badgesSection" . }} +[![Garnet release](https://img.shields.io/github/v/release/microsoft/garnet?sort=semver)](https://github.com/microsoft/garnet/releases/latest) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) {{ template "chart.description" . }} From c4cc01a17772738002fef600536f3ff7171c0d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20=C5=9Eafak?= <3928300+esafak@users.noreply.github.com> Date: Wed, 26 Aug 2026 11:00:39 -0400 Subject: [PATCH 3/4] Regenerate Helm chart README metadata --- charts/garnet/README.md | 2 +- charts/garnet/README.md.gotmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/garnet/README.md b/charts/garnet/README.md index 55782cdf1ac..d7202a9856b 100644 --- a/charts/garnet/README.md +++ b/charts/garnet/README.md @@ -1,6 +1,6 @@ # garnet -[![Garnet release](https://img.shields.io/github/v/release/microsoft/garnet?sort=semver)](https://github.com/microsoft/garnet/releases/latest) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![Version: 2.1.5](https://img.shields.io/badge/Version-2.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.1.5](https://img.shields.io/badge/AppVersion-2.1.5-informational?style=flat-square) A Helm chart for Microsoft Garnet diff --git a/charts/garnet/README.md.gotmpl b/charts/garnet/README.md.gotmpl index af87f963314..db5f1153da9 100644 --- a/charts/garnet/README.md.gotmpl +++ b/charts/garnet/README.md.gotmpl @@ -1,7 +1,7 @@ {{ template "chart.header" . }} {{ template "chart.deprecationWarning" . }} -[![Garnet release](https://img.shields.io/github/v/release/microsoft/garnet?sort=semver)](https://github.com/microsoft/garnet/releases/latest) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +{{ template "chart.badgesSection" . }} {{ template "chart.description" . }} From b9293703ea8f2500c366a0fcc790268195de7c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20=C5=9Eafak?= <3928300+esafak@users.noreply.github.com> Date: Sat, 29 Aug 2026 12:04:36 -0400 Subject: [PATCH 4/4] Fix independent Helm chart versioning --- .github/workflows/helm-chart-check.yml | 114 ++++++++++++++++++ .github/workflows/helm-chart-release-sync.yml | 91 ++++++++++++++ .github/workflows/helm-chart.yml | 44 ++----- charts/garnet/Chart.yaml | 2 +- charts/garnet/README.md | 16 ++- charts/garnet/README.md.gotmpl | 6 + 6 files changed, 237 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/helm-chart-check.yml create mode 100644 .github/workflows/helm-chart-release-sync.yml diff --git a/.github/workflows/helm-chart-check.yml b/.github/workflows/helm-chart-check.yml new file mode 100644 index 00000000000..cd3597ddd7f --- /dev/null +++ b/.github/workflows/helm-chart-check.yml @@ -0,0 +1,114 @@ +name: Check Garnet Helm Chart + +on: + pull_request: + branches: + - main + paths: + - 'charts/**' + - 'Version.props' + +permissions: + contents: read + +jobs: + helm-chart-check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + + - name: Install helm + uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.0 + + - name: Install helm-docs + env: + HELM_DOCS_VERSION: "1.14.2" + HELM_DOCS_SHA256: "a8cf72ada34fad93285ba2a452b38bdc5bd52cc9a571236244ec31022928d6cc" + run: | + set -euo pipefail + cd /tmp + FILENAME="helm-docs_${HELM_DOCS_VERSION}_Linux_x86_64.tar.gz" + wget "https://github.com/norwoodj/helm-docs/releases/download/v${HELM_DOCS_VERSION}/${FILENAME}" + echo "${HELM_DOCS_SHA256} ${FILENAME}" | sha256sum -c - + tar -xvf "${FILENAME}" + sudo mv helm-docs /usr/local/bin + + - name: Verify chart version was bumped + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + set -euo pipefail + changed_files=$(git diff --name-only "${BASE_SHA}"...HEAD) + chart_source_changed=false + while IFS= read -r file; do + case "${file}" in + charts/garnet/Chart.yaml|charts/garnet/values*|charts/garnet/README.md.gotmpl|charts/garnet/templates/*) + chart_source_changed=true + ;; + esac + done <<< "${changed_files}" + + if [[ "${chart_source_changed}" != true ]]; then + exit 0 + fi + + base_chart_version=$(git show "${BASE_SHA}:charts/garnet/Chart.yaml" | awk '$1 == "version:" {print $2}') + chart_version=$(awk '$1 == "version:" {print $2}' charts/garnet/Chart.yaml) + if [[ -z "${base_chart_version}" || -z "${chart_version}" ]]; then + echo "Unable to read chart version" + exit 1 + fi + + python3 - "${base_chart_version}" "${chart_version}" <<'PY' + import re + import sys + + semver = re.compile(r"^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$") + + def key(value): + match = semver.fullmatch(value) + if not match: + raise SystemExit(f"Invalid chart semver: {value}") + return tuple(int(part) for part in match.groups()[:3]) + + base, current = sys.argv[1:] + if key(current) <= key(base): + raise SystemExit(f"Chart version must increase: {base} -> {current}") + PY + + - name: Verify application version + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + set -euo pipefail + changed_files=$(git diff --name-only "${BASE_SHA}"...HEAD) + chart_source_changed=false + while IFS= read -r file; do + case "${file}" in + charts/garnet/Chart.yaml|charts/garnet/values*|charts/garnet/README.md.gotmpl|charts/garnet/templates/*) + chart_source_changed=true + ;; + esac + done <<< "${changed_files}" + + if [[ "${chart_source_changed}" != true ]]; then + echo "No chart source changes; application version check is deferred to release synchronization" + exit 0 + fi + + version_props=$(awk -F'[<>]' '//{print $3}' Version.props | tr -d '\n') + chart_app_version=$(awk '$1 == "appVersion:" {print $2}' charts/garnet/Chart.yaml) + if [[ "${chart_app_version}" != "${version_props}" ]]; then + echo "Chart appVersion (${chart_app_version}) must match Version.props (${version_props})" + exit 1 + fi + + - name: Lint chart and verify generated README + run: | + set -euo pipefail + helm lint charts/garnet + helm-docs --document-dependency-values --chart-search-root charts/garnet + git diff --exit-code -- charts/garnet/README.md diff --git a/.github/workflows/helm-chart-release-sync.yml b/.github/workflows/helm-chart-release-sync.yml new file mode 100644 index 00000000000..b0168e2e842 --- /dev/null +++ b/.github/workflows/helm-chart-release-sync.yml @@ -0,0 +1,91 @@ +name: Sync Garnet Helm Chart Release + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - 'Version.props' + +permissions: + contents: write + pull-requests: write + +concurrency: + group: helm-chart-release-sync + cancel-in-progress: true + +jobs: + release-sync: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + + - name: Install helm-docs + env: + HELM_DOCS_VERSION: "1.14.2" + HELM_DOCS_SHA256: "a8cf72ada34fad93285ba2a452b38bdc5bd52cc9a571236244ec31022928d6cc" + run: | + set -euo pipefail + cd /tmp + FILENAME="helm-docs_${HELM_DOCS_VERSION}_Linux_x86_64.tar.gz" + wget "https://github.com/norwoodj/helm-docs/releases/download/v${HELM_DOCS_VERSION}/${FILENAME}" + echo "${HELM_DOCS_SHA256} ${FILENAME}" | sha256sum -c - + tar -xvf "${FILENAME}" + sudo mv helm-docs /usr/local/bin + + - name: Install helm + uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.0 + + - name: Update chart metadata and documentation + run: | + set -euo pipefail + version_props=$(awk -F'[<>]' '//{print $3}' Version.props | tr -d '\n') + chart_app_version=$(awk '$1 == "appVersion:" {print $2}' charts/garnet/Chart.yaml) + + if [[ "${chart_app_version}" == "${version_props}" ]]; then + echo "Chart already targets ${version_props}; nothing to synchronize" + exit 0 + fi + + python3 - "${version_props}" <<'PY' + import re + import sys + from pathlib import Path + + path = Path("charts/garnet/Chart.yaml") + text = path.read_text() + match = re.search(r"(?m)^version:\s*(\d+)\.(\d+)\.(\d+)(?:-[^\s]+)?\s*$", text) + if not match: + raise SystemExit("Chart.yaml does not contain a supported stable chart version") + + major, minor, patch = (int(part) for part in match.groups()) + chart_version = f"{major}.{minor}.{patch + 1}" + text = re.sub(r"(?m)^version:\s*.*$", f"version: {chart_version}", text, count=1) + text = re.sub(r"(?m)^appVersion:\s*.*$", f"appVersion: {sys.argv[1]}", text, count=1) + path.write_text(text) + print(f"Updated chart to {chart_version} / {sys.argv[1]}") + PY + + helm lint charts/garnet + helm-docs --document-dependency-values --chart-search-root charts/garnet + + - name: Create or update release synchronization PR + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.8 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: automation/helm-chart-release-sync + delete-branch: true + title: '[helm-chart] Sync chart with Garnet release' + commit-message: '[helm-chart] Sync chart with Garnet release' + body: | + Updates the Helm chart version, application version, and generated README for the latest Garnet release. + + This PR is generated automatically from `Version.props`. + add-paths: | + charts/garnet/Chart.yaml + charts/garnet/README.md diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml index a346838a4c0..52bbc468a1a 100644 --- a/.github/workflows/helm-chart.yml +++ b/.github/workflows/helm-chart.yml @@ -6,14 +6,15 @@ on: branches: - main paths: - - 'charts/**' - - 'Version.props' + - 'charts/**/Chart.yaml' + - 'charts/**/templates/**' + - 'charts/**/values*' + - 'charts/**/README.md.gotmpl' permissions: - contents: write + contents: read packages: write - pull-requests: write - + jobs: helm-chart: runs-on: ubuntu-latest @@ -23,11 +24,6 @@ jobs: with: fetch-depth: 0 - - name: Configure git - run: | - git config user.name "${GITHUB_ACTOR}" - git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" - - name: Install helm uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.0 for security reasons we have pinned the tag (commit SHA) for 3rd party env: @@ -49,40 +45,26 @@ jobs: tar -xvf "${FILENAME}" sudo mv helm-docs /usr/local/bin - - name: Verify helm chart version matches Version.props + - name: Verify chart metadata run: | + set -euo pipefail VERSION_PROPS=$(awk -F'[<>]' '//{print $3}' Version.props | tr -d '\n') - CHART_VERSION=$(awk '$1 == "version:" {print $2}' charts/garnet/Chart.yaml) CHART_APP_VERSION=$(awk '$1 == "appVersion:" {print $2}' charts/garnet/Chart.yaml) - if [[ "${CHART_VERSION}" != "${VERSION_PROPS}" || "${CHART_APP_VERSION}" != "${VERSION_PROPS}" ]]; then - echo "Chart version (${CHART_VERSION}) and appVersion (${CHART_APP_VERSION}) must match Version.props (${VERSION_PROPS})" + if [[ "${CHART_APP_VERSION}" != "${VERSION_PROPS}" ]]; then + echo "Chart appVersion (${CHART_APP_VERSION}) must match Version.props (${VERSION_PROPS})" exit 1 fi - name: Helm lint, helm-docs and helm package run: | + set -euo pipefail mkdir .cr-release-packages - for chart in $(find charts -mindepth 1 -maxdepth 1 -type d); do - if [ -z "${chart:-}" ]; then - break - fi + while IFS= read -r -d '' chart; do helm lint "${chart}" helm-docs --document-dependency-values --chart-search-root "${chart}" helm package "${chart}" --dependency-update --destination .cr-release-packages - done - - - name: Commit and Push to Branch (no PR) - run: | - git config user.name "github-actions[bot]" - git config user.email "${{ github.actor }}@users.noreply.github.com" - # Create or switch to the branch - git checkout -B helm-docs-gen - # Add and commit changes - git add charts/garnet/README.md - git commit -m "[helm-chart] Update charts/garnet/README.md by helm-docs" || echo "No changes to commit" - # Push to remote using GITHUB_TOKEN - git push -f origin helm-docs-gen + done < <(find charts -mindepth 1 -maxdepth 1 -type d -print0) - name: Login to GHCR env: diff --git a/charts/garnet/Chart.yaml b/charts/garnet/Chart.yaml index 57cb2bcd969..e48d110d7dc 100644 --- a/charts/garnet/Chart.yaml +++ b/charts/garnet/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: garnet description: A Helm chart for Microsoft Garnet type: application -version: 2.1.5 +version: 0.2.3 appVersion: 2.1.5 home: https://github.com/microsoft/garnet icon: https://avatars.githubusercontent.com/u/6154722?s=200&v=4 diff --git a/charts/garnet/README.md b/charts/garnet/README.md index d7202a9856b..1a920610ff2 100644 --- a/charts/garnet/README.md +++ b/charts/garnet/README.md @@ -1,6 +1,12 @@ # garnet -![Version: 2.1.5](https://img.shields.io/badge/Version-2.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.1.5](https://img.shields.io/badge/AppVersion-2.1.5-informational?style=flat-square) +![Version: 0.2.3](https://img.shields.io/badge/Version-0.2.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.1.5](https://img.shields.io/badge/AppVersion-2.1.5-informational?style=flat-square) + +## Versioning + +The Helm chart version and Garnet application version are independent. Chart +changes require a chart version bump; Garnet releases receive a chart patch +bump so the published chart points to the new application image by default. A Helm chart for Microsoft Garnet @@ -35,9 +41,7 @@ helm delete garnet | config.existingSecret | string | `""` | Garnet secret (if you want to use an existing secret). This secret must contains a key called 'garnet.conf'. | | config.garnetConf | string | `""` | The garnet.conf data content. | | containers.args | list | `[]` | Containers args | -| containers.livenessProbe | object | `{}` | Containers livenessProbe | | containers.port | int | `6379` | Containers port | -| containers.readinessProbe | object | `{}` | Containers livenessProbe | | dnsConfig | object | `{}` | DNS config | | dnsPolicy | string | `"ClusterFirst"` | DNS policy | | extraVolumeMounts | list | `[]` | Extra Volume Mounts | @@ -49,21 +53,25 @@ helm delete garnet | image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. | | imagePullSecrets | list | `[]` | Image pull secrets | | initContainers | list | `[]` | Init containers | +| livenessProbe | object | `{}` | Containers livenessProbe | | nameOverride | string | `""` | Chart name override | | nodeSelector | object | `{}` | Node Selector labels | | persistence.enabled | bool | `false` | persistence enabled | | persistence.storageDir | string | `""` | The Storage directory for tiered records (hybrid log), if storage tiering (--storage-tier) is enabled. Default: "/data" | | podAnnotations | object | `{}` | Pod annotations | | podSecurityContext | object | `{}` | Pod Security Context | +| readinessProbe | object | `{}` | Containers livenessProbe | | resources | object | `{}` | Resources | | securityContext | object | `{}` | Security Context | | service.annotations | object | `{}` | Service annotations | +| service.ipFamilies | list | `["IPv4"]` | Service ipFamilies | +| service.ipFamilyPolicy | string | `"SingleStack"` | Service ipFamilyPolicy SingleStack|PreferDualStack|RequireDualStack | | service.port | int | `6379` | Service port | | service.type | string | `"ClusterIP"` | Service type | | serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.automount | bool | `false` | Automatically mount the service account token | | serviceAccount.create | bool | `false` | Specifies whether a service account should be created | | serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | -| serviceAccount.token | bool | `false` | Creates the token object | | statefulSet.annotations | object | `{}` | StatefulSet annotations | | statefulSet.replicas | int | `1` | StatefulSet replicas | | statefulSet.revisionHistoryLimit | int | `1` | StatefulSet revisionHistoryLimit | diff --git a/charts/garnet/README.md.gotmpl b/charts/garnet/README.md.gotmpl index db5f1153da9..97e7b68c607 100644 --- a/charts/garnet/README.md.gotmpl +++ b/charts/garnet/README.md.gotmpl @@ -3,6 +3,12 @@ {{ template "chart.badgesSection" . }} +## Versioning + +The Helm chart version and Garnet application version are independent. Chart +changes require a chart version bump; Garnet releases receive a chart patch +bump so the published chart points to the new application image by default. + {{ template "chart.description" . }} {{ template "chart.homepageLine" . }}