From 8d825fe3ef802661010a2900e2d9e83fd13ecdd4 Mon Sep 17 00:00:00 2001 From: kina0630 Date: Tue, 16 Jun 2026 10:45:50 +0800 Subject: [PATCH 1/2] feat(helm): roll deployment on agent-config change via checksum annotation Subpath-mounted ConfigMap changes do not refresh in a running pod and the Deployment had no config-checksum annotation, so config edits required a manual `kubectl rollout restart`. Add the standard checksum/config pod annotation hashing configmap-agent-config.yaml so any config change triggers a rollout automatically. Pre-existing podAnnotations still merge in. Co-Authored-By: Claude Opus 4.8 --- coding-agent/helm/templates/deployment.yaml | 5 +++-- coding-agent/tests/deploy/test_helm_chart.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/coding-agent/helm/templates/deployment.yaml b/coding-agent/helm/templates/deployment.yaml index 799753f4f..bc222000a 100644 --- a/coding-agent/helm/templates/deployment.yaml +++ b/coding-agent/helm/templates/deployment.yaml @@ -13,10 +13,11 @@ spec: metadata: labels: {{- include "coding-agent.selectorLabels" . | nindent 8 }} - {{- with .Values.podAnnotations }} annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap-agent-config.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} spec: serviceAccountName: {{ include "coding-agent.serviceAccountName" . }} automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} diff --git a/coding-agent/tests/deploy/test_helm_chart.py b/coding-agent/tests/deploy/test_helm_chart.py index e11257c59..259ea9fbe 100644 --- a/coding-agent/tests/deploy/test_helm_chart.py +++ b/coding-agent/tests/deploy/test_helm_chart.py @@ -178,6 +178,21 @@ def test_helm_default_runtime_contract_is_runnable() -> None: assert "--allow-unauthenticated" not in main["command"] +def test_helm_agent_config_checksum_annotation_changes_with_config() -> None: + default_docs = _render() + custom_docs = _render("--set", "agent.config.model=claude-test-checksum") + + default_annotations = _deployment(default_docs)["spec"]["template"]["metadata"][ + "annotations" + ] + custom_annotations = _deployment(custom_docs)["spec"]["template"]["metadata"][ + "annotations" + ] + + assert re.fullmatch(r"[0-9a-f]{64}", default_annotations["checksum/config"]) + assert custom_annotations["checksum/config"] != default_annotations["checksum/config"] + + def test_helm_default_creates_unprivileged_service_account_without_rbac() -> None: docs = _render() From b46881f00d38da08f7d9f6d03217fee985e90f32 Mon Sep 17 00:00:00 2001 From: kina0630 Date: Tue, 16 Jun 2026 11:06:51 +0800 Subject: [PATCH 2/2] fix(helm): computed checksum/config wins over user podAnnotations Render the computed checksum/config annotation after .Values.podAnnotations so a user-supplied checksum/config key cannot override it and silently defeat the auto-rollout guarantee. Add a precedence regression test. Addresses CodeRabbit review on #606. Co-Authored-By: Claude Opus 4.8 --- coding-agent/helm/templates/deployment.yaml | 2 +- coding-agent/tests/deploy/test_helm_chart.py | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/coding-agent/helm/templates/deployment.yaml b/coding-agent/helm/templates/deployment.yaml index bc222000a..342532aaf 100644 --- a/coding-agent/helm/templates/deployment.yaml +++ b/coding-agent/helm/templates/deployment.yaml @@ -14,10 +14,10 @@ spec: labels: {{- include "coding-agent.selectorLabels" . | nindent 8 }} annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap-agent-config.yaml") . | sha256sum }} {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} + checksum/config: {{ include (print $.Template.BasePath "/configmap-agent-config.yaml") . | sha256sum }} spec: serviceAccountName: {{ include "coding-agent.serviceAccountName" . }} automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} diff --git a/coding-agent/tests/deploy/test_helm_chart.py b/coding-agent/tests/deploy/test_helm_chart.py index 259ea9fbe..4e417ab59 100644 --- a/coding-agent/tests/deploy/test_helm_chart.py +++ b/coding-agent/tests/deploy/test_helm_chart.py @@ -178,9 +178,18 @@ def test_helm_default_runtime_contract_is_runnable() -> None: assert "--allow-unauthenticated" not in main["command"] -def test_helm_agent_config_checksum_annotation_changes_with_config() -> None: +def test_helm_agent_config_checksum_annotation_changes_with_config( + tmp_path: Path, +) -> None: default_docs = _render() custom_docs = _render("--set", "agent.config.model=claude-test-checksum") + override_values = tmp_path / "values.yaml" + override_values.write_text( + "podAnnotations:\n" + " checksum/config: user-override-value\n", + encoding="utf-8", + ) + override_docs = _render("-f", str(override_values)) default_annotations = _deployment(default_docs)["spec"]["template"]["metadata"][ "annotations" @@ -188,8 +197,14 @@ def test_helm_agent_config_checksum_annotation_changes_with_config() -> None: custom_annotations = _deployment(custom_docs)["spec"]["template"]["metadata"][ "annotations" ] + override_annotations = _deployment(override_docs)["spec"]["template"]["metadata"][ + "annotations" + ] assert re.fullmatch(r"[0-9a-f]{64}", default_annotations["checksum/config"]) + assert re.fullmatch(r"[0-9a-f]{64}", override_annotations["checksum/config"]) + assert override_annotations["checksum/config"] == default_annotations["checksum/config"] + assert override_annotations["checksum/config"] != "user-override-value" assert custom_annotations["checksum/config"] != default_annotations["checksum/config"]