From 0f0b3407548af8d7d7a246f8fe74085e585993fa Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 3 Jul 2026 22:29:27 +0200 Subject: [PATCH] Add in-cluster Forgejo Actions runner manifests (ADR-004) DinD sidecar + forgejo-runner Deployment with PVC-backed registration state. Makefile targets for registration secret, deploy, and status. --- Makefile | 24 +++- docs/forgejo-on-railiance01.md | 5 + ...ejo-runner-registration.sops.yaml.template | 15 ++ manifests/forgejo-runner.yaml | 134 ++++++++++++++++++ 4 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 helm/forgejo-runner-registration.sops.yaml.template create mode 100644 manifests/forgejo-runner.yaml diff --git a/Makefile b/Makefile index 6a5ea46..fb4d1ba 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,8 @@ FORGEJO_SSH_NODEPORT ?= manifests/forgejo-ssh-nodeport.yaml FORGEJO_BASE_URL ?= https://forgejo.coulomb.social FORGEJO_DB_CLUSTER ?= forgejo-db FORGEJO_DB_NAMESPACE ?= databases +FORGEJO_RUNNER_MANIFEST ?= manifests/forgejo-runner.yaml +FORGEJO_RUNNER_REGISTRATION_SECRET ?= helm/forgejo-runner-registration.sops.yaml INTER_HUB_IMAGE_REF = $(INTER_HUB_IMAGE_REPOSITORY):$(INTER_HUB_IMAGE_TAG) INTER_HUB_IMAGE_SET_ARG = $(if $(strip $(INTER_HUB_IMAGE_TAG)),--set image.tag=$(INTER_HUB_IMAGE_TAG),) @@ -216,6 +218,26 @@ forgejo-smoke: ## Verify Forgejo web and OCI registry challenge forgejo-logs: check-railiance01-kubeconfig ## Tail Forgejo application logs KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl logs -n $(FORGEJO_NAMESPACE) -l app.kubernetes.io/instance=$(FORGEJO_RELEASE) -f --tail=50 +forgejo-runner-registration-deploy: check-railiance01-kubeconfig check-sops ## Apply SOPS runner registration secret + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl apply -f <(sops -d $(FORGEJO_RUNNER_REGISTRATION_SECRET)) + +forgejo-runner-deploy: check-railiance01-kubeconfig ## Deploy in-cluster Forgejo Actions runner (ADR-004) + @test -n "$$(KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl get secret forgejo-runner-registration -n $(FORGEJO_NAMESPACE) -o name 2>/dev/null)" || { \ + echo "Missing secret forgejo-runner-registration in $(FORGEJO_NAMESPACE)." >&2; \ + echo "Apply helm/forgejo-runner-registration.sops.yaml or bootstrap once:" >&2; \ + echo " kubectl create secret generic forgejo-runner-registration -n forgejo --from-literal=token=" >&2; \ + exit 1; \ + } + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl apply -f $(FORGEJO_RUNNER_MANIFEST) + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl rollout status deployment/forgejo-runner -n $(FORGEJO_NAMESPACE) --timeout=5m + +forgejo-runner-status: check-railiance01-kubeconfig ## Show in-cluster runner pod and PVC state + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl get deploy,pods,pvc -n $(FORGEJO_NAMESPACE) -l app.kubernetes.io/name=forgejo-runner --ignore-not-found + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl logs -n $(FORGEJO_NAMESPACE) deploy/forgejo-runner -c runner --tail=20 2>/dev/null || true + +forgejo-runner-logs: check-railiance01-kubeconfig ## Tail in-cluster runner logs + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl logs -n $(FORGEJO_NAMESPACE) deploy/forgejo-runner -c runner -f --tail=50 + ##@ reuse-surface (reuse.coulomb.social) reuse-dry-run: check-railiance01-kubeconfig ## helm template render (no apply) for reuse-surface @@ -246,4 +268,4 @@ help: ## Show this help /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } \ /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(MAKEFILE_LIST) -.PHONY: check-tools check-sops k8s-server-dry-run apps-pg-status check-railiance01-kubeconfig check-inter-hub-image-tag check-inter-hub-image vergabe-dry-run vergabe-deploy vergabe-ingress-deploy vergabe-status vergabe-migrate vergabe-seed vergabe-superuser vergabe-logs vergabe-db-url-secret forgejo-dry-run forgejo-server-dry-run forgejo-deploy forgejo-ingress-deploy forgejo-ssh-nodeport-deploy forgejo-status forgejo-smoke forgejo-logs inter-hub-render-baseline inter-hub-dry-run inter-hub-server-dry-run inter-hub-deploy inter-hub-status inter-hub-release-info inter-hub-smoke inter-hub-logs reuse-dry-run reuse-deploy reuse-status reuse-smoke reuse-logs help +.PHONY: check-tools check-sops k8s-server-dry-run apps-pg-status check-railiance01-kubeconfig check-inter-hub-image-tag check-inter-hub-image vergabe-dry-run vergabe-deploy vergabe-ingress-deploy vergabe-status vergabe-migrate vergabe-seed vergabe-superuser vergabe-logs vergabe-db-url-secret forgejo-dry-run forgejo-server-dry-run forgejo-deploy forgejo-ingress-deploy forgejo-ssh-nodeport-deploy forgejo-status forgejo-smoke forgejo-logs forgejo-runner-registration-deploy forgejo-runner-deploy forgejo-runner-status forgejo-runner-logs inter-hub-render-baseline inter-hub-dry-run inter-hub-server-dry-run inter-hub-deploy inter-hub-status inter-hub-release-info inter-hub-smoke inter-hub-logs reuse-dry-run reuse-deploy reuse-status reuse-smoke reuse-logs help diff --git a/docs/forgejo-on-railiance01.md b/docs/forgejo-on-railiance01.md index 8be4c1f..1f228fd 100644 --- a/docs/forgejo-on-railiance01.md +++ b/docs/forgejo-on-railiance01.md @@ -56,8 +56,13 @@ make forgejo-dry-run make forgejo-deploy make forgejo-ingress-deploy make forgejo-ssh-nodeport-deploy # optional; git+ssh via nodePort 30022 +# In-cluster Actions runner (ADR-004, railiance-infra/docs/adr/ADR-004-...) +# One-time: encrypt helm/forgejo-runner-registration.sops.yaml from template +make forgejo-runner-registration-deploy +make forgejo-runner-deploy make forgejo-status make forgejo-smoke +make forgejo-runner-status ``` ## Upgrade notes diff --git a/helm/forgejo-runner-registration.sops.yaml.template b/helm/forgejo-runner-registration.sops.yaml.template new file mode 100644 index 0000000..261f1bc --- /dev/null +++ b/helm/forgejo-runner-registration.sops.yaml.template @@ -0,0 +1,15 @@ +# Encrypt as helm/forgejo-runner-registration.sops.yaml, then: +# kubectl apply -f <(sops -d helm/forgejo-runner-registration.sops.yaml) +# +# Generate token (one-time, do not commit plaintext): +# kubectl exec -n forgejo deploy/forgejo-gitea -- \ +# forgejo actions generate-runner-token --scope coulomb +--- +apiVersion: v1 +kind: Secret +metadata: + name: forgejo-runner-registration + namespace: forgejo +type: Opaque +stringData: + token: REPLACE_WITH_RUNNER_REGISTRATION_TOKEN \ No newline at end of file diff --git a/manifests/forgejo-runner.yaml b/manifests/forgejo-runner.yaml new file mode 100644 index 0000000..3ec2e3e --- /dev/null +++ b/manifests/forgejo-runner.yaml @@ -0,0 +1,134 @@ +# In-cluster Forgejo Actions runner (ADR-004). +# DinD sidecar + forgejo-runner; registration via init container on first boot. +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: forgejo-runner-data + namespace: forgejo + labels: + app.kubernetes.io/name: forgejo-runner + app.kubernetes.io/part-of: railiance-apps +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: local-path +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: forgejo-runner-init + namespace: forgejo + labels: + app.kubernetes.io/name: forgejo-runner +data: + register.sh: | + #!/bin/sh + set -eu + cd /data + if [ ! -f config.yaml ]; then + forgejo-runner generate-config > config.yaml + fi + if [ ! -f .runner ]; then + forgejo-runner register --no-interactive \ + --config /data/config.yaml \ + --instance "${FORGEJO_INSTANCE}" \ + --token "${REGISTRATION_TOKEN}" \ + --name "${RUNNER_NAME}" \ + --labels "${RUNNER_LABELS}" + fi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: forgejo-runner + namespace: forgejo + labels: + app.kubernetes.io/name: forgejo-runner + app.kubernetes.io/part-of: railiance-apps +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/name: forgejo-runner + template: + metadata: + labels: + app.kubernetes.io/name: forgejo-runner + spec: + securityContext: + fsGroup: 1000 + initContainers: + - name: register + image: code.forgejo.org/forgejo/runner:6.3.1 + imagePullPolicy: IfNotPresent + command: ["/bin/sh", "/scripts/register.sh"] + env: + - name: FORGEJO_INSTANCE + value: "https://forgejo.coulomb.social/" + - name: RUNNER_NAME + value: "railiance01-build-01" + - name: RUNNER_LABELS + value: "self-hosted:host,linux:host,linux_amd64:host,container-build:host,registry-publish:host,railiance01:host,ubuntu-latest:docker://node:20-bookworm,docker:docker://node:20-bookworm" + - name: REGISTRATION_TOKEN + valueFrom: + secretKeyRef: + name: forgejo-runner-registration + key: token + volumeMounts: + - name: data + mountPath: /data + - name: init-scripts + mountPath: /scripts + readOnly: true + containers: + - name: dind + image: docker:27-dind + imagePullPolicy: IfNotPresent + securityContext: + privileged: true + env: + - name: DOCKER_TLS_CERTDIR + value: "" + args: + - dockerd + - -H + - tcp://0.0.0.0:2375 + - --tls=false + readinessProbe: + exec: + command: [docker, info] + initialDelaySeconds: 5 + periodSeconds: 10 + - name: runner + image: code.forgejo.org/forgejo/runner:6.3.1 + imagePullPolicy: IfNotPresent + env: + - name: DOCKER_HOST + value: tcp://127.0.0.1:2375 + command: + - forgejo-runner + - daemon + - --config + - /data/config.yaml + volumeMounts: + - name: data + mountPath: /data + readinessProbe: + exec: + command: [forgejo-runner, -v] + initialDelaySeconds: 10 + periodSeconds: 30 + volumes: + - name: data + persistentVolumeClaim: + claimName: forgejo-runner-data + - name: init-scripts + configMap: + name: forgejo-runner-init + defaultMode: 0555 \ No newline at end of file