From 6900271f8620982d829b6368d5b46c78a9992cff Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Sat, 25 Jul 2026 06:18:54 +0200 Subject: [PATCH] refactor(woodpecker): dedicated woodpecker KS, retire seed-woodpecker (stage 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructures woodpecker into its own Flux Kustomization instead of splitting its app across the catch-all apps KS and its DB across seed-woodpecker. - Add clusters/homelab/woodpecker.yaml: dedicated KS over apps/woodpecker with the infrastructure-cnpg-barman dep + CNPG Cluster healthCheckExprs (moved off seed-woodpecker) so the CNPG concerns live here, not in the shared apps KS. - Remove woodpecker/ from apps/kustomization.yaml (catch-all apps KS no longer owns the woodpecker app objects). - git mv seed/woodpecker/{cluster,objectstore,scheduled-backup, hetzner-creds-externalsecret}.yaml + MIGRATION.md -> apps/woodpecker/, and add the four DB manifests to apps/woodpecker/kustomization.yaml. - Delete clusters/homelab/seed-woodpecker.yaml and the now-empty kubernetes/seed/woodpecker/. - bootstrap.sh: add a wait_kustomization woodpecker entry (it used to be covered by 'wait apps'); e2e-test.sh: add woodpecker to the KS readiness checks. Safe dual ownership transfer (nothing pruned): every object carries prune: disabled from stage 1 (#394) — the app objects via commonAnnotations, the DB objects per-file — so when the apps KS drops woodpecker/ and seed-woodpecker is deleted, both GC sweeps skip these live objects and the new woodpecker KS adopts them in place. No CNPG restart (Cluster is not a Deployment); no app restart (manifests unchanged, only the owning KS label flips). Verified: kubectl kustomize apps/woodpecker builds 17 objects (13 app + 4 DB incl. wp-pg Cluster), all prune-protected; bash -n bootstrap.sh + e2e-test.sh OK; wp-pg is the sole CNPG cluster in apps ns and hetzner-s3-creds is used only by wp-pg-store; seed/woodpecker fully removed. Stage 3 will drop the transient commonAnnotations (one more accepted app roll). Co-Authored-By: Claude Bot Co-Authored-By: Claude Opus 4.8 (1M context) --- kubernetes/apps/kustomization.yaml | 4 +++- .../{seed => apps}/woodpecker/MIGRATION.md | 0 .../{seed => apps}/woodpecker/cluster.yaml | 0 .../hetzner-creds-externalsecret.yaml | 0 kubernetes/apps/woodpecker/kustomization.yaml | 8 ++++++++ .../{seed => apps}/woodpecker/objectstore.yaml | 0 .../woodpecker/scheduled-backup.yaml | 0 kubernetes/bootstrap.sh | 1 + .../{seed-woodpecker.yaml => woodpecker.yaml} | 17 +++++++++-------- kubernetes/e2e-test.sh | 2 +- kubernetes/seed/woodpecker/kustomization.yaml | 7 ------- 11 files changed, 22 insertions(+), 17 deletions(-) rename kubernetes/{seed => apps}/woodpecker/MIGRATION.md (100%) rename kubernetes/{seed => apps}/woodpecker/cluster.yaml (100%) rename kubernetes/{seed => apps}/woodpecker/hetzner-creds-externalsecret.yaml (100%) rename kubernetes/{seed => apps}/woodpecker/objectstore.yaml (100%) rename kubernetes/{seed => apps}/woodpecker/scheduled-backup.yaml (100%) rename kubernetes/clusters/homelab/{seed-woodpecker.yaml => woodpecker.yaml} (54%) delete mode 100644 kubernetes/seed/woodpecker/kustomization.yaml diff --git a/kubernetes/apps/kustomization.yaml b/kubernetes/apps/kustomization.yaml index afd771dc..cb504ae0 100644 --- a/kubernetes/apps/kustomization.yaml +++ b/kubernetes/apps/kustomization.yaml @@ -8,6 +8,8 @@ resources: - gitea/ - ical-proxy/ - pve/ - - woodpecker/ + # woodpecker/ moved to its own dedicated `woodpecker` Kustomization + # (clusters/homelab/woodpecker.yaml) so its wp-pg CNPG cluster's barman + # dependency + Cluster health-gating don't contaminate this shared apps KS. # Read-only ServiceAccount for the off-site Claude Code workstation. - claude-workstation/ diff --git a/kubernetes/seed/woodpecker/MIGRATION.md b/kubernetes/apps/woodpecker/MIGRATION.md similarity index 100% rename from kubernetes/seed/woodpecker/MIGRATION.md rename to kubernetes/apps/woodpecker/MIGRATION.md diff --git a/kubernetes/seed/woodpecker/cluster.yaml b/kubernetes/apps/woodpecker/cluster.yaml similarity index 100% rename from kubernetes/seed/woodpecker/cluster.yaml rename to kubernetes/apps/woodpecker/cluster.yaml diff --git a/kubernetes/seed/woodpecker/hetzner-creds-externalsecret.yaml b/kubernetes/apps/woodpecker/hetzner-creds-externalsecret.yaml similarity index 100% rename from kubernetes/seed/woodpecker/hetzner-creds-externalsecret.yaml rename to kubernetes/apps/woodpecker/hetzner-creds-externalsecret.yaml diff --git a/kubernetes/apps/woodpecker/kustomization.yaml b/kubernetes/apps/woodpecker/kustomization.yaml index 9435cd54..1fd751c2 100644 --- a/kubernetes/apps/woodpecker/kustomization.yaml +++ b/kubernetes/apps/woodpecker/kustomization.yaml @@ -32,3 +32,11 @@ resources: # (kubernetes/infrastructure/openbao/rotation/woodpecker.yaml) — intra-ns # OpenBao access, no NetworkPolicy needed. server.yaml/agent.yaml keep their # Reloader annotations; externalsecret.yaml keeps the 10m refreshInterval. + # wp-pg CNPG Postgres backend (moved here from the retired seed-woodpecker KS; + # each object carries prune: disabled so ownership transferred without a + # teardown). The dedicated `woodpecker` KS depends on infrastructure-cnpg-barman + # for the barman plugin behind the ObjectStore/ScheduledBackup. + - cluster.yaml + - objectstore.yaml + - scheduled-backup.yaml + - hetzner-creds-externalsecret.yaml diff --git a/kubernetes/seed/woodpecker/objectstore.yaml b/kubernetes/apps/woodpecker/objectstore.yaml similarity index 100% rename from kubernetes/seed/woodpecker/objectstore.yaml rename to kubernetes/apps/woodpecker/objectstore.yaml diff --git a/kubernetes/seed/woodpecker/scheduled-backup.yaml b/kubernetes/apps/woodpecker/scheduled-backup.yaml similarity index 100% rename from kubernetes/seed/woodpecker/scheduled-backup.yaml rename to kubernetes/apps/woodpecker/scheduled-backup.yaml diff --git a/kubernetes/bootstrap.sh b/kubernetes/bootstrap.sh index d157a77f..c5b3ec9f 100755 --- a/kubernetes/bootstrap.sh +++ b/kubernetes/bootstrap.sh @@ -332,6 +332,7 @@ if phase_runs wait-apps; then # is genuinely 5–10 min on a fresh OSD-wiped cluster). wait_kustomization apps "apps" 90 wait_kustomization influxdb "InfluxDB (HR install + token Jobs)" 600 + wait_kustomization woodpecker "Woodpecker CI (incl. wp-pg CNPG backend)" 600 wait_kustomization authentik "Authentik (incl. ak-pg seed)" 600 wait_kustomization monitoring "kube-prometheus-stack (Loki + Prom + AM + Grafana)" 180 wait_kustomization music-assistant "Music Assistant (incl. data seed)" 300 diff --git a/kubernetes/clusters/homelab/seed-woodpecker.yaml b/kubernetes/clusters/homelab/woodpecker.yaml similarity index 54% rename from kubernetes/clusters/homelab/seed-woodpecker.yaml rename to kubernetes/clusters/homelab/woodpecker.yaml index e954c274..5eb61493 100644 --- a/kubernetes/clusters/homelab/seed-woodpecker.yaml +++ b/kubernetes/clusters/homelab/woodpecker.yaml @@ -1,24 +1,25 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: - name: seed-woodpecker + name: woodpecker namespace: flux-system spec: - # Owns the wp-pg CNPG Cluster, its ObjectStore + ScheduledBackup, and the - # Hetzner S3 creds. Provisions the Postgres backend that woodpecker-server - # migrates onto (from its old sqlite-on-PVC), which removes the fragile - # ceph-block snapshot backup path that broke #295/#324. Bootstraps an empty - # DB via initdb; the sqlite->pg data migration is a one-time manual runbook - # (kubernetes/seed/woodpecker/MIGRATION.md). + # Dedicated lifecycle owner of Woodpecker CI: the server/agent app (formerly + # under the catch-all `apps` KS) plus its wp-pg CNPG Cluster + ObjectStore + + # ScheduledBackup (formerly under seed-woodpecker). Pulled into its own KS so + # the CNPG barman dependency and Cluster health-gating live here instead of + # contaminating the shared `apps` KS. Replaces seed-woodpecker. interval: 10m retryInterval: 2m timeout: 30m sourceRef: kind: GitRepository name: flux-system - path: ./kubernetes/seed/woodpecker + path: ./kubernetes/apps/woodpecker prune: true wait: true + # sops-free path: woodpecker-secret + barman creds come from OpenBao via ESO + # (MIGRATION-sops-openbao.md). dependsOn: - name: infrastructure - name: infrastructure-crds diff --git a/kubernetes/e2e-test.sh b/kubernetes/e2e-test.sh index 80b323a7..18579a35 100755 --- a/kubernetes/e2e-test.sh +++ b/kubernetes/e2e-test.sh @@ -108,7 +108,7 @@ check "3 nodes Ready" \ echo "=== Flux Kustomizations ===" for ks in flux-system infrastructure infrastructure-crds infrastructure-ceph-cluster \ seed-authentik seed-immich seed-paperless influxdb \ - apps authentik paperless audiobookshelf; do + apps authentik paperless audiobookshelf woodpecker; do check "kustomization/$ks Ready" \ bash -c "kubectl -n flux-system get kustomization $ks \ -o jsonpath='{.status.conditions[?(@.type==\"Ready\")].status}' | grep -q '^True\$'" diff --git a/kubernetes/seed/woodpecker/kustomization.yaml b/kubernetes/seed/woodpecker/kustomization.yaml deleted file mode 100644 index bb863c2b..00000000 --- a/kubernetes/seed/woodpecker/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - hetzner-creds-externalsecret.yaml - - objectstore.yaml - - cluster.yaml - - scheduled-backup.yaml -- 2.54.0