From 69620e53589455b6dc96a0e86eaffb09402e81f4 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 3 Jul 2026 14:32:12 +0000 Subject: [PATCH] fix: roll branch follower on config changes --- config/cicd-branch-followers.yaml | 1 + scripts/src/cicd-controller-render.ts | 29 ++++++++++++++++++--------- scripts/src/cicd-types.ts | 1 + scripts/src/cicd.ts | 1 + 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/config/cicd-branch-followers.yaml b/config/cicd-branch-followers.yaml index 18ec0a76..cbe5c4e9 100644 --- a/config/cicd-branch-followers.yaml +++ b/config/cicd-branch-followers.yaml @@ -45,6 +45,7 @@ controller: intervalSeconds: 30 reconcileTimeoutSeconds: 110 leaseDurationSeconds: 140 + terminationGracePeriodSeconds: 30 budgets: applyWaitSeconds: 120 statusSeconds: 35 diff --git a/scripts/src/cicd-controller-render.ts b/scripts/src/cicd-controller-render.ts index e351af29..1e9deab0 100644 --- a/scripts/src/cicd-controller-render.ts +++ b/scripts/src/cicd-controller-render.ts @@ -1,5 +1,6 @@ // SPEC: PJ2026-01060703 CI/CD branch follower controller render helpers. // Responsibility: Kubernetes controller/reconcile Job manifests and controller bootstrap scripts. +import { createHash } from "node:crypto"; import { readFileSync } from "node:fs"; import { rootPath } from "./config"; import { shQuote } from "./platform-infra-ops-library"; @@ -86,6 +87,16 @@ export function waitForJobShell(namespace: string, jobName: string, timeoutSecon export function renderControllerManifests(registry: BranchFollowerRegistry): Record[] { const labels = registry.controller.labels; const selector = labels; + const controllerConfigData = { + "cicd-branch-followers.yaml": registry.rawText, + "sync-source.sh": nativeCicdScript("sync-source.sh"), + "controller-one-shot.sh": nativeCicdScript("controller-one-shot.sh"), + "controller-loop.sh": nativeCicdScript("controller-loop.sh"), + "hwlab-node-control-plane-refresh.mjs": nativeCicdScript("hwlab-node-control-plane-refresh.mjs"), + "github-proxy-connect.mjs": nativeCicdScript("github-proxy-connect.mjs"), + "git-ssh-proxy.sh": nativeCicdScript("git-ssh-proxy.sh"), + }; + const controllerConfigSha = sha256(JSON.stringify(controllerConfigData)); return [ { apiVersion: "v1", @@ -141,15 +152,7 @@ export function renderControllerManifests(registry: BranchFollowerRegistry): Rec apiVersion: "v1", kind: "ConfigMap", metadata: { name: registry.controller.configMapName, namespace: registry.controller.namespace, labels }, - data: { - "cicd-branch-followers.yaml": registry.rawText, - "sync-source.sh": nativeCicdScript("sync-source.sh"), - "controller-one-shot.sh": nativeCicdScript("controller-one-shot.sh"), - "controller-loop.sh": nativeCicdScript("controller-loop.sh"), - "hwlab-node-control-plane-refresh.mjs": nativeCicdScript("hwlab-node-control-plane-refresh.mjs"), - "github-proxy-connect.mjs": nativeCicdScript("github-proxy-connect.mjs"), - "git-ssh-proxy.sh": nativeCicdScript("git-ssh-proxy.sh"), - }, + data: controllerConfigData, }, { apiVersion: "v1", @@ -159,6 +162,7 @@ export function renderControllerManifests(registry: BranchFollowerRegistry): Rec _createdAt: new Date().toISOString(), _specRef: SPEC_REF, _registrySha256: registry.rawSha256, + _controllerConfigSha256: controllerConfigSha, }, }, { @@ -180,12 +184,13 @@ export function renderControllerManifests(registry: BranchFollowerRegistry): Rec annotations: { "unidesk.pikapython.com/spec-ref": SPEC_REF, "unidesk.pikapython.com/registry-sha256": registry.rawSha256, + "unidesk.pikapython.com/controller-config-sha256": controllerConfigSha, "unidesk.pikapython.com/host-worktree-authority": "false", }, }, spec: { serviceAccountName: registry.controller.serviceAccountName, - terminationGracePeriodSeconds: 30, + terminationGracePeriodSeconds: registry.controller.loop.terminationGracePeriodSeconds, volumes: [ { name: "registry", configMap: { name: registry.controller.configMapName, defaultMode: 0o755 } }, { name: "git-mirror-cache", persistentVolumeClaim: { claimName: registry.controller.source.gitMirrorCachePvcName } }, @@ -227,3 +232,7 @@ export function renderControllerManifests(registry: BranchFollowerRegistry): Rec function nativeCicdScript(name: string): string { return readFileSync(rootPath("scripts/native/cicd", name), "utf8"); } + +function sha256(value: string): string { + return createHash("sha256").update(value).digest("hex"); +} diff --git a/scripts/src/cicd-types.ts b/scripts/src/cicd-types.ts index 8a2bced1..860d1a7a 100644 --- a/scripts/src/cicd-types.ts +++ b/scripts/src/cicd-types.ts @@ -152,6 +152,7 @@ export interface ControllerSpec { intervalSeconds: number; reconcileTimeoutSeconds: number; leaseDurationSeconds: number; + terminationGracePeriodSeconds: number; }; budgets: { applyWaitSeconds: number; diff --git a/scripts/src/cicd.ts b/scripts/src/cicd.ts index 0d97fac3..c455b470 100644 --- a/scripts/src/cicd.ts +++ b/scripts/src/cicd.ts @@ -280,6 +280,7 @@ function parseController(root: Record): ControllerSpec { intervalSeconds: integerField(loop, "intervalSeconds", "controller.loop"), reconcileTimeoutSeconds: integerField(loop, "reconcileTimeoutSeconds", "controller.loop"), leaseDurationSeconds: integerField(loop, "leaseDurationSeconds", "controller.loop"), + terminationGracePeriodSeconds: integerField(loop, "terminationGracePeriodSeconds", "controller.loop"), }, budgets: { applyWaitSeconds: integerField(budgets, "applyWaitSeconds", "controller.budgets"),