From 52c6aadcf02d48da1961926b9a47c510a03a4cda Mon Sep 17 00:00:00 2001 From: davrad Date: Wed, 15 Jul 2026 15:02:09 +0200 Subject: [PATCH 1/9] ci: add image scanning to ci --- .github/workflows/pr-checks.yaml | 51 +++++++++++++++++++ .github/workflows/release.yaml | 46 +++++++++++++++++ .scripts/image-version.sh | 84 ++++++++++++++++++++++++++++++++ .scripts/kubara-config-update.sh | 10 ++++ src/.goreleaser.yaml | 3 ++ 5 files changed, 194 insertions(+) create mode 100755 .scripts/image-version.sh diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml index 2e5f0880..e800965f 100644 --- a/.github/workflows/pr-checks.yaml +++ b/.github/workflows/pr-checks.yaml @@ -32,6 +32,8 @@ env: # renovate: datasource=github-releases depName=terraform-linters/tflint TFLINT_VERSION: "v0.63.1" ARTIFACT_RETENTION_DAYS: "15" + # renovate: datasource=github-releases depName=aquasecurity/trivy + TRIVY_VERSION: "v0.70.0" permissions: contents: read @@ -426,3 +428,52 @@ jobs: name: terraform-validation-${{ github.run_attempt }}-${{ github.sha }}-${{ github.run_number }} retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} path: ${{ env.REPORT_DIR }}/terraform + + + extract-images: + needs: run-kubara-init-and-generate + runs-on: ubuntu-latest + outputs: + images: ${{ steps.matrix.outputs.images }} + has_images: ${{ steps.matrix.outputs.has_images }} + defaults: + run: + shell: bash + steps: + - name: Checkout CI scripts + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + sparse-checkout: | + .scripts + .github/helm-profiles + + - name: Download generated kubara artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: kubara-generated-files-${{ github.run_attempt }}-${{ github.sha }}-${{ github.run_number }} + + - name: Verify Helm + run: helm version --short + + - name: Extract container images + run: | + mkdir -p reports + OUTPUT_FILE="$PWD/reports/images.txt" .scripts/image-version.sh + + - name: Write image summary + if: always() + run: | + [[ -f reports/images.txt ]] || exit 0 + echo "### Container Images" >> "$GITHUB_STEP_SUMMARY" + while read -r img; do + echo "- $img" >> "$GITHUB_STEP_SUMMARY" + done < reports/images.txt + + - name: Upload image list + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + if: always() + with: + name: container-images-${{ github.run_attempt }}-${{ github.sha }}-${{ github.run_number }} + retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} + path: reports/images.txt + diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7d197344..e13f4ffe 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -57,6 +57,52 @@ jobs: - name: Install go-licenses run: go install github.com/google/go-licenses/v2@3e084b0caf710f7bfead967567539214f598c0a2 #v2.0.1 + - name: Verify preinstalled Helm + run: | + set -euo pipefail + helm version --short + + - name: Run kubara generate + env: + KUBARA_PROJECT_NAME: kubara + KUBARA_PROJECT_STAGE: tst + KUBARA_DOCKERCONFIG_BASE64: "000000" + KUBARA_ARGOCD_WIZARD_ACCOUNT_PASSWORD: "000000" + KUBARA_ARGOCD_HELM_REPO_USERNAME: git + KUBARA_ARGOCD_HELM_REPO_PASSWORD: "000000" + KUBARA_ARGOCD_HELM_REPO_URL: "https://kubara.io/kubara.git" + KUBARA_ARGOCD_GIT_HTTPS_URL: "https://kubara.io/kubara.git" + KUBARA_ARGOCD_GIT_PAT_OR_PASSWORD: "000000" + KUBARA_ARGOCD_GIT_USERNAME: git + KUBARA_DNS_NAME: kubara-tst.stackit.run + KUBARA_STACKIT_PROJECT_ID: "00000000-0000-0000-0000-000000000000" + KUBARA_TERRAFORM_PROVIDER: stackit + KUBARA_CLUSTER_TYPE: hub + KUBARA_SSO_ORG: Kubara + KUBARA_SSO_TEAM: Test + KUBARA_KUBERNETES_TYPE: ske + KUBARA_KUBERNETES_VERSION: "1.35.0" + run: | + set -euo pipefail + mkdir -p /tmp/gen + (cd src && go run main.go --work-dir /tmp/gen init --prep) + .scripts/kubara-env-update.sh /tmp/gen/.env + (cd src && go run main.go --work-dir /tmp/gen init) + .scripts/kubara-config-update.sh /tmp/gen/config.yaml + (cd src && go run main.go --work-dir /tmp/gen generate) + + - name: Extract images and set goreleaser header + run: | + MANAGED=/tmp/gen/managed-service-catalog/helm \ + OUTPUT_FILE=/tmp/images.txt \ + "$GITHUB_WORKSPACE"/.scripts/image-version.sh + { + echo "IMAGE_LIST<> "$GITHUB_ENV" + + - name: Run GoReleaser if: github.event_name == 'push' uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3 diff --git a/.scripts/image-version.sh b/.scripts/image-version.sh new file mode 100755 index 00000000..b8d71559 --- /dev/null +++ b/.scripts/image-version.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + + +# pipefail that pipes break +set -euo pipefail + +export PATH="$HOME/.local/bin/:$PATH" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +MANAGED="${MANAGED:-${PWD}/platform-components/helm}" +CONFIG_FILE="${CONFIG_FILE:-config.yaml}" +CLUSTER_NAME="$(yq -r '.clusters[0].name' "$CONFIG_FILE")" +CONFIGS="${CONFIGS:-platform-configs/${CLUSTER_NAME}/helm}" +OUTPUT_FILE="${OUTPUT_FILE:-}" + +[[ -f "$CONFIG_FILE" ]] || { echo "::error::Missing $CONFIG_FILE — run 'kubara generate' first (or cd into its output)"; exit 1; } +[[ -d "$MANAGED" ]] || { echo "::error::Missing $MANAGED — run 'kubara generate' first"; exit 1; } +command -v helm >/dev/null 2>&1 || { echo "::error::helm not found on PATH"; exit 1; } +command -v yq >/dev/null 2>&1 || { echo "::error::yq not found on PATH"; exit 1; } + +KUBE_VERSION=$(yq -r '.clusters[0].terraform.kubernetesVersion' "$CONFIG_FILE") + +PROMETHEUS_STATUS="$(yq -r '.clusters[0].services."kube-prometheus-stack".status // "disabled"' "$CONFIG_FILE")" + +# helm template flags advertise the monitoring API only when +# kube-prometheus-stack is enabled, since some charts (eg. traefik) render +# ServiceMonitors guarded by a `fail` on monitoring.coreos.com/v1. +HELM_TEMPLATE_ARGS=(--kube-version "$KUBE_VERSION" --include-crds) +if [[ "$PROMETHEUS_STATUS" == enabled ]]; then + HELM_TEMPLATE_ARGS+=(--api-versions "monitoring.coreos.com/v1") +fi + + +echo "Rendering charts from $MANAGED (kube-version=$KUBE_VERSION)" >&2 + + +render_dir="$(mktemp -d)"; trap 'rm -rf "$render_dir"' EXIT +FAILED=() + +for chart_path in "$MANAGED"/*/; do + chart=$(basename "$chart_path") + [[ -f "$chart_path/Chart.yaml" ]] || continue + + # Don't render library charts + [[ "$(yq '.type // "application"' "$chart_path/Chart.yaml")" == library ]] && continue + + echo "Updating dependency for ${chart_path}" >&2 + + if ! dep_out=$(helm dependency update "$chart_path" >/dev/null 2>&1); then + echo "::error::helm dependency update failed for '$chart_path'"; echo "$dep_out" >&2 + FAILED+=("$chart:dependency-update"); continue + fi + + values_file="$CONFIGS/$chart/values.generated.yaml" + base_values=(); [[ -f "$values_file" ]] && base_values=(-f "$values_file") + + if ! helm template "${HELM_TEMPLATE_ARGS[@]}" \ + "$chart" "$chart_path" "${base_values[@]}" \ + > "$render_dir/$chart.yaml" 2> "$render_dir/$chart.err"; then + echo "::error::helm template for for '$chart':" + sed 's/^/ /' "$render_dir/$chart.err" >&2 + FAILED+=("$chart:template"); continue + fi +done + +IMAGES="$( + cat "$render_dir"/*.yaml | + grep -E '^[[:space:]]*image:' | + sed -E "s/^[[:space:]]*image:[[:space:]]*//; s/[\"']//g" | + grep -vE '[*!]' | # drop kyverno wildcard/negation entries + grep -vE '^[[:space:]]*$' | + sort -u +)" + +echo "Done Rendering!" + +[[ -n "$IMAGES" ]] || { echo "::warning::No image references found"; exit 0; } + +echo "$IMAGES" + +if [[ -n "$OUTPUT_FILE" ]]; then + echo "$IMAGES" > "$OUTPUT_FILE" + echo "::notice::Image list written to $OUTPUT_FILE" +fi diff --git a/.scripts/kubara-config-update.sh b/.scripts/kubara-config-update.sh index 90fddaa5..d7a85f8a 100755 --- a/.scripts/kubara-config-update.sh +++ b/.scripts/kubara-config-update.sh @@ -49,4 +49,14 @@ apply_yaml_if_set KUBARA_KUBERNETES_VERSION ".clusters[0].terraform.kubernetesV apply_yaml_if_set KUBARA_DNS_NAME ".clusters[0].dnsName" apply_yaml_if_set KUBARA_DNS_NAME ".clusters[0].terraform.dns.name" +# Enable every catalog service to the image/vuln report and the release header cover all charts +yq eval '(.clusters[0].services[] | .status) = "enabled"' -i "$CFG" + +# metalb, loki and velero need custom configs +yq eval '.clusters[0].services.metallb.config.publicLoadBalancerIPs = "203.0.113.10"' -i "$CFG" +yq eval '.clusters[0].services.metallb.config.loadBalancerAddressPool = ["203.0.113.0/24"]' -i "$CFG" +yq eval '.clusters[0].storage.bucketNames.chunks = "loki"' -i "$CFG" + +yq eval '.clusters[0].services.velero.config.backupStorage.s3Url = "https://bucket.example.com"' -i "$CFG" + log "✅ config.yaml updated" diff --git a/src/.goreleaser.yaml b/src/.goreleaser.yaml index b996b83a..85ae7443 100644 --- a/src/.goreleaser.yaml +++ b/src/.goreleaser.yaml @@ -13,6 +13,9 @@ release: replace_existing_artifacts: true extra_files: - glob: licenses.csv + header: | + ## Container Images + {{ .Env.IMAGE_LIST }} changelog: use: git sort: asc From 20727dd6f2d835784eb37a68a0febce5d4f19b26 Mon Sep 17 00:00:00 2001 From: davrad Date: Fri, 17 Jul 2026 12:39:36 +0200 Subject: [PATCH 2/9] ci: extract helm images --- .scripts/image-version.sh | 19 +++++++++++++++---- .../helm/velero/Chart.yaml | 13 +++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml diff --git a/.scripts/image-version.sh b/.scripts/image-version.sh index b8d71559..0471ab18 100755 --- a/.scripts/image-version.sh +++ b/.scripts/image-version.sh @@ -11,7 +11,8 @@ MANAGED="${MANAGED:-${PWD}/platform-components/helm}" CONFIG_FILE="${CONFIG_FILE:-config.yaml}" CLUSTER_NAME="$(yq -r '.clusters[0].name' "$CONFIG_FILE")" CONFIGS="${CONFIGS:-platform-configs/${CLUSTER_NAME}/helm}" -OUTPUT_FILE="${OUTPUT_FILE:-}" +IMAGE_OUTPUT_FILE="${IMAGE_OUTPUT_FILE:-}" +HELM_IMAGE_OUTPUT_FILE="${HELM_IMAGE_OUTPUT_FILE:-}" [[ -f "$CONFIG_FILE" ]] || { echo "::error::Missing $CONFIG_FILE — run 'kubara generate' first (or cd into its output)"; exit 1; } [[ -d "$MANAGED" ]] || { echo "::error::Missing $MANAGED — run 'kubara generate' first"; exit 1; } @@ -77,8 +78,18 @@ echo "Done Rendering!" [[ -n "$IMAGES" ]] || { echo "::warning::No image references found"; exit 0; } echo "$IMAGES" +echo "Extracting Helm Dependencies" +HELM_IMAGES="$(find . -name Chart.yaml -exec yq '.dependencies[] | select(.name != "template-library") | .name + ": " + .version' {} \;)" +echo "$HELM_IMAGES" -if [[ -n "$OUTPUT_FILE" ]]; then - echo "$IMAGES" > "$OUTPUT_FILE" - echo "::notice::Image list written to $OUTPUT_FILE" +[[ -n "$HELM_IMAGES" ]] || { echo "::warning::No helm image references found"; exit 0; } + +if [[ -n "$IMAGE_OUTPUT_FILE" ]]; then + echo "$IMAGES" > "$IMAGE_OUTPUT_FILE" + echo "::notice::Image list written to $IMAGE_OUTPUT_FILE" +fi + +if [[ -n "$HELM_IMAGE_OUTPUT_FILE" ]]; then + echo "$HELM_IMAGES" > "$HELM_IMAGE_OUTPUT_FILE" + echo "::notice:: Helm Image list written to $HELM_IMAGE_OUTPUT_FILE" fi diff --git a/src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml b/src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml new file mode 100644 index 00000000..6963007b --- /dev/null +++ b/src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: v2 +name: velero +description: Umbrella Chart for Velero Config +type: application +version: 0.3.0 +dependencies: + - name: velero + version: 12.1.0 + repository: https://vmware-tanzu.github.io/helm-charts + - name: template-library + repository: file://../template-library + version: 0.2.0 From ff6edcda8bae2be2809808e842861e584f5471fd Mon Sep 17 00:00:00 2001 From: davrad Date: Fri, 17 Jul 2026 13:35:58 +0200 Subject: [PATCH 3/9] fix: update reloader template reference --- .../platform-components/helm/reloader/Chart.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml diff --git a/src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml b/src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml new file mode 100644 index 00000000..25482274 --- /dev/null +++ b/src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: v2 +name: reloader +description: Umbrella Chart for reloader +type: application +version: 1.0.0 +dependencies: + - name: template-library + repository: file://../template-library + version: 0.2.0 + # https://docs.stakater.com/reloader/latest/ + - name: reloader + repository: https://stakater.github.io/stakater-charts + version: 2.2.14 From 122cebb6f05c3435920648ee99039eb0b91d0246 Mon Sep 17 00:00:00 2001 From: davrad Date: Fri, 24 Jul 2026 17:40:08 +0200 Subject: [PATCH 4/9] fix: address review feedback --- .github/workflows/pr-checks.yaml | 6 ++++-- .github/workflows/release.yaml | 5 +++-- .scripts/image-version.sh | 37 +++++++++++++++++++++++--------- .scripts/kubara-config-update.sh | 2 +- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml index e800965f..531de634 100644 --- a/.github/workflows/pr-checks.yaml +++ b/.github/workflows/pr-checks.yaml @@ -445,7 +445,7 @@ jobs: with: sparse-checkout: | .scripts - .github/helm-profiles + .github - name: Download generated kubara artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 @@ -458,7 +458,9 @@ jobs: - name: Extract container images run: | mkdir -p reports - OUTPUT_FILE="$PWD/reports/images.txt" .scripts/image-version.sh + IMAGE_OUTPUT_FILE="$PWD/reports/images.txt" + HELM_CHART_VERSION_FILE="$PWD/reports/chart.txt" + .scripts/image-version.sh - name: Write image summary if: always() diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e13f4ffe..45f6c44e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -93,8 +93,9 @@ jobs: - name: Extract images and set goreleaser header run: | - MANAGED=/tmp/gen/managed-service-catalog/helm \ - OUTPUT_FILE=/tmp/images.txt \ + CONFIG_FILE=/tmp/gen/config.yaml \ + MANAGED=/tmp/gen/platform-components/helm \ + IMAGE_OUTPUT_FILE=/tmp/images.txt \ "$GITHUB_WORKSPACE"/.scripts/image-version.sh { echo "IMAGE_LIST</dev/null 2>&1 || { echo "::error::helm not found on PATH"; exit 1; } command -v yq >/dev/null 2>&1 || { echo "::error::yq not found on PATH"; exit 1; } @@ -47,7 +49,7 @@ for chart_path in "$MANAGED"/*/; do echo "Updating dependency for ${chart_path}" >&2 - if ! dep_out=$(helm dependency update "$chart_path" >/dev/null 2>&1); then + if ! dep_out=$(helm dependency update "$chart_path" 2>&1 >/dev/null ); then echo "::error::helm dependency update failed for '$chart_path'"; echo "$dep_out" >&2 FAILED+=("$chart:dependency-update"); continue fi @@ -64,9 +66,13 @@ for chart_path in "$MANAGED"/*/; do fi done +# Note! This script does capture normal, init and sidecar containers, but by design +# misses out on runtime-injected images (e.g through webhooks, Kyverno etc.) +# and images refs passed via environment, this does not represent an exhaustive list of images +# captured IMAGES="$( cat "$render_dir"/*.yaml | - grep -E '^[[:space:]]*image:' | + grep -E '^[[:space:]]*image:' || true | sed -E "s/^[[:space:]]*image:[[:space:]]*//; s/[\"']//g" | grep -vE '[*!]' | # drop kyverno wildcard/negation entries grep -vE '^[[:space:]]*$' | @@ -77,19 +83,30 @@ echo "Done Rendering!" [[ -n "$IMAGES" ]] || { echo "::warning::No image references found"; exit 0; } -echo "$IMAGES" -echo "Extracting Helm Dependencies" -HELM_IMAGES="$(find . -name Chart.yaml -exec yq '.dependencies[] | select(.name != "template-library") | .name + ": " + .version' {} \;)" -echo "$HELM_IMAGES" - -[[ -n "$HELM_IMAGES" ]] || { echo "::warning::No helm image references found"; exit 0; } +if ((${#FAILED[@]})); then + echo "::warning:: Errors during templating: " + for err in "${FAILED[@]}"; do + echo "- $err" + done + exit 1 +fi if [[ -n "$IMAGE_OUTPUT_FILE" ]]; then echo "$IMAGES" > "$IMAGE_OUTPUT_FILE" echo "::notice::Image list written to $IMAGE_OUTPUT_FILE" fi +echo "$IMAGES" + +### Helm dependency part +echo "Extracting Helm Dependencies" +HELM_CHART_VERSIONS="$(find "$MANAGED" -name Chart.yaml -exec yq '.dependencies[] | select(.name != "template-library") | .name + ": " + .version' {} \;)" +echo "$HELM_CHART_VERSIONS" + +[[ -n "$HELM_CHART_VERSIONS" ]] || { echo "::warning::No helm image references found"; exit 0; } + + if [[ -n "$HELM_IMAGE_OUTPUT_FILE" ]]; then - echo "$HELM_IMAGES" > "$HELM_IMAGE_OUTPUT_FILE" + echo "$HELM_CHART_VERSIONS" > "$HELM_IMAGE_OUTPUT_FILE" echo "::notice:: Helm Image list written to $HELM_IMAGE_OUTPUT_FILE" fi diff --git a/.scripts/kubara-config-update.sh b/.scripts/kubara-config-update.sh index d7a85f8a..9424169c 100755 --- a/.scripts/kubara-config-update.sh +++ b/.scripts/kubara-config-update.sh @@ -55,7 +55,7 @@ yq eval '(.clusters[0].services[] | .status) = "enabled"' -i "$CFG" # metalb, loki and velero need custom configs yq eval '.clusters[0].services.metallb.config.publicLoadBalancerIPs = "203.0.113.10"' -i "$CFG" yq eval '.clusters[0].services.metallb.config.loadBalancerAddressPool = ["203.0.113.0/24"]' -i "$CFG" -yq eval '.clusters[0].storage.bucketNames.chunks = "loki"' -i "$CFG" +# yq eval '.clusters[0].storage.bucketNames.chunks = "loki"' -i "$CFG" yq eval '.clusters[0].services.velero.config.backupStorage.s3Url = "https://bucket.example.com"' -i "$CFG" From 7d4b1e02222478d272d27d414bfb29628a85f1c6 Mon Sep 17 00:00:00 2001 From: davrad Date: Mon, 27 Jul 2026 10:27:48 +0200 Subject: [PATCH 5/9] ci: extract image scanning to new repo --- .github/workflows/pr-checks.yaml | 51 -------- .scripts/image-version.sh | 112 ------------------ .../helm/reloader/Chart.yaml | 14 --- .../helm/velero/Chart.yaml | 13 -- 4 files changed, 190 deletions(-) delete mode 100755 .scripts/image-version.sh delete mode 100644 src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml delete mode 100644 src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml index 531de634..5ffb8620 100644 --- a/.github/workflows/pr-checks.yaml +++ b/.github/workflows/pr-checks.yaml @@ -428,54 +428,3 @@ jobs: name: terraform-validation-${{ github.run_attempt }}-${{ github.sha }}-${{ github.run_number }} retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} path: ${{ env.REPORT_DIR }}/terraform - - - extract-images: - needs: run-kubara-init-and-generate - runs-on: ubuntu-latest - outputs: - images: ${{ steps.matrix.outputs.images }} - has_images: ${{ steps.matrix.outputs.has_images }} - defaults: - run: - shell: bash - steps: - - name: Checkout CI scripts - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - sparse-checkout: | - .scripts - .github - - - name: Download generated kubara artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 - with: - name: kubara-generated-files-${{ github.run_attempt }}-${{ github.sha }}-${{ github.run_number }} - - - name: Verify Helm - run: helm version --short - - - name: Extract container images - run: | - mkdir -p reports - IMAGE_OUTPUT_FILE="$PWD/reports/images.txt" - HELM_CHART_VERSION_FILE="$PWD/reports/chart.txt" - .scripts/image-version.sh - - - name: Write image summary - if: always() - run: | - [[ -f reports/images.txt ]] || exit 0 - echo "### Container Images" >> "$GITHUB_STEP_SUMMARY" - while read -r img; do - echo "- $img" >> "$GITHUB_STEP_SUMMARY" - done < reports/images.txt - - - name: Upload image list - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 - if: always() - with: - name: container-images-${{ github.run_attempt }}-${{ github.sha }}-${{ github.run_number }} - retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} - path: reports/images.txt - diff --git a/.scripts/image-version.sh b/.scripts/image-version.sh deleted file mode 100755 index 46512084..00000000 --- a/.scripts/image-version.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env bash - - -# pipefail that pipes break -set -euo pipefail - -export PATH="$HOME/.local/bin/:$PATH" -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -MANAGED="${MANAGED:-${PWD}/platform-components/helm}" -CONFIG_FILE="${CONFIG_FILE:-config.yaml}" - -[[ -f "$CONFIG_FILE" ]] || { echo "::error::Missing $CONFIG_FILE — run 'kubara generate' first (or cd into its output)"; exit 1; } - -CLUSTER_NAME="$(yq -r '.clusters[0].name' "$CONFIG_FILE")" -CONFIGS="${CONFIGS:-platform-configs/${CLUSTER_NAME}/helm}" -IMAGE_OUTPUT_FILE="${IMAGE_OUTPUT_FILE:-}" -HELM_IMAGE_OUTPUT_FILE="${HELM_IMAGE_OUTPUT_FILE:-}" - -[[ -d "$MANAGED" ]] || { echo "::error::Missing $MANAGED — run 'kubara generate' first"; exit 1; } -command -v helm >/dev/null 2>&1 || { echo "::error::helm not found on PATH"; exit 1; } -command -v yq >/dev/null 2>&1 || { echo "::error::yq not found on PATH"; exit 1; } - -KUBE_VERSION=$(yq -r '.clusters[0].terraform.kubernetesVersion' "$CONFIG_FILE") - -PROMETHEUS_STATUS="$(yq -r '.clusters[0].services."kube-prometheus-stack".status // "disabled"' "$CONFIG_FILE")" - -# helm template flags advertise the monitoring API only when -# kube-prometheus-stack is enabled, since some charts (eg. traefik) render -# ServiceMonitors guarded by a `fail` on monitoring.coreos.com/v1. -HELM_TEMPLATE_ARGS=(--kube-version "$KUBE_VERSION" --include-crds) -if [[ "$PROMETHEUS_STATUS" == enabled ]]; then - HELM_TEMPLATE_ARGS+=(--api-versions "monitoring.coreos.com/v1") -fi - - -echo "Rendering charts from $MANAGED (kube-version=$KUBE_VERSION)" >&2 - - -render_dir="$(mktemp -d)"; trap 'rm -rf "$render_dir"' EXIT -FAILED=() - -for chart_path in "$MANAGED"/*/; do - chart=$(basename "$chart_path") - [[ -f "$chart_path/Chart.yaml" ]] || continue - - # Don't render library charts - [[ "$(yq '.type // "application"' "$chart_path/Chart.yaml")" == library ]] && continue - - echo "Updating dependency for ${chart_path}" >&2 - - if ! dep_out=$(helm dependency update "$chart_path" 2>&1 >/dev/null ); then - echo "::error::helm dependency update failed for '$chart_path'"; echo "$dep_out" >&2 - FAILED+=("$chart:dependency-update"); continue - fi - - values_file="$CONFIGS/$chart/values.generated.yaml" - base_values=(); [[ -f "$values_file" ]] && base_values=(-f "$values_file") - - if ! helm template "${HELM_TEMPLATE_ARGS[@]}" \ - "$chart" "$chart_path" "${base_values[@]}" \ - > "$render_dir/$chart.yaml" 2> "$render_dir/$chart.err"; then - echo "::error::helm template for for '$chart':" - sed 's/^/ /' "$render_dir/$chart.err" >&2 - FAILED+=("$chart:template"); continue - fi -done - -# Note! This script does capture normal, init and sidecar containers, but by design -# misses out on runtime-injected images (e.g through webhooks, Kyverno etc.) -# and images refs passed via environment, this does not represent an exhaustive list of images -# captured -IMAGES="$( - cat "$render_dir"/*.yaml | - grep -E '^[[:space:]]*image:' || true | - sed -E "s/^[[:space:]]*image:[[:space:]]*//; s/[\"']//g" | - grep -vE '[*!]' | # drop kyverno wildcard/negation entries - grep -vE '^[[:space:]]*$' | - sort -u -)" - -echo "Done Rendering!" - -[[ -n "$IMAGES" ]] || { echo "::warning::No image references found"; exit 0; } - -if ((${#FAILED[@]})); then - echo "::warning:: Errors during templating: " - for err in "${FAILED[@]}"; do - echo "- $err" - done - exit 1 -fi - -if [[ -n "$IMAGE_OUTPUT_FILE" ]]; then - echo "$IMAGES" > "$IMAGE_OUTPUT_FILE" - echo "::notice::Image list written to $IMAGE_OUTPUT_FILE" -fi - -echo "$IMAGES" - -### Helm dependency part -echo "Extracting Helm Dependencies" -HELM_CHART_VERSIONS="$(find "$MANAGED" -name Chart.yaml -exec yq '.dependencies[] | select(.name != "template-library") | .name + ": " + .version' {} \;)" -echo "$HELM_CHART_VERSIONS" - -[[ -n "$HELM_CHART_VERSIONS" ]] || { echo "::warning::No helm image references found"; exit 0; } - - -if [[ -n "$HELM_IMAGE_OUTPUT_FILE" ]]; then - echo "$HELM_CHART_VERSIONS" > "$HELM_IMAGE_OUTPUT_FILE" - echo "::notice:: Helm Image list written to $HELM_IMAGE_OUTPUT_FILE" -fi diff --git a/src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml b/src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml deleted file mode 100644 index 25482274..00000000 --- a/src/internal/catalog/built-in/platform-components/helm/reloader/Chart.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: v2 -name: reloader -description: Umbrella Chart for reloader -type: application -version: 1.0.0 -dependencies: - - name: template-library - repository: file://../template-library - version: 0.2.0 - # https://docs.stakater.com/reloader/latest/ - - name: reloader - repository: https://stakater.github.io/stakater-charts - version: 2.2.14 diff --git a/src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml b/src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml deleted file mode 100644 index 6963007b..00000000 --- a/src/internal/catalog/built-in/platform-components/helm/velero/Chart.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: v2 -name: velero -description: Umbrella Chart for Velero Config -type: application -version: 0.3.0 -dependencies: - - name: velero - version: 12.1.0 - repository: https://vmware-tanzu.github.io/helm-charts - - name: template-library - repository: file://../template-library - version: 0.2.0 From 1e041c7f00c2b07a8cce560188ea0610b68f1b60 Mon Sep 17 00:00:00 2001 From: davrad Date: Mon, 27 Jul 2026 10:44:08 +0200 Subject: [PATCH 6/9] ci: fix pipeline and remove leftover image extraction --- .github/workflows/pr-checks.yaml | 2 -- .github/workflows/release.yaml | 44 +++++--------------------------- .scripts/kubara-config-update.sh | 10 -------- mise.toml | 2 ++ 4 files changed, 8 insertions(+), 50 deletions(-) create mode 100644 mise.toml diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml index 5ffb8620..2e5f0880 100644 --- a/.github/workflows/pr-checks.yaml +++ b/.github/workflows/pr-checks.yaml @@ -32,8 +32,6 @@ env: # renovate: datasource=github-releases depName=terraform-linters/tflint TFLINT_VERSION: "v0.63.1" ARTIFACT_RETENTION_DAYS: "15" - # renovate: datasource=github-releases depName=aquasecurity/trivy - TRIVY_VERSION: "v0.70.0" permissions: contents: read diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 45f6c44e..fbfff459 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -62,46 +62,14 @@ jobs: set -euo pipefail helm version --short - - name: Run kubara generate + + - name: Pull Images list from Catalog + id: images env: - KUBARA_PROJECT_NAME: kubara - KUBARA_PROJECT_STAGE: tst - KUBARA_DOCKERCONFIG_BASE64: "000000" - KUBARA_ARGOCD_WIZARD_ACCOUNT_PASSWORD: "000000" - KUBARA_ARGOCD_HELM_REPO_USERNAME: git - KUBARA_ARGOCD_HELM_REPO_PASSWORD: "000000" - KUBARA_ARGOCD_HELM_REPO_URL: "https://kubara.io/kubara.git" - KUBARA_ARGOCD_GIT_HTTPS_URL: "https://kubara.io/kubara.git" - KUBARA_ARGOCD_GIT_PAT_OR_PASSWORD: "000000" - KUBARA_ARGOCD_GIT_USERNAME: git - KUBARA_DNS_NAME: kubara-tst.stackit.run - KUBARA_STACKIT_PROJECT_ID: "00000000-0000-0000-0000-000000000000" - KUBARA_TERRAFORM_PROVIDER: stackit - KUBARA_CLUSTER_TYPE: hub - KUBARA_SSO_ORG: Kubara - KUBARA_SSO_TEAM: Test - KUBARA_KUBERNETES_TYPE: ske - KUBARA_KUBERNETES_VERSION: "1.35.0" - run: | - set -euo pipefail - mkdir -p /tmp/gen - (cd src && go run main.go --work-dir /tmp/gen init --prep) - .scripts/kubara-env-update.sh /tmp/gen/.env - (cd src && go run main.go --work-dir /tmp/gen init) - .scripts/kubara-config-update.sh /tmp/gen/config.yaml - (cd src && go run main.go --work-dir /tmp/gen generate) - - - name: Extract images and set goreleaser header + GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} run: | - CONFIG_FILE=/tmp/gen/config.yaml \ - MANAGED=/tmp/gen/platform-components/helm \ - IMAGE_OUTPUT_FILE=/tmp/images.txt \ - "$GITHUB_WORKSPACE"/.scripts/image-version.sh - { - echo "IMAGE_LIST<> "$GITHUB_ENV" + echo "Dummy command" + - name: Run GoReleaser diff --git a/.scripts/kubara-config-update.sh b/.scripts/kubara-config-update.sh index 9424169c..90fddaa5 100755 --- a/.scripts/kubara-config-update.sh +++ b/.scripts/kubara-config-update.sh @@ -49,14 +49,4 @@ apply_yaml_if_set KUBARA_KUBERNETES_VERSION ".clusters[0].terraform.kubernetesV apply_yaml_if_set KUBARA_DNS_NAME ".clusters[0].dnsName" apply_yaml_if_set KUBARA_DNS_NAME ".clusters[0].terraform.dns.name" -# Enable every catalog service to the image/vuln report and the release header cover all charts -yq eval '(.clusters[0].services[] | .status) = "enabled"' -i "$CFG" - -# metalb, loki and velero need custom configs -yq eval '.clusters[0].services.metallb.config.publicLoadBalancerIPs = "203.0.113.10"' -i "$CFG" -yq eval '.clusters[0].services.metallb.config.loadBalancerAddressPool = ["203.0.113.0/24"]' -i "$CFG" -# yq eval '.clusters[0].storage.bucketNames.chunks = "loki"' -i "$CFG" - -yq eval '.clusters[0].services.velero.config.backupStorage.s3Url = "https://bucket.example.com"' -i "$CFG" - log "✅ config.yaml updated" diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000..fd57bb2a --- /dev/null +++ b/mise.toml @@ -0,0 +1,2 @@ +[tools] +actionlint = "latest" From 54c6ea4f99dec9504101c0a61103935ec83fe8eb Mon Sep 17 00:00:00 2001 From: davrad Date: Mon, 27 Jul 2026 15:05:47 +0200 Subject: [PATCH 7/9] ci: update goreleaser to included fetched files in footer --- .github/workflows/release.yaml | 38 ++++++++++++++++++++++++++++++++++ .gitignore | 1 + src/.goreleaser.yaml | 14 ++++++++++--- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fbfff459..412c644d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -68,8 +68,44 @@ jobs: env: GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} run: | + set -euo pipefail + + # TODO: replace dummy command with correct one echo "Dummy command" + cat > /tmp/platform-images.txt << 'EOF' + ghcr.io/dummy/argo-cd:v0.0.0-dummy + ghcr.io/dummy/cert-manager:v0.0.0-dummy + ghcr.io/dummy/external-secrets:v0.0.0-dummy + EOF + + cat > /tmp/helm-images-ver.txt << 'EOF' + ghcr.io/helm/argo-cd:v0.0.0-dummy + ghcr.io/helm/cert-manager:v0.0.0-dummy + ghcr.io/helm/external-secrets:v0.0.0-dummy + EOF + + echo "Images used for this release" + cat /tmp/platform-images.txt + echo "Helm Chart Versions used for this release" + cat /tmp/helm-images-ver.txt + + + # write to Github Actions environment + { + echo 'images-list<> "$GITHUB_OUTPUT" + + { + echo 'helm-images-ver<> "$GITHUB_OUTPUT" + + + - name: Run GoReleaser @@ -82,6 +118,8 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} + KUBARA_IMAGE_LIST: ${{ steps.images.outputs.images-list }} + HELM_IMAGES_VER: ${{ steps.images.outputs.helm-images-ver }} # The base64 of the contents of your '.p12' key. MACOS_SIGN_P12: ${{ secrets.MACOS_SIGN_P12 }} # The password to open the '.p12' key. diff --git a/.gitignore b/.gitignore index 445f2c06..1fbf15a9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .vscode/ +dist/ ./dist .act/ .actrc diff --git a/src/.goreleaser.yaml b/src/.goreleaser.yaml index 85ae7443..cb47b77b 100644 --- a/src/.goreleaser.yaml +++ b/src/.goreleaser.yaml @@ -13,9 +13,17 @@ release: replace_existing_artifacts: true extra_files: - glob: licenses.csv - header: | - ## Container Images - {{ .Env.IMAGE_LIST }} + footer: | + ## Platform images + Container images referenced by the platform components in this release + ```text + {{ .Env.KUBARA_IMAGE_LIST }} + ``` + ## Helm Charts + Helm Chart Versions for Images: + ```text + {{ .Env.HELM_IMAGES_VER }} + ``` changelog: use: git sort: asc From 77673e05faeadc6fec1fbfd26fe1128293e14ac4 Mon Sep 17 00:00:00 2001 From: davrad Date: Wed, 5 Aug 2026 16:35:40 +0200 Subject: [PATCH 8/9] ci: fetch images.txt from endpoint --- .github/workflows/release.yaml | 39 ++++++++++++++++++++-------------- .gitignore | 2 +- mise.toml | 2 -- 3 files changed, 24 insertions(+), 19 deletions(-) delete mode 100644 mise.toml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 412c644d..0f6a4e82 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,6 +9,12 @@ permissions: contents: write packages: write +env: + # renovate: datasource=github-releases depName=oras-project/oras extractVersion=^v(?.*)$ + ORAS_VERSION: "1.3.1" + CATALOG_IMAGES_REPO: ghcr.io/${{ github.repository_owner }}/catalogs + + jobs: goreleaser: runs-on: ubuntu-latest @@ -62,6 +68,11 @@ jobs: set -euo pipefail helm version --short + - name: Install oras + uses: oras-project/setup-oras@1d808f7d7f6995cc68b7bf507bfe5c5446e1dc9d # v2.0.1 + with: + version: ${{ env.ORAS_VERSION }} + - name: Pull Images list from Catalog id: images @@ -70,40 +81,36 @@ jobs: run: | set -euo pipefail - # TODO: replace dummy command with correct one - echo "Dummy command" + out="$RUNNTER_TEMP/catalog-images" - cat > /tmp/platform-images.txt << 'EOF' - ghcr.io/dummy/argo-cd:v0.0.0-dummy - ghcr.io/dummy/cert-manager:v0.0.0-dummy - ghcr.io/dummy/external-secrets:v0.0.0-dummy - EOF + for catalog in bootstrap general; do + oras pull "${CATALOG_IMAGES_REPO}/$P{catalog}-images:latest" -o "$out/$catalog" + done - cat > /tmp/helm-images-ver.txt << 'EOF' - ghcr.io/helm/argo-cd:v0.0.0-dummy - ghcr.io/helm/cert-manager:v0.0.0-dummy - ghcr.io/helm/external-secrets:v0.0.0-dummy - EOF + cat "$out"/*/images.txt | sort -u > "$out/platform-images.txt" + cat "$out/*/chart.txt" | sort -u > "$out/helm-images-ver.txt" echo "Images used for this release" cat /tmp/platform-images.txt echo "Helm Chart Versions used for this release" cat /tmp/helm-images-ver.txt - # write to Github Actions environment + echo "Writing images into release" + { echo 'images-list<> "$GITHUB_OUTPUT" - + { echo 'helm-images-ver<> "$GITHUB_OUTPUT" + diff --git a/.gitignore b/.gitignore index 1fbf15a9..90870f83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .DS_Store .idea/ .vscode/ - +mise.toml dist/ ./dist diff --git a/mise.toml b/mise.toml deleted file mode 100644 index fd57bb2a..00000000 --- a/mise.toml +++ /dev/null @@ -1,2 +0,0 @@ -[tools] -actionlint = "latest" From c4349b0a70e6f37d9c33b75c56a027f72acd8b48 Mon Sep 17 00:00:00 2001 From: davrad Date: Wed, 5 Aug 2026 16:47:43 +0200 Subject: [PATCH 9/9] ci: fix typos --- .github/workflows/release.yaml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0f6a4e82..c324ab0a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -81,19 +81,14 @@ jobs: run: | set -euo pipefail - out="$RUNNTER_TEMP/catalog-images" + out="$RUNNER_TEMP/catalog-images" for catalog in bootstrap general; do - oras pull "${CATALOG_IMAGES_REPO}/$P{catalog}-images:latest" -o "$out/$catalog" + oras pull "${CATALOG_IMAGES_REPO}/${catalog}-images:latest" -o "$out/$catalog" done cat "$out"/*/images.txt | sort -u > "$out/platform-images.txt" - cat "$out/*/chart.txt" | sort -u > "$out/helm-images-ver.txt" - - echo "Images used for this release" - cat /tmp/platform-images.txt - echo "Helm Chart Versions used for this release" - cat /tmp/helm-images-ver.txt + cat "$out"/*/chart.txt | sort -u > "$out/helm-images-ver.txt" # write to Github Actions environment echo "Writing images into release" @@ -111,10 +106,6 @@ jobs: } >> "$GITHUB_OUTPUT" - - - - - name: Run GoReleaser if: github.event_name == 'push' uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3