From b47ab6c19710192c7470d42baeba51c6946bfe4d Mon Sep 17 00:00:00 2001 From: kfox1111 Date: Fri, 21 Aug 2026 05:22:55 -0700 Subject: [PATCH] README.md version match check (#916) * README.md version match check Signed-off-by: Kevin Fox * Fix existing version issues Signed-off-by: Kevin Fox * Fix existing version issues Signed-off-by: Kevin Fox --------- Signed-off-by: Kevin Fox --- .github/scripts/check-readme-versions.sh | 114 ++++++++++++++++++++ .github/workflows/helm-chart-ci-ignore.yaml | 1 + .github/workflows/helm-chart-ci.yaml | 17 +++ Makefile | 5 + charts/spire-crds/README.md | 2 +- charts/spire-ha-agent/README.md | 2 +- charts/spire-nested/README.md | 2 +- charts/spire/Chart.yaml | 2 +- charts/spire/README.md | 2 +- 9 files changed, 142 insertions(+), 5 deletions(-) create mode 100755 .github/scripts/check-readme-versions.sh diff --git a/.github/scripts/check-readme-versions.sh b/.github/scripts/check-readme-versions.sh new file mode 100755 index 0000000..5fe195c --- /dev/null +++ b/.github/scripts/check-readme-versions.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash + +# Verify that the shields.io version badges in each top-level chart README +# agree with the version and appVersion declared in the sibling Chart.yaml. +# Nothing regenerates those badges, so they drift silently as charts are bumped. +# +# READMEs without a Version badge (library charts, hand written docs) are +# skipped. A leading 'v' is ignored when comparing, so 'v0.3.0' matches '0.3.0'. + +set -euo pipefail + +SCRIPT="$(readlink -f "$0")" +SCRIPTPATH="$(dirname "${SCRIPT}")" +REPO_ROOT="$(dirname "${SCRIPTPATH}")/.." + +function print_problem { + echo >&2 " ❌ ${*}" +} + +function require_command { + command -v "$1" >/dev/null 2>&1 || { + print_problem "$2" + exit 1 + } +} + +# Print the value of a shields.io badge as " ", or nothing +# at all when the badge is absent. Each version is spelled twice in the badge +# markup, and both spellings need checking. +function badge_values { + local readme="$1" + local name="$2" + local badge alt url + + badge="$(grep -o "!\[${name}: [^]]*\](https://img.shields.io/badge/${name}-[^)]*)" "${readme}" | head -1 || true)" + if [ -z "${badge}" ]; then + return 0 + fi + + alt="$(printf '%s' "${badge}" | sed "s#^!\[${name}: \([^]]*\)\].*#\1#")" + # shields.io escapes a literal dash in the value as '--' + url="$(printf '%s' "${badge}" | sed "s#.*/badge/${name}-\(.*\)-informational.*#\1#; s#--#-#g")" + + printf '%s %s' "${alt}" "${url}" +} + +# Compare two versions, ignoring a single leading 'v' on either side. +function versions_match { + [ "${1#v}" = "${2#v}" ] +} + +require_command yq 'yq is required to run this script' + +problems=0 + +for chart_yaml in "${REPO_ROOT}"/charts/*/Chart.yaml; do + [ -f "${chart_yaml}" ] || continue + + chart_dir="$(dirname "${chart_yaml}")" + readme="${chart_dir}/README.md" + label="charts/$(basename "${chart_dir}")/README.md" + + [ -f "${readme}" ] || continue + + version_badge="$(badge_values "${readme}" Version)" + if [ -z "${version_badge}" ]; then + # No version badges in this README, nothing to keep in sync. + continue + fi + + chart_version="$(yq e '.version // ""' "${chart_yaml}")" + chart_app_version="$(yq e '.appVersion // ""' "${chart_yaml}")" + + version_alt="${version_badge%% *}" + version_url="${version_badge##* }" + + if ! versions_match "${version_alt}" "${chart_version}"; then + print_problem "${label}: Version badge ${version_alt} does not match Chart.yaml version ${chart_version}" + problems=$((problems + 1)) + fi + if [ "${version_url}" != "${version_alt}" ]; then + print_problem "${label}: Version badge text (${version_alt}) and image URL (${version_url}) disagree" + problems=$((problems + 1)) + fi + + app_badge="$(badge_values "${readme}" AppVersion)" + if [ -z "${app_badge}" ]; then + if [ -n "${chart_app_version}" ]; then + print_problem "${label}: has a Version badge but no AppVersion badge, while Chart.yaml declares appVersion ${chart_app_version}" + problems=$((problems + 1)) + fi + continue + fi + + app_alt="${app_badge%% *}" + app_url="${app_badge##* }" + + if [ -z "${chart_app_version}" ]; then + print_problem "${label}: AppVersion badge is ${app_alt} but Chart.yaml declares no appVersion" + problems=$((problems + 1)) + elif ! versions_match "${app_alt}" "${chart_app_version}"; then + print_problem "${label}: AppVersion badge ${app_alt} does not match Chart.yaml appVersion ${chart_app_version}" + problems=$((problems + 1)) + fi + if [ "${app_url}" != "${app_alt}" ]; then + print_problem "${label}: AppVersion badge text (${app_alt}) and image URL (${app_url}) disagree" + problems=$((problems + 1)) + fi +done + +if [ "${problems}" -ne 0 ]; then + print_problem "${problems} README version badge problem(s) found. Update the badges to match Chart.yaml." + exit 1 +fi diff --git a/.github/workflows/helm-chart-ci-ignore.yaml b/.github/workflows/helm-chart-ci-ignore.yaml index 470c2da..0bf2124 100644 --- a/.github/workflows/helm-chart-ci-ignore.yaml +++ b/.github/workflows/helm-chart-ci-ignore.yaml @@ -10,6 +10,7 @@ on: - '.github/tests/**/*.yaml' - '.github/tests/**/*.sh' - '.github/tests/**/*.json' + - '.github/scripts/check-readme-versions.sh' - 'examples/**/*.yaml' - 'helm-docs.sh' diff --git a/.github/workflows/helm-chart-ci.yaml b/.github/workflows/helm-chart-ci.yaml index 083939d..ec7b9b3 100644 --- a/.github/workflows/helm-chart-ci.yaml +++ b/.github/workflows/helm-chart-ci.yaml @@ -16,6 +16,7 @@ on: - '.github/tests/**/*.yaml' - '.github/tests/**/*.sh' - '.github/tests/**/*.json' + - '.github/scripts/check-readme-versions.sh' - 'examples/**/*.yaml' - 'examples/**/*.sh' - 'tests/**/*' @@ -42,6 +43,22 @@ jobs: - name: Verify Docs updated run: ./helm-docs.sh + - name: Verify README version badges + run: | + set +e + .github/scripts/check-readme-versions.sh 2>/tmp/badge-findings + res=$? + if [ $res -ne 0 ]; then + { + echo "## README version badges" + echo + echo ":x: These chart READMEs have version badges that disagree with their Chart.yaml. Please fix." + echo + cat /tmp/badge-findings + } >> "$GITHUB_STEP_SUMMARY" + exit 1 + fi + - name: Verify Spire appVersion run: | set +e diff --git a/Makefile b/Makefile index e3d7506..c8b0937 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,11 @@ lint-release: ## Lint the charts using chart-testing for release @echo Linting charts… @ct lint --config ct.yaml --target-branch $(TARGET_BRANCH) +.PHONY: check-readme-versions +check-readme-versions: ## Verify chart README version badges match Chart.yaml + @echo Checking README version badges… + @.github/scripts/check-readme-versions.sh + ##@ Testing: (ensure to run on dedicated test cluster) .PHONY: clean-test-leftovers diff --git a/charts/spire-crds/README.md b/charts/spire-crds/README.md index 63134e1..c92c731 100644 --- a/charts/spire-crds/README.md +++ b/charts/spire-crds/README.md @@ -1,6 +1,6 @@ # spire-crds -![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.7.2](https://img.shields.io/badge/AppVersion-1.7.2-informational?style=flat-square) +![Version: 0.6.0](https://img.shields.io/badge/Version-0.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.0.1](https://img.shields.io/badge/AppVersion-0.0.1-informational?style=flat-square) A Helm chart to install the SPIRE CRDS. diff --git a/charts/spire-ha-agent/README.md b/charts/spire-ha-agent/README.md index 0130833..2c08b19 100644 --- a/charts/spire-ha-agent/README.md +++ b/charts/spire-ha-agent/README.md @@ -1,6 +1,6 @@ # spire-ha-agent -![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.7.2](https://img.shields.io/badge/AppVersion-1.7.2-informational?style=flat-square) +![Version: 0.3.0](https://img.shields.io/badge/Version-0.3.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.3.0](https://img.shields.io/badge/AppVersion-0.3.0-informational?style=flat-square) A Helm chart to install the SPIRE HA agent. diff --git a/charts/spire-nested/README.md b/charts/spire-nested/README.md index de38714..b0d1a3d 100644 --- a/charts/spire-nested/README.md +++ b/charts/spire-nested/README.md @@ -1,6 +1,6 @@ # spire -![Version: 0.28.5](https://img.shields.io/badge/Version-0.28.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.15.2](https://img.shields.io/badge/AppVersion-1.15.2-informational?style=flat-square) +![Version: 0.30.0](https://img.shields.io/badge/Version-0.30.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.15.2](https://img.shields.io/badge/AppVersion-1.15.2-informational?style=flat-square) [![Development Phase](https://github.com/spiffe/spiffe/blob/main/.img/maturity/dev.svg)](https://github.com/spiffe/spiffe/blob/main/MATURITY.md#development) A Helm chart for deploying the complete Spire stack including: spire-server, spire-agent, spiffe-csi-driver, spiffe-oidc-discovery-provider and spire-controller-manager. diff --git a/charts/spire/Chart.yaml b/charts/spire/Chart.yaml index 30c3878..5040e65 100644 --- a/charts/spire/Chart.yaml +++ b/charts/spire/Chart.yaml @@ -5,7 +5,7 @@ description: > type: application version: 0.30.0 -appVersion: "1.14.5" +appVersion: "1.15.2" keywords: ["spiffe", "spire", "spire-server", "spire-agent", "oidc", "spire-controller-manager"] home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire sources: diff --git a/charts/spire/README.md b/charts/spire/README.md index 83a0a53..72a7646 100644 --- a/charts/spire/README.md +++ b/charts/spire/README.md @@ -1,6 +1,6 @@ # spire -![Version: 0.28.5](https://img.shields.io/badge/Version-0.28.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.15.2](https://img.shields.io/badge/AppVersion-1.15.2-informational?style=flat-square) +![Version: 0.30.0](https://img.shields.io/badge/Version-0.30.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.15.2](https://img.shields.io/badge/AppVersion-1.15.2-informational?style=flat-square) [![Development Phase](https://github.com/spiffe/spiffe/blob/main/.img/maturity/dev.svg)](https://github.com/spiffe/spiffe/blob/main/MATURITY.md#development) A Helm chart for deploying the complete Spire stack including: spire-server, spire-agent, spiffe-csi-driver, spiffe-oidc-discovery-provider and spire-controller-manager.