From 9f5a25a41ed292576e27be59f902270e63636eaf Mon Sep 17 00:00:00 2001 From: Tom Brow Date: Tue, 6 Oct 2026 19:31:43 -0700 Subject: [PATCH] feat(push): support Deployment metadata annotations (#8136) Consumers currently need a Kustomize patch to place secret-reloader annotations on the gateway Deployment. Add optional `deploymentAnnotations` so they can express that configuration through Helm values. The setting applies only to Deployment metadata. The chart's release-namespace and external-network-policy annotations remain reserved and cannot be overridden. ### Validation Full gateway chart render suite passes, including schema rejection of reserved keys and non-string values, preservation of external-policy ownership markers, and unchanged Pod annotations and migration hooks. Repository-wide `just ci` passed with `RUST_TEST_THREADS=1`. The first parallel run failed five unrelated timing/transport tests; all five passed isolated reruns and the full serialized run completed successfully. `buzz-review-completed`: Codex review is clean on the current commit and agent render validation exercises the change. Tom confirmed the repository human-testing requirement does not apply to this chart-only change; personal human testing is not claimed. Signed-off-by: Tom Brow --- deploy/charts/buzz-push-gateway/README.md | 7 +++++ .../templates/deployment.yaml | 9 ++++--- .../tests/migration-annotations.sh | 27 +++++++++++++++++++ .../buzz-push-gateway/values.schema.json | 10 +++++++ deploy/charts/buzz-push-gateway/values.yaml | 3 +++ 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/deploy/charts/buzz-push-gateway/README.md b/deploy/charts/buzz-push-gateway/README.md index b461e3ba7d..e0569a134b 100644 --- a/deploy/charts/buzz-push-gateway/README.md +++ b/deploy/charts/buzz-push-gateway/README.md @@ -45,3 +45,10 @@ both ingress and egress isolation. It emits no manifests on failure and preserve successful output byte-for-byte. Parent CI must run this same gate on its complete render; a subchart-only render intentionally fails in external-policy mode. The deployment owner must separately validate the allowed traffic and rolling drain. + +## Deployment annotations + +Use `deploymentAnnotations` for Deployment metadata such as +`secret.reloader.stakater.com/reload`. These do not apply to runtime Pods or +migration Jobs. Values must be strings; `buzz.block.xyz/release-namespace` and +`buzz.block.xyz/external-network-policy` are reserved for chart policy ownership. diff --git a/deploy/charts/buzz-push-gateway/templates/deployment.yaml b/deploy/charts/buzz-push-gateway/templates/deployment.yaml index 287ab67b3b..bee0ec8a41 100644 --- a/deploy/charts/buzz-push-gateway/templates/deployment.yaml +++ b/deploy/charts/buzz-push-gateway/templates/deployment.yaml @@ -3,10 +3,13 @@ kind: Deployment metadata: name: {{ include "push.name" . }} labels: {{- include "push.runtimeLabels" . | nindent 4 }} + {{- $annotations := deepCopy .Values.deploymentAnnotations }} {{- if not .Values.networkPolicy.enabled }} - annotations: - buzz.block.xyz/release-namespace: {{ .Release.Namespace | quote }} - buzz.block.xyz/external-network-policy: {{ .Values.networkPolicy.externalPolicyName | quote }} + {{- $_ := set $annotations "buzz.block.xyz/release-namespace" .Release.Namespace }} + {{- $_ := set $annotations "buzz.block.xyz/external-network-policy" .Values.networkPolicy.externalPolicyName }} + {{- end }} + {{- with $annotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} spec: replicas: {{ .Values.replicaCount }} diff --git a/deploy/charts/buzz-push-gateway/tests/migration-annotations.sh b/deploy/charts/buzz-push-gateway/tests/migration-annotations.sh index fdeb627031..345b40f4d0 100644 --- a/deploy/charts/buzz-push-gateway/tests/migration-annotations.sh +++ b/deploy/charts/buzz-push-gateway/tests/migration-annotations.sh @@ -5,6 +5,7 @@ out=$(mktemp -d) trap 'rm -rf "$out"' EXIT helm template push "$chart" >"$out/default.yaml" helm template push "$chart" \ + --set-string 'deploymentAnnotations.secret\.reloader\.stakater\.com/reload=buzz-push-gateway' \ --set-string 'migration.podAnnotations.sidecar\.istio\.io/inject=false' \ --set-string 'podAnnotations.example\.com/runtime=enabled' >"$out/annotated.yaml" env -u GEM_HOME -u GEM_PATH -u RUBYLIB -u RUBYOPT ruby -ryaml - "$out" <<'RUBY' @@ -12,6 +13,7 @@ base, changed = %w[default annotated].map { |name| YAML.load_stream(File.read("# job = changed.find { |r| r['kind'] == 'Job' } raise 'migration annotation missing or not a string' unless job.dig('spec', 'template', 'metadata').delete('annotations') == {'sidecar.istio.io/inject' => 'false'} runtime = changed.find { |r| r['kind'] == 'Deployment' } +raise 'Deployment annotation missing' unless runtime['metadata'].delete('annotations') == {'secret.reloader.stakater.com/reload' => 'buzz-push-gateway'} raise 'runtime annotations changed' unless runtime.dig('spec', 'template', 'metadata').delete('annotations') == {'example.com/runtime' => 'enabled'} raise 'annotations changed other resources or hook metadata' unless base == changed RUBY @@ -25,3 +27,28 @@ for value in true 7; do exit 1 fi done + +for key in release-namespace external-network-policy; do + if helm template push "$chart" --set-string "deploymentAnnotations.buzz\.block\.xyz/$key=override" >"$out/invalid.log" 2>&1; then + echo 'expected reserved Deployment annotation to fail schema validation' >&2 + exit 1 + fi + grep -q 'deploymentAnnotations' "$out/invalid.log" +done +if helm template push "$chart" --set deploymentAnnotations.invalid=true >"$out/invalid.log" 2>&1; then + echo 'expected non-string Deployment annotation to fail schema validation' >&2 + exit 1 +fi +grep -q 'deploymentAnnotations' "$out/invalid.log" +helm template push "$chart" --namespace tenant-runtime \ + --set networkPolicy.enabled=false --set networkPolicy.externalPolicyName=platform-runtime \ + --set-string 'deploymentAnnotations.secret\.reloader\.stakater\.com/reload=buzz-push-gateway' >"$out/external.yaml" +env -u GEM_HOME -u GEM_PATH -u RUBYLIB -u RUBYOPT ruby -ryaml - "$out/external.yaml" <<'RUBY' +resources = YAML.load_stream(File.read(ARGV[0])).compact +deployment = resources.find { |r| r['kind'] == 'Deployment' } +raise 'ownership annotations not preserved' unless deployment['metadata']['annotations'] == { + 'secret.reloader.stakater.com/reload' => 'buzz-push-gateway', + 'buzz.block.xyz/release-namespace' => 'tenant-runtime', + 'buzz.block.xyz/external-network-policy' => 'platform-runtime' +} +RUBY diff --git a/deploy/charts/buzz-push-gateway/values.schema.json b/deploy/charts/buzz-push-gateway/values.schema.json index 4afad6edd0..5a9befcccf 100644 --- a/deploy/charts/buzz-push-gateway/values.schema.json +++ b/deploy/charts/buzz-push-gateway/values.schema.json @@ -34,6 +34,16 @@ } }, "apnsKey": false, + "deploymentAnnotations": { + "type": "object", + "properties": { + "buzz.block.xyz/release-namespace": false, + "buzz.block.xyz/external-network-policy": false + }, + "additionalProperties": { + "type": "string" + } + }, "podAnnotations": { "type": "object", "additionalProperties": { diff --git a/deploy/charts/buzz-push-gateway/values.yaml b/deploy/charts/buzz-push-gateway/values.yaml index 92960444f6..2bad78d731 100644 --- a/deploy/charts/buzz-push-gateway/values.yaml +++ b/deploy/charts/buzz-push-gateway/values.yaml @@ -37,6 +37,9 @@ appAttestRoot: secretKey: app-attest-root.pem service: port: 8080 +# Optional Deployment metadata, independent of runtime and migration Pods. +# The chart owns buzz.block.xyz/release-namespace and external-network-policy. +deploymentAnnotations: {} podAnnotations: {} httpRoute: # Disabled by default so a generic install cannot claim an unattached route.