From 8cbfa6856c3eb44831faf20ed5638b0db36b5cdc Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Sat, 16 May 2026 12:28:54 +0000 Subject: [PATCH] Phase 1a: enroll 4 self-hosted services in Keel auto-update Enrolls the cleanest Woodpecker-build-only self-hosted services into the inject-keel-annotations ClusterPolicy by labeling their namespaces keel.sh/enrolled=true. CI already pushes :latest (auto_tag: true) on each, so Keel will detect the current upstream digest and trigger a rolling restart when polling starts (1h cadence). Per-Deployment lifecycle extended with KYVERNO_LIFECYCLE_V2 to suppress the annotation drift Kyverno will inject (keel.sh/policy, /trigger, /pollSchedule). Services included: - fire-planner - job-hunter - payslip-ingest - recruiter-responder Skipped from Phase 1 for follow-up: - claude-agent-service (user has WIP on main.tf) - claude-memory (Postgres co-deployed; treat in Phase 9 with other DBs) - kms (two Deployments; needs per-resource review) - wealthfolio (sync sidecar pattern; needs review) - chrome-service (deliberate :v4 pin; needs keel.sh/policy: never label) - GHA-migrated repos (10) (need per-repo CI cleanup) - beadboard, freedify (no CI) See docs/plans/2026-05-16-auto-upgrade-apps-{design,plan}.md. Co-Authored-By: Claude Opus 4.7 --- stacks/fire-planner/main.tf | 9 ++++++++- stacks/job-hunter/main.tf | 9 ++++++++- stacks/payslip-ingest/main.tf | 9 ++++++++- stacks/recruiter-responder/main.tf | 9 ++++++++- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/stacks/fire-planner/main.tf b/stacks/fire-planner/main.tf index fa056e9f..cdc895a0 100644 --- a/stacks/fire-planner/main.tf +++ b/stacks/fire-planner/main.tf @@ -33,6 +33,8 @@ resource "kubernetes_namespace" "fire_planner" { # for headless verification (NetworkPolicy in chrome-service ns admits # any namespace carrying this label). "chrome-service.viktorbarzin.me/client" = "true" + # Opt into Keel auto-update (inject-keel-annotations ClusterPolicy). + "keel.sh/enrolled" = "true" } } lifecycle { @@ -311,7 +313,12 @@ resource "kubernetes_deployment" "fire_planner" { } lifecycle { - ignore_changes = [spec[0].template[0].spec[0].dns_config] # KYVERNO_LIFECYCLE_V1 + ignore_changes = [ + spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1 + metadata[0].annotations["keel.sh/policy"], + metadata[0].annotations["keel.sh/trigger"], + metadata[0].annotations["keel.sh/pollSchedule"], # KYVERNO_LIFECYCLE_V2 + ] } depends_on = [ diff --git a/stacks/job-hunter/main.tf b/stacks/job-hunter/main.tf index 46f208ff..679a4d16 100644 --- a/stacks/job-hunter/main.tf +++ b/stacks/job-hunter/main.tf @@ -21,6 +21,8 @@ resource "kubernetes_namespace" "job_hunter" { labels = { tier = local.tiers.aux "istio-injection" = "disabled" + # Opt into Keel auto-update (inject-keel-annotations ClusterPolicy). + "keel.sh/enrolled" = "true" } } lifecycle { @@ -264,7 +266,12 @@ resource "kubernetes_deployment" "job_hunter" { } lifecycle { - ignore_changes = [spec[0].template[0].spec[0].dns_config] # KYVERNO_LIFECYCLE_V1 + ignore_changes = [ + spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1 + metadata[0].annotations["keel.sh/policy"], + metadata[0].annotations["keel.sh/trigger"], + metadata[0].annotations["keel.sh/pollSchedule"], # KYVERNO_LIFECYCLE_V2 + ] } depends_on = [ diff --git a/stacks/payslip-ingest/main.tf b/stacks/payslip-ingest/main.tf index 5782092f..dc3c5af2 100644 --- a/stacks/payslip-ingest/main.tf +++ b/stacks/payslip-ingest/main.tf @@ -23,6 +23,8 @@ resource "kubernetes_namespace" "payslip_ingest" { labels = { tier = local.tiers.aux "istio-injection" = "disabled" + # Opt into Keel auto-update (inject-keel-annotations ClusterPolicy). + "keel.sh/enrolled" = "true" } } lifecycle { @@ -296,7 +298,12 @@ resource "kubernetes_deployment" "payslip_ingest" { } lifecycle { - ignore_changes = [spec[0].template[0].spec[0].dns_config] # KYVERNO_LIFECYCLE_V1 + ignore_changes = [ + spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1 + metadata[0].annotations["keel.sh/policy"], + metadata[0].annotations["keel.sh/trigger"], + metadata[0].annotations["keel.sh/pollSchedule"], # KYVERNO_LIFECYCLE_V2 + ] } depends_on = [ diff --git a/stacks/recruiter-responder/main.tf b/stacks/recruiter-responder/main.tf index f7aafd51..482ae15f 100644 --- a/stacks/recruiter-responder/main.tf +++ b/stacks/recruiter-responder/main.tf @@ -25,6 +25,8 @@ resource "kubernetes_namespace" "recruiter_responder" { labels = { tier = local.tiers.aux "istio-injection" = "disabled" + # Opt into Keel auto-update (inject-keel-annotations ClusterPolicy). + "keel.sh/enrolled" = "true" } } lifecycle { @@ -286,7 +288,12 @@ resource "kubernetes_deployment" "recruiter_responder" { } lifecycle { - ignore_changes = [spec[0].template[0].spec[0].dns_config] # KYVERNO_LIFECYCLE_V1 + ignore_changes = [ + spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1 + metadata[0].annotations["keel.sh/policy"], + metadata[0].annotations["keel.sh/trigger"], + metadata[0].annotations["keel.sh/pollSchedule"], # KYVERNO_LIFECYCLE_V2 + ] } depends_on = [