From 417dff0f806a4e18a1aaaa49f910de6b2120224e Mon Sep 17 00:00:00 2001 From: MeepMr <67143880+MeepMr@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:46:54 +0200 Subject: [PATCH] install-test: wait for a Ready node, not for an answer Second defect in the same check, and the more serious one: kubectl get nodes exits 0 on an EMPTY list. The cluster on Gitea answered while its node had not registered, the step logged 'No resources found' and went green, and the failure surfaced five minutes later as a pod stuck in Pending with no node and no scheduling event - the cause nowhere near the symptom. kubectl wait --for=condition=Ready nodes --all has the same hole; with zero nodes it succeeds vacuously. It now counts Ready nodes, and on timeout dumps the node conditions and the k3s server log so the error picture is in the job that caused it. --- .github/workflows/validate-charts.yml | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/.github/workflows/validate-charts.yml b/.github/workflows/validate-charts.yml index 1918c4a..aa52bee 100644 --- a/.github/workflows/validate-charts.yml +++ b/.github/workflows/validate-charts.yml @@ -462,16 +462,30 @@ jobs: # it produces exactly the sporadic red this job must not have. The # loop asks for the node list, which is the thing that has to work # and exercises discovery on the way. - for ATTEMPT in $(seq 1 60); do - kubectl get nodes >/dev/null 2>&1 && break - if [ "$ATTEMPT" -eq 60 ]; then - echo "::error::the k3d cluster '$CLUSTER' was created but never became reachable" - kubectl get nodes || true + # It waits for a READY NODE, not for the API server to answer. The + # difference is not pedantry, it is the second bug this check had: + # `kubectl get nodes` exits 0 on an EMPTY list, so the first version + # passed against a cluster whose server was up and whose node had + # not registered - the log said "No resources found" and the step + # went green, and the failure surfaced five minutes later as a pod + # stuck in Pending with no node and no scheduling event. A check + # that a broken cluster passes is worse than none. `kubectl wait + # --for=condition=Ready nodes --all` has the same hole: with zero + # nodes it succeeds vacuously. + for ATTEMPT in $(seq 1 90); do + READY_NODES="$(kubectl get nodes --no-headers 2>/dev/null | awk '$2 == "Ready"' | wc -l | tr -d ' ')" + [ "$READY_NODES" -ge 1 ] && break + if [ "$ATTEMPT" -eq 90 ]; then + echo "::error::the k3d cluster '$CLUSTER' answers but has no Ready node after 180s" + kubectl get nodes -o wide || true + kubectl describe nodes || true + echo "--- k3s server log ---" + docker logs "k3d-$CLUSTER-server-0" 2>&1 | tail -80 || true exit 1 fi sleep 2 done - kubectl get nodes + kubectl get nodes -o wide # Every chart reaching this step is one the exclusion filter let through, # so the script's SKIP branch is never taken here - it exists for local # runs. The variables below are empty for every chart but the one that