11name : kube-score validator workflow
2- # Works only with pull request triggers
32on :
43 workflow_call :
54
98 steps :
109 - name : Checkout code
1110 uses : actions/checkout@v4
11+
1212 - uses : azure/setup-kubectl@v4
1313 id : install-kubectl
1414
@@ -22,42 +22,61 @@ jobs:
2222 uses : tj-actions/changed-files@cf79a64fed8a943fb1073260883d08fe0dfb4e56
2323
2424 - name : Build overlays for changed kustomizations
25+ id : build
26+ shell : bash
2527 run : |
2628 set -euo pipefail
2729 out_dir="out/kustomize"
2830 mkdir -p "$out_dir"
2931
3032 changed_files="${{ steps.changed-files.outputs.all_changed_files }}"
3133
32- to_rebuild=$(echo "$changed_files" | tr ' ' '\n' |
33- grep -E '^(apps|bases|system|common)/' |
34- cut -d/ -f1-2 | sed 's:/$::' | sort -u)
35-
36- echo "Apps to rebuild:"; printf ' %s\n' $to_rebuild
34+ # Tolerate "no matches" under -euo pipefail
35+ to_rebuild=$(
36+ { printf '%s\n' "$changed_files" | tr ' ' '\n' | grep -E '^(apps|bases|system|common)/' || true; } |
37+ cut -d/ -f1-2 | sed 's:/$::' | sort -u
38+ )
39+
40+ echo "Apps to rebuild:"
41+ if [ -n "${to_rebuild:-}" ]; then
42+ printf ' %s\n' $to_rebuild
43+ else
44+ echo " (none)"
45+ fi
3746 echo "-----------------------------------------"
3847
48+ # Discover kustomization roots present in the repo
3949 roots=()
4050 for d in apps bases system common; do
4151 [ -d "$d" ] && roots+=("./$d")
4252 done
43- [ "${#roots[@]}" -eq 0 ] && { echo "No kustomization roots found."; exit 0; }
53+ [ "${#roots[@]}" -eq 0 ] && {
54+ echo "No kustomization roots found."
55+ echo "built_any=false" >> "$GITHUB_OUTPUT"
56+ exit 0
57+ }
58+
59+ # Early exit if nothing to rebuild
60+ if [ -z "${to_rebuild:-}" ]; then
61+ echo "Nothing to rebuild."
62+ echo "built_any=false" >> "$GITHUB_OUTPUT"
63+ exit 0
64+ fi
4465
66+ # Build each selected kustomization
4567 find "${roots[@]}" \
46- -type f \( -name kustomization.yaml -o -name kustomization.yml \) \
47- -not -path '*/base/*' -print0 |
68+ -type f \( -name kustomization.yaml -o -name kustomization.yml \) \
69+ -not -path '*/base/*' -print0 |
4870 while IFS= read -r -d '' kustom; do
4971 dir="$(dirname "$kustom")"
5072 rel="${dir#./}"
51-
5273 root_key=$(echo "$rel" | cut -d/ -f1-2)
5374 if grep -Fxq "$root_key" <<<"$to_rebuild"; then
5475 name="${rel//\//_}.yaml"
5576 echo "▶ building $name"
56-
57- # Allow refs that climb out of the kustomisation dir (needed for nextcloud)
5877 if kubectl kustomize --enable-helm \
59- --load-restrictor LoadRestrictionsNone \
60- "$dir" > "$out_dir/$name"; then
78+ --load-restrictor LoadRestrictionsNone \
79+ "$dir" > "$out_dir/$name"; then
6180 echo "✓ $name built"
6281 else
6382 echo "⚠️ $rel failed to build; skipping"
@@ -71,13 +90,32 @@ jobs:
7190 echo "---- Resulting manifests ----"
7291 ls -l "$out_dir" || true
7392
74- - name : kube‑score check
93+ # Output flag to gate follow-up steps
94+ shopt -s nullglob
95+ files=( "$out_dir"/*.yaml )
96+ if [ ${#files[@]} -gt 0 ]; then
97+ echo "built_any=true" >> "$GITHUB_OUTPUT"
98+ else
99+ echo "built_any=false" >> "$GITHUB_OUTPUT"
100+ fi
101+
102+ - name : kube-score check
75103 id : score
104+ if : steps.build.outputs.built_any == 'true'
105+ shell : bash
76106 run : |
77- kube-score score --output-format ci ./out/kustomize/*.yaml | tee /tmp/kube-score.ci
107+ set -euo pipefail
108+ shopt -s nullglob
109+ files=( ./out/kustomize/*.yaml )
110+ if [ ${#files[@]} -eq 0 ]; then
111+ echo "No manifests to score."
112+ exit 0
113+ fi
114+ kube-score score --output-format ci "${files[@]}" | tee /tmp/kube-score.ci
78115
79116 - name : Collect /kube-score skip directives
80117 id : skips
118+ if : steps.build.outputs.built_any == 'true'
81119 shell : bash
82120 env :
83121 GH_TOKEN : ${{ github.token }}
@@ -94,24 +132,30 @@ jobs:
94132 echo "Skip directives found:"
95133 cat /tmp/kskip.list || echo "(none)"
96134
97- - name : Validate kube‑score results
135+ - name : Validate kube-score results
136+ if : steps.build.outputs.built_any == 'true'
98137 shell : bash
99138 run : |
100- sk=$(sed -E 's%^/kube-score skip %%; s/\r$//' /tmp/kskip.list | sort -u)
139+ set -euo pipefail
101140
141+ # If kube-score didn't run or produced no output, exit cleanly
142+ if [ ! -f /tmp/kube-score.ci ]; then
143+ echo "No kube-score output; nothing to validate."
144+ exit 0
145+ fi
146+
147+ sk=$(sed -E 's%^/kube-score skip %%; s/\r$//' /tmp/kskip.list 2>/dev/null | sort -u || true)
102148 critical_lines=$(grep '^\[CRITICAL\]' /tmp/kube-score.ci || true)
103149 failures=0
104150
105151 while IFS= read -r line; do
106152 [ -z "$line" ] && continue
107-
108153 key=$(sed -E 's/^\[CRITICAL\] +([^ ]+) +([^:]+):.*/\1 \2/' <<< "$line" | tr -d '\r')
109-
110154 if grep -Fxq "$key" <<< "$sk"; then
111155 echo "⏭ $key (skipped)"
112156 else
113157 echo "::error::$line"
114- echo "↳ Pour ignorer : /kube-score skip $key"
158+ echo "↳ Pour ignorer : /kube-score skip $key"
115159 failures=1
116160 fi
117161 done <<< "$critical_lines"
0 commit comments