From 31e42605800a22a310f940053a4bf4a861bfa4fd Mon Sep 17 00:00:00 2001 From: MeepMr <67143880+MeepMr@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:29:08 +0200 Subject: [PATCH] install-test: reach the k3d cluster when the job itself is a container Closes the last gap from #227. k3d publishes the API server port on the Docker HOST. On GitHub's hosted runners the job is that host, so the https://0.0.0.0: k3d writes into the kubeconfig works. Every Gitea Actions job is itself a container, and there the host is the dind container: 0.0.0.0 points at the job container, where nothing listens. The cluster comes up cleanly and the first kubectl call is refused - as measured, surfacing two steps later as a validation error on the fixtures, which named nothing useful. The case is decided on whether THIS job runs in a container, not on which forge it runs on. github.server_url would pick the right branch today and still be wrong: a self-hosted GitHub runner in a container has the identical problem, and a condition that says GitHub while meaning not-containerised is the kind of lie this repo exists to remove. The detection is the same question the fix needs answered anyway - ask the daemon about ourselves. In a container it returns our network, k3d joins it, and Docker's DNS resolves the node names; on a host it returns nothing and the previous path is taken unchanged. kubectl cluster-info and get nodes now run inside the create step, so a cluster that is up but unreachable fails where it is caused instead of two steps downstream. --- .github/workflows/validate-charts.yml | 50 ++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/.github/workflows/validate-charts.yml b/.github/workflows/validate-charts.yml index f9b945e..6a6f040 100644 --- a/.github/workflows/validate-charts.yml +++ b/.github/workflows/validate-charts.yml @@ -404,7 +404,55 @@ jobs: echo "::error::chart name '$CLUSTER' is ${#CLUSTER} characters and k3d allows at most 32 for a cluster name." exit 1 fi - k3d cluster create "$CLUSTER" --image "$K3S_IMAGE" --wait --timeout 180s + + # Does THIS job run inside a container? That, and not which forge we + # are on, is what decides whether k3d's cluster is reachable (#227). + # + # k3d publishes the API server port on the Docker *host*. When the + # job runs straight on the host - GitHub's hosted runners - that is + # the same machine, and the "https://0.0.0.0:" k3d writes into + # the kubeconfig works. When the job itself is a container, as every + # Gitea Actions job is, the host is the dind container and 0.0.0.0 + # points at the job container itself, where nothing listens. The + # cluster comes up fine and the first kubectl call is refused. + # + # Deliberately NOT keyed on github.server_url, although that would + # pick the right branch today: a self-hosted GitHub runner in a + # container has exactly this problem, and a condition that says + # "GitHub" while meaning "not containerised" is the kind of lie this + # repo exists to remove. So the state is detected instead of + # inferred, and the detection is the same question the fix needs + # answered anyway: ask the daemon about ourselves. Inside a + # container that the daemon knows, this returns our network and k3d + # joins it, which puts k3s and this job on one bridge where Docker's + # own DNS resolves the container names. On a host it returns nothing, + # because the hostname is not a container, and the old path is taken + # unchanged. + # The "|| true" is load-bearing: this step runs under `bash -e -o + # pipefail`, and on a host `docker inspect` exits non-zero, which + # would abort the step instead of taking the else branch. + JOB_NET="$(docker inspect -f '{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}' "$(hostname)" 2>/dev/null | awk '{print $1}' || true)" + + if [ -n "$JOB_NET" ]; then + echo "Containerised job: $(hostname) on docker network '$JOB_NET' - k3d joins it." + k3d cluster create "$CLUSTER" --image "$K3S_IMAGE" --network "$JOB_NET" --wait --timeout 180s + # Same reason: the published port is useless from in here, so the + # kubeconfig is pointed at the load balancer container by name, + # over the shared network. If the API server certificate did not + # carry that name this would fail on the TLS handshake and the + # cluster-info below would say so - it holds without an extra + # --tls-san, measured on the probe PR of #225. + kubectl config set-cluster "k3d-$CLUSTER" --server="https://k3d-$CLUSTER-serverlb:6443" + else + echo "Job runs on the docker host - k3d's published port is reachable as written." + k3d cluster create "$CLUSTER" --image "$K3S_IMAGE" --wait --timeout 180s + fi + + # Proves reachability here rather than letting it surface two steps + # later as a validation error on the fixtures, which is where it + # showed up before and named nothing useful. + kubectl cluster-info + kubectl get nodes # 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