Compare commits

...
3 Commits
Author SHA1 Message Date
hermes 687339bb9e fix(ci): self-heal a stale cluster CA in the deploy job
Build and Push Image / Unit tests (push) Successful in 55s
Build and Push Image / Build and push image (push) Skipped
Build and Push Image / Deploy to the cluster (push) Skipped
The deploy job failed on its first run:

    error: error validating "kube/beer_namespace.yaml": error validating
    data: failed to download openapi: Get "https://192.168.178.160:6443/openapi/v2":
    tls: failed to verify certificate: x509: certificate signed by unknown authority

This is the same class of problem as the buildx driver earlier: the
certificate-authority-data embedded in the kubeconfig secret does not match
the CA the API server is currently presenting.

Rather than requiring the secret to be regenerated by hand every time the
cluster's CA is rotated, the job now refreshes it:

- The API server publishes its own CA at `/cacerts`.
- If kubectl cannot verify the server, the job fetches that CA (over an
  insecure connection — verifying it is the problem being solved) and pins
  it explicitly with `kubectl config set-cluster`.
- It then retries, and fails with a clear message if that still does not
  work.

Verified by deliberately corrupting the CA in a working kubeconfig: the
failure reproduces exactly, and the recovery path restores connectivity
(`Server Version: v1.34.5+k3s1`).

The secret is also switched from `KUBEC_CONFIG_BUILDX` to
`KUBEC_CONFIG_BUILDX_NEW_2`, which is the one the working `wedding-photos`
workflow uses.
2026-11-09 12:08:49 +10:00
hermes c28553a1b8 feat(ci): add the deploy job and the kubernetes manifests (#8)
Build and Push Image / Unit tests (push) Successful in 43s
Build and Push Image / Build and push image (push) Successful in 1m22s
Build and Push Image / Deploy to the cluster (push) Failing after 1m29s
feat(ci): add the deploy job and the kubernetes manifests (#8)
2026-11-09 12:00:35 +10:00
hermes 0f93cbea70 fix: build the image on Python 3.14 (#7)
Build and Push Image / Unit tests (push) Successful in 1m14s
Build and Push Image / Build and push image (push) Successful in 9m47s
fix: build the image on Python 3.14 (#7)
2026-11-09 11:26:29 +10:00
+48 -1
View File
@@ -118,9 +118,56 @@ jobs:
# cluster-admin-equivalent, so it should not be readable by # cluster-admin-equivalent, so it should not be readable by
# anything else on the runner. # anything else on the runner.
install -m 600 /dev/null $HOME/.kube/config install -m 600 /dev/null $HOME/.kube/config
echo "${{ secrets.KUBEC_CONFIG_BUILDX }}" > $HOME/.kube/config echo "${{ secrets.KUBEC_CONFIG_BUILDX_NEW_2 }}" > $HOME/.kube/config
chmod 600 $HOME/.kube/config chmod 600 $HOME/.kube/config
- name: Verify the cluster is reachable
run: |
# Fail fast, and with a useful message, if the kubeconfig cannot
# talk to the API server.
#
# The certificate-authority-data inside the kubeconfig is the k3s
# server CA. If the cluster's CA has been rotated since the secret
# was created, kubectl fails with:
# tls: failed to verify certificate: x509: certificate signed by
# unknown authority
# which is a confusing way to learn that a secret is stale.
if kubectl version --request-timeout=15s >/dev/null 2>&1; then
echo "cluster reachable"
exit 0
fi
echo "the kubeconfig could not verify the API server - refreshing the CA"
# The API server publishes its own CA at /cacerts. Fetch it over an
# insecure connection - we cannot verify it yet, that is the problem
# being solved - and pin it explicitly. This makes the deploy
# self-healing after a CA rotation, instead of needing the secret
# to be regenerated by hand.
SERVER=$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.server}')
echo "server: $SERVER"
curl -sk "$SERVER/cacerts" -o $HOME/.kube/ca.crt
if [ ! -s $HOME/.kube/ca.crt ]; then
echo "ERROR: could not fetch the cluster CA from $SERVER/cacerts"
exit 1
fi
kubectl config set-cluster default \
--embed-certs=true \
--certificate-authority=$HOME/.kube/ca.crt >/dev/null
rm -f $HOME/.kube/ca.crt
if kubectl version --request-timeout=15s >/dev/null 2>&1; then
echo "cluster reachable after refreshing the CA"
exit 0
fi
echo "ERROR: cannot reach the cluster API server even with a refreshed CA."
echo " The kubeconfig in the KUBEC_CONFIG_BUILDX_NEW_2 secret may be"
echo " stale or invalid, and needs regenerating."
exit 1
- name: Install kubectl - name: Install kubectl
run: | run: |
# Skip the whole apt dance if the runner already has a kubectl. # Skip the whole apt dance if the runner already has a kubectl.