From 7082cd4dd58a1b4d640eb01ff0dcc58f4714cd3d Mon Sep 17 00:00:00 2001 From: Quentin Campos Date: Tue, 21 Apr 2026 15:25:24 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20forgejo:=20add=20forgejo-runner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .forgejo/workflows/build.yaml | 25 +++--- Dockerfile | 2 +- git-forgejo/instance/deployment.yaml | 5 ++ git-forgejo/instance/registry-secret.yaml | 16 ++-- git-forgejo/runner/configmap.yaml | 43 +++++++++ git-forgejo/runner/deployment.yaml | 103 ++++++++++++++++++++++ git-forgejo/runner/pvc.yaml | 16 ++++ git-forgejo/runner/secret.yaml | 16 ++++ 8 files changed, 209 insertions(+), 17 deletions(-) create mode 100644 git-forgejo/runner/configmap.yaml create mode 100644 git-forgejo/runner/deployment.yaml create mode 100644 git-forgejo/runner/pvc.yaml create mode 100644 git-forgejo/runner/secret.yaml diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 253fba8..015c632 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -1,15 +1,18 @@ -name: Build avec Kaniko +name: Build on: [push] jobs: - kaniko-build: - runs-on: k8s # Doit correspondre au label dans ta configmap - container: - image: gcr.io/kaniko-project/executor:debug + build: + runs-on: k8s steps: - - name: Build et Push - run: | - /kaniko/executor \ - --context "${{ github.workspace }}" \ - --dockerfile "${{ github.workspace }}/Dockerfile" \ - --destination "git.qcampos.fr/${{ github.repository }}:latest" \ No newline at end of file + - uses: actions/checkout@v4 + - uses: https://git.qcampos.fr/system/actions/setup-kaniko@main + + - name: Build and push + uses: docker://gcr.io/kaniko-project/executor:debug + with: + args: >- + --context dir:///github/workspace + --destination git.qcampos.fr/${{ github.repository }}:latest + --destination git.qcampos.fr/${{ github.repository }}:${{ github.sha }} + --skip-tls-verify diff --git a/Dockerfile b/Dockerfile index 182f813..88b5d14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM python:alpine -RUN ["touch", "foo.txt"] +RUN ["touch", "barrrrrrr.txt"] CMD ["python", "-c", "'import this'"] \ No newline at end of file diff --git a/git-forgejo/instance/deployment.yaml b/git-forgejo/instance/deployment.yaml index 1e417f6..25c301e 100644 --- a/git-forgejo/instance/deployment.yaml +++ b/git-forgejo/instance/deployment.yaml @@ -13,6 +13,8 @@ spec: labels: app: forgejo spec: + imagePullSecrets: + - name: forgejo-registry-secret containers: - name: forgejo image: codeberg.org/forgejo/forgejo:8 @@ -31,6 +33,9 @@ spec: # Activation du Registre d'images - name: FORGEJO__packages__ENABLED value: "true" + # Required for OCI/container image pushes (chunked upload temp dir) + - name: FORGEJO__packages__CHUNKED_UPLOAD_PATH + value: /data/tmp/package-chunked-upload # Activation des Actions (CI/CD) - name: FORGEJO__actions__ENABLED value: "true" diff --git a/git-forgejo/instance/registry-secret.yaml b/git-forgejo/instance/registry-secret.yaml index 5f78cc2..0187389 100644 --- a/git-forgejo/instance/registry-secret.yaml +++ b/git-forgejo/instance/registry-secret.yaml @@ -1,10 +1,16 @@ +# Docker registry credentials for git.qcampos.fr (Forgejo packages). +# +# Stored as an Opaque secret so the key name becomes the filename when +# mounted as a volume — DinD will expose it to Kaniko at /kaniko/.docker/config.json. +# +# To regenerate the auth value: +# printf 'qcampos:' | base64 -w0 apiVersion: v1 kind: Secret metadata: - name: registry-secret + name: forgejo-registry-secret namespace: forgejo +type: Opaque stringData: - docker-server: git.qcampos.fr - docker-username: qcampos - docker-password: "50f5bf95338e2f39d70210d6cc71f82c091d1331" - namespace: forgejo \ No newline at end of file + config.json: | + {"auths":{"git.qcampos.fr":{"auth":"cWNhbXBvczphMDFhMDRlOGE1NzkzNzdmNWZjZWU5NmFlMDAyMDRkZTdmMTY0Zjgw"}}} \ No newline at end of file diff --git a/git-forgejo/runner/configmap.yaml b/git-forgejo/runner/configmap.yaml new file mode 100644 index 0000000..10a50f1 --- /dev/null +++ b/git-forgejo/runner/configmap.yaml @@ -0,0 +1,43 @@ +# ConfigMap contenant la configuration du runner (fichier config.yaml). +# Ce fichier est monté dans le pod et passé au runner via --config. +apiVersion: v1 +kind: ConfigMap +metadata: + name: forgejo-runner-config + namespace: forgejo +data: + config.yaml: | + log: + level: info + + runner: + file: /data/.runner + + # Number of parallel jobs + capacity: 2 + + # Labels exposed to Forgejo for workflows to target the runner. + # Here "k8s" corresponds to `runs-on: k8s` in workflows. + # + # The job container needs /bin/sh and /bin/sleep (act_runner requirement). + # Kaniko is invoked as a step image (uses: docker://) — not as the job container. + labels: + - "k8s:docker://node:20-bookworm" + + container: + # Bind-mount the registry credentials (config.json) that were injected into + # the DinD sidecar into every job container. + # Kaniko looks for credentials in /kaniko/.docker by default + options: "-v /run/secrets/docker:/kaniko/.docker:ro" + + # act_runner only allows mounting paths listed here. + valid_volumes: + - /run/secrets/docker + + # The action cache allow reuse of artifacts between jobs + # Disabled for now + cache: + enabled: false + + host: + workdir: /tmp \ No newline at end of file diff --git a/git-forgejo/runner/deployment.yaml b/git-forgejo/runner/deployment.yaml new file mode 100644 index 0000000..d8e00b5 --- /dev/null +++ b/git-forgejo/runner/deployment.yaml @@ -0,0 +1,103 @@ +# ForgeJo Runner : Uses a side-container with DinD +apiVersion: apps/v1 +kind: Deployment +metadata: + name: forgejo-runner + namespace: forgejo +spec: + # Single replica, the concurrency is handled by the runner itself + replicas: 1 + selector: + matchLabels: + app: forgejo-runner + template: + metadata: + labels: + app: forgejo-runner + spec: + containers: + + # Runner : main container + - name: forgejo-runner + image: code.forgejo.org/forgejo/runner:3.3.0 + command: + - /bin/sh + - -c + - | + # Register the runner on first boot if .runner does not exist yet. + # The register step contacts Forgejo, exchanges the registration token + # for a session token, and writes it to /data/.runner. + # On subsequent starts the file already exists and we skip straight to daemon. + if [ ! -f /data/.runner ]; then + forgejo-runner register \ + --no-interactive \ + --config /config/config.yaml \ + --instance "$GITEA_INSTANCE_URL" \ + --token "$GITEA_RUNNER_REGISTRATION_TOKEN" + fi + + exec forgejo-runner daemon --config /config/config.yaml + env: + - name: GITEA_INSTANCE_URL + value: "https://git.qcampos.fr" + + # The runner must talk to DinD for job container management. + - name: DOCKER_HOST + value: "tcp://localhost:2375" + + - name: GITEA_RUNNER_REGISTRATION_TOKEN + valueFrom: + secretKeyRef: + name: forgejo-runner-secret + key: registration-token + + volumeMounts: + - name: config + mountPath: /config + readOnly: true + + # Persistent storage for the .runner file (post-registration session token) + - name: data + mountPath: /data + + # DinD : side container — provides the Docker daemon for job containers + - name: docker-dind + image: docker:dind + env: + # Disable TLS so the runner connects on plain TCP port 2375 + - name: DOCKER_TLS_CERTDIR + value: "" + securityContext: + # Required for DinD to create kernel namespaces and run containers + privileged: true + volumeMounts: + # Persist Docker layer cache across pod restarts to speed up builds + - name: docker-storage + mountPath: /var/lib/docker + + # Registry credentials — mounted here so DinD can bind-mount this + # path into job containers (e.g. Kaniko) via container.options. + # The file is exposed at /run/secrets/docker/config.json. + - name: registry-credentials + mountPath: /run/secrets/docker + readOnly: true + + volumes: + - name: config + configMap: + name: forgejo-runner-config + + - name: data + persistentVolumeClaim: + claimName: forgejo-runner-data + + # emptyDir is fine here — Docker layers are re-pulled after a pod restart, + # which is acceptable on a VPS. Replace with a PVC if cold starts become slow. + - name: docker-storage + emptyDir: {} + + # Docker config.json for the Forgejo registry — injected from a K8s secret. + # DinD bind-mounts this into every job container via container.options in the configmap. + - name: registry-credentials + secret: + secretName: forgejo-registry-secret diff --git a/git-forgejo/runner/pvc.yaml b/git-forgejo/runner/pvc.yaml new file mode 100644 index 0000000..052ba5b --- /dev/null +++ b/git-forgejo/runner/pvc.yaml @@ -0,0 +1,16 @@ +# Stockage persistant pour l'état d'enregistrement du runner (fichier .runner). +# Ce fichier contient le token de session émis par Forgejo après le premier enregistrement. +# Sans ce PVC, le runner se ré-enregistre à chaque redémarrage du pod et crée +# un nouveau runner orphelin dans l'interface Forgejo. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: forgejo-runner-data + namespace: forgejo +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + # Le fichier .runner est minuscule — 100Mi est largement suffisant. + storage: 100Mi diff --git a/git-forgejo/runner/secret.yaml b/git-forgejo/runner/secret.yaml new file mode 100644 index 0000000..e867b82 --- /dev/null +++ b/git-forgejo/runner/secret.yaml @@ -0,0 +1,16 @@ +# Secret contenant le token d'enregistrement du runner. +# Ce token se trouve dans Forgejo : Administration du site → Runners → "Créer un runner". +# Il est utilisé UNE SEULE FOIS au démarrage pour s'enregistrer auprès de Forgejo. +# Après l'enregistrement, Forgejo émet un token de session stocké dans le fichier .runner +# à l'intérieur du pod — ce token d'enregistrement n'est plus nécessaire ensuite. +# +# ⚠️ Ce token est en clair dans le dépôt. Pour un usage en production, privilégier +# Sealed Secrets ou External Secrets Operator. +apiVersion: v1 +kind: Secret +metadata: + name: forgejo-runner-secret + namespace: forgejo +stringData: + # Remplacer par le token copié depuis l'interface Forgejo. + registration-token: "LOqadesvfA2tjVRoyWUxCnzYjmgMhZqhHHT30nnp"