From fd885b553004520ce5ed5dffdb085957d01a80cd Mon Sep 17 00:00:00 2001 From: Tom Brow Date: Mon, 5 Oct 2026 11:39:20 -0700 Subject: [PATCH] feat(push): support migration pod annotations (#8105) Allow operators to configure migration Pod annotations independently of runtime Pod annotations. This lets clusters with automatic sidecar injection opt the migration Job out without changing the gateway Deployment or Helm hook metadata. The new string-map setting defaults to empty. Chart version 0.3.3 is prepared here; publication requires a separate approved chart release PR. ### Validation The full chart render suite and focused migration annotation tests pass. Tests verify unchanged default resources and hooks, independent runtime annotations, and rejection of non-string annotation values. Independent agent review found no blockers. Repository-wide `just ci` exited 1 in unchanged `buzz-acp` tests: idle/stdout keepalive timing and steering assertions (one failure in the first group, four in the second). Subsequent recipes were not reached. No rerun or unrelated code fix was attempted. Human testing remains pending. Signed-off-by: Tom Brow --- deploy/charts/buzz-push-gateway/Chart.yaml | 2 +- .../templates/migration-job.yaml | 3 +++ .../tests/migration-annotations.sh | 27 +++++++++++++++++++ .../charts/buzz-push-gateway/tests/render.sh | 1 + .../buzz-push-gateway/values.schema.json | 6 +++++ deploy/charts/buzz-push-gateway/values.yaml | 2 ++ 6 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 deploy/charts/buzz-push-gateway/tests/migration-annotations.sh diff --git a/deploy/charts/buzz-push-gateway/Chart.yaml b/deploy/charts/buzz-push-gateway/Chart.yaml index a72de0b66a..e1dfa24704 100644 --- a/deploy/charts/buzz-push-gateway/Chart.yaml +++ b/deploy/charts/buzz-push-gateway/Chart.yaml @@ -3,6 +3,6 @@ apiVersion: v2 # branches (see docs/push-gateway-deployment.md, "Gateway chart release"). name: buzz-push-gateway description: Public capability-gated APNs last-hop gateway for Buzz -version: 0.3.2 +version: 0.3.3 appVersion: "0.1.0" type: application diff --git a/deploy/charts/buzz-push-gateway/templates/migration-job.yaml b/deploy/charts/buzz-push-gateway/templates/migration-job.yaml index d9d01c6048..a68b8a4394 100644 --- a/deploy/charts/buzz-push-gateway/templates/migration-job.yaml +++ b/deploy/charts/buzz-push-gateway/templates/migration-job.yaml @@ -11,6 +11,9 @@ spec: backoffLimit: 3 template: metadata: + {{- with .Values.migration.podAnnotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} labels: {{- include "push.migrationLabels" . | nindent 8 }} spec: restartPolicy: Never diff --git a/deploy/charts/buzz-push-gateway/tests/migration-annotations.sh b/deploy/charts/buzz-push-gateway/tests/migration-annotations.sh new file mode 100644 index 0000000000..fdeb627031 --- /dev/null +++ b/deploy/charts/buzz-push-gateway/tests/migration-annotations.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail +chart=deploy/charts/buzz-push-gateway +out=$(mktemp -d) +trap 'rm -rf "$out"' EXIT +helm template push "$chart" >"$out/default.yaml" +helm template push "$chart" \ + --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' +base, changed = %w[default annotated].map { |name| YAML.load_stream(File.read("#{ARGV[0]}/#{name}.yaml")).compact } +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 '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 +for value in true 7; do + if helm template push "$chart" --set "migration.podAnnotations.invalid=$value" >"$out/invalid.log" 2>&1; then + echo 'expected non-string migration annotation to fail schema validation' >&2 + exit 1 + fi + if ! grep -Eq 'Expected: string|want string' "$out/invalid.log"; then + cat "$out/invalid.log" >&2 + exit 1 + fi +done diff --git a/deploy/charts/buzz-push-gateway/tests/render.sh b/deploy/charts/buzz-push-gateway/tests/render.sh index efba0c0943..4dae7a6821 100755 --- a/deploy/charts/buzz-push-gateway/tests/render.sh +++ b/deploy/charts/buzz-push-gateway/tests/render.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -euo pipefail bash deploy/charts/buzz-push-gateway/tests/grant-lifetime.sh +bash deploy/charts/buzz-push-gateway/tests/migration-annotations.sh out=$(mktemp); production_out=$(mktemp); route_out=$(mktemp); datadog_out=$(mktemp) trap 'rm -f "$out" "$production_out" "$route_out" "$datadog_out" "${monitoring_out:-}"' EXIT gateway_origin_arg=(--set 'gatewayOrigin=https://push.example') diff --git a/deploy/charts/buzz-push-gateway/values.schema.json b/deploy/charts/buzz-push-gateway/values.schema.json index b2e785e33f..80a21c3b80 100644 --- a/deploy/charts/buzz-push-gateway/values.schema.json +++ b/deploy/charts/buzz-push-gateway/values.schema.json @@ -239,6 +239,12 @@ }, "resources": { "type": "object" + }, + "podAnnotations": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } diff --git a/deploy/charts/buzz-push-gateway/values.yaml b/deploy/charts/buzz-push-gateway/values.yaml index 237bc874ee..9a42afde8b 100644 --- a/deploy/charts/buzz-push-gateway/values.yaml +++ b/deploy/charts/buzz-push-gateway/values.yaml @@ -10,6 +10,8 @@ existingSecret: buzz-push-gateway # DDL-capable credentials are used only by the pre-install/pre-upgrade migration # Job. Runtime DATABASE_URL in existingSecret should have DML-only privileges. migration: + # Applies only to migration Pods, independently of runtime podAnnotations. + podAnnotations: {} existingSecret: buzz-push-gateway-migrations databaseUrlKey: DATABASE_URL # Existing LOGIN role used by runtime DATABASE_URL. Migrations grant it only