From 978bcffc9113d1773f68ce443478d6908bbd7f08 Mon Sep 17 00:00:00 2001 From: jedarden Date: Thu, 23 Apr 2026 23:07:29 -0400 Subject: [PATCH] fix(manifests): pin all ronaldraygun images to SHA digests, add image-updater annotations Replace :latest with @sha256: digest for acb-api, acb-evolver, acb-index-builder, acb-matchmaker, and acb-worker. Add argocd-image-updater annotations to all five deployments to auto-track future sha-* tag builds. Add missing deployment manifests for index-builder, matchmaker, and worker. Co-Authored-By: Claude Sonnet 4.6 --- .needle-predispatch-sha | 2 +- manifests/acb-api-deployment.yml | 7 +- manifests/acb-evolver-deployment.yml | 7 +- manifests/acb-index-builder-deployment.yml | 127 +++++++++++++++++++++ manifests/acb-matchmaker-deployment.yml | 93 +++++++++++++++ manifests/acb-worker-deployment.yml | 102 +++++++++++++++++ 6 files changed, 335 insertions(+), 3 deletions(-) create mode 100644 manifests/acb-index-builder-deployment.yml create mode 100644 manifests/acb-matchmaker-deployment.yml create mode 100644 manifests/acb-worker-deployment.yml diff --git a/.needle-predispatch-sha b/.needle-predispatch-sha index 3d1880b..a29e837 100644 --- a/.needle-predispatch-sha +++ b/.needle-predispatch-sha @@ -1 +1 @@ -fddcc0ba34f2ce3a57a17122826ef7963f8bf7d3 +283e0df5e51e79930353f5913a131b436b494ba5 diff --git a/manifests/acb-api-deployment.yml b/manifests/acb-api-deployment.yml index 761bd27..da53b5f 100644 --- a/manifests/acb-api-deployment.yml +++ b/manifests/acb-api-deployment.yml @@ -13,6 +13,11 @@ metadata: labels: app.kubernetes.io/name: acb-api app.kubernetes.io/part-of: ai-code-battle + annotations: + argocd-image-updater.argoproj.io/image-list: app=ronaldraygun/acb-api + argocd-image-updater.argoproj.io/app.update-strategy: name + argocd-image-updater.argoproj.io/app.allow-tags: 'regexp:^sha-[0-9a-f]+$' + argocd-image-updater.argoproj.io/write-back-method: argocd spec: replicas: 1 selector: @@ -27,7 +32,7 @@ spec: restartPolicy: Always containers: - name: api - image: ronaldraygun/acb-api:latest + image: ronaldraygun/acb-api@sha256:82e20d034f4098442b094bd6590673b09f8bbd78c5c5f5e1f5079c677564dc83 imagePullPolicy: Always ports: - containerPort: 8080 diff --git a/manifests/acb-evolver-deployment.yml b/manifests/acb-evolver-deployment.yml index b56beec..bc97469 100644 --- a/manifests/acb-evolver-deployment.yml +++ b/manifests/acb-evolver-deployment.yml @@ -18,6 +18,11 @@ metadata: labels: app.kubernetes.io/name: acb-evolver app.kubernetes.io/part-of: ai-code-battle + annotations: + argocd-image-updater.argoproj.io/image-list: app=ronaldraygun/acb-evolver + argocd-image-updater.argoproj.io/app.update-strategy: name + argocd-image-updater.argoproj.io/app.allow-tags: 'regexp:^sha-[0-9a-f]+$' + argocd-image-updater.argoproj.io/write-back-method: argocd spec: replicas: 1 selector: @@ -33,7 +38,7 @@ spec: restartPolicy: Always containers: - name: evolver - image: ronaldraygun/acb-evolver:latest + image: ronaldraygun/acb-evolver@sha256:15f72e07037585734a4417f5d7402463ed846c6fc73e55e4e58bc71787c6465d imagePullPolicy: Always args: ["run", "-continuous"] ports: diff --git a/manifests/acb-index-builder-deployment.yml b/manifests/acb-index-builder-deployment.yml new file mode 100644 index 0000000..26ece13 --- /dev/null +++ b/manifests/acb-index-builder-deployment.yml @@ -0,0 +1,127 @@ +# acb-index-builder: Static index generation and deployment for AI Code Battle +# Reads PostgreSQL, generates JSON indexes every 15m, deploys to Cloudflare Pages +# every ~90m, manages R2 warm cache (promote from armor/B2, prune old). +# Self-restarts every 4h to prevent memory leaks. +# +# Staging file — sync to declarative-config/k8s/iad-acb/ai-code-battle/ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: acb-index-builder + namespace: ai-code-battle + labels: + app.kubernetes.io/component: index-builder + app.kubernetes.io/name: acb-index-builder + app.kubernetes.io/part-of: ai-code-battle + annotations: + argocd-image-updater.argoproj.io/image-list: app=ronaldraygun/acb-index-builder + argocd-image-updater.argoproj.io/app.update-strategy: name + argocd-image-updater.argoproj.io/app.allow-tags: 'regexp:^sha-[0-9a-f]+$' + argocd-image-updater.argoproj.io/write-back-method: argocd + reloader.stakater.com/auto: "true" +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: acb-index-builder + strategy: + type: Recreate + template: + metadata: + labels: + app.kubernetes.io/component: index-builder + app.kubernetes.io/name: acb-index-builder + app.kubernetes.io/part-of: ai-code-battle + annotations: + reloader.stakater.com/auto: "true" + spec: + restartPolicy: Always + containers: + - name: index-builder + image: ronaldraygun/acb-index-builder@sha256:a19c311f0166f2cb969d389a56dc7c9ed4a5c6913c6b4c9a817fb18de078c469 + imagePullPolicy: Always + env: + - name: ACB_POSTGRES_HOST + value: "acb-postgres" + - name: ACB_POSTGRES_PORT + value: "5432" + - name: ACB_POSTGRES_DATABASE + value: "ai_code_battle" + - name: ACB_POSTGRES_USER + valueFrom: + secretKeyRef: + name: acb-postgres-credentials + key: username + - name: ACB_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: acb-postgres-credentials + key: password + - name: ACB_BUILD_INTERVAL + value: "15m" + - name: ACB_DEPLOY_INTERVAL + value: "6" + - name: ACB_MAX_LIFETIME + value: "4h" + - name: ACB_BUILD_TIMEOUT + value: "10m" + - name: ACB_OUTPUT_DIR + value: "/data" + - name: ACB_CLOUDFLARE_API_TOKEN + valueFrom: + secretKeyRef: + name: acb-cloudflare-api-token + key: token + - name: ACB_CLOUDFLARE_ACCOUNT_ID + valueFrom: + secretKeyRef: + name: acb-cloudflare-api-token + key: account-id + - name: ACB_PAGES_PROJECT + value: "ai-code-battle" + - name: ACB_R2_ENDPOINT + valueFrom: + secretKeyRef: + name: acb-r2-credentials + key: endpoint + - name: ACB_R2_BUCKET + valueFrom: + secretKeyRef: + name: acb-r2-credentials + key: bucket + - name: ACB_R2_ACCESS_KEY + valueFrom: + secretKeyRef: + name: acb-r2-credentials + key: access-key + - name: ACB_R2_SECRET_KEY + valueFrom: + secretKeyRef: + name: acb-r2-credentials + key: secret-key + - name: ACB_B2_ENDPOINT + value: "http://armor:9000" + - name: ACB_B2_BUCKET + valueFrom: + secretKeyRef: + name: acb-armor-credentials + key: bucket + - name: ACB_B2_ACCESS_KEY + valueFrom: + secretKeyRef: + name: acb-armor-credentials + key: auth-access-key + - name: ACB_B2_SECRET_KEY + valueFrom: + secretKeyRef: + name: acb-armor-credentials + key: auth-secret-key + resources: + requests: + cpu: "50m" + memory: "192Mi" + limits: + memory: "512Mi" + imagePullSecrets: + - name: docker-hub-registry diff --git a/manifests/acb-matchmaker-deployment.yml b/manifests/acb-matchmaker-deployment.yml new file mode 100644 index 0000000..f3fd854 --- /dev/null +++ b/manifests/acb-matchmaker-deployment.yml @@ -0,0 +1,93 @@ +# acb-matchmaker: Internal matchmaking scheduler for AI Code Battle +# Computes pairings, enqueues job IDs into Valkey, health-checks bots, +# and reaps stale jobs. No external exposure. +# +# Staging file — sync to declarative-config/k8s/iad-acb/ai-code-battle/ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: acb-matchmaker + namespace: ai-code-battle + labels: + app.kubernetes.io/component: matchmaker + app.kubernetes.io/name: acb-matchmaker + app.kubernetes.io/part-of: ai-code-battle + annotations: + argocd-image-updater.argoproj.io/image-list: app=ronaldraygun/acb-matchmaker + argocd-image-updater.argoproj.io/app.update-strategy: name + argocd-image-updater.argoproj.io/app.allow-tags: 'regexp:^sha-[0-9a-f]+$' + argocd-image-updater.argoproj.io/write-back-method: argocd + reloader.stakater.com/auto: "true" +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: acb-matchmaker + template: + metadata: + labels: + app.kubernetes.io/component: matchmaker + app.kubernetes.io/name: acb-matchmaker + app.kubernetes.io/part-of: ai-code-battle + annotations: + reloader.stakater.com/auto: "true" + spec: + restartPolicy: Always + containers: + - name: matchmaker + image: ronaldraygun/acb-matchmaker@sha256:1a322b94e32e6cd843abe3c2beb1478f2c4893ce5d963a8d2eeff92cfe7c0e06 + imagePullPolicy: Always + env: + - name: ACB_POSTGRES_USER + valueFrom: + secretKeyRef: + name: acb-postgres-credentials + key: username + - name: ACB_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: acb-postgres-credentials + key: password + - name: ACB_DATABASE_URL + value: "postgresql://$(ACB_POSTGRES_USER):$(ACB_POSTGRES_PASSWORD)@acb-postgres:5432/ai_code_battle?sslmode=disable" + - name: ACB_VALKEY_ADDR + value: "valkey:6379" + - name: ACB_ENCRYPTION_KEY + valueFrom: + secretKeyRef: + name: acb-matchmaker-secrets + key: encryption-key + optional: true + - name: ACB_DISCORD_WEBHOOK + valueFrom: + secretKeyRef: + name: acb-alert-webhooks + key: discord + optional: true + - name: ACB_SLACK_WEBHOOK + valueFrom: + secretKeyRef: + name: acb-alert-webhooks + key: slack + optional: true + - name: ACB_MATCHMAKER_INTERVAL + value: "60" + - name: ACB_HEALTHCHECK_INTERVAL + value: "900" + - name: ACB_REAPER_INTERVAL + value: "300" + - name: ACB_BOT_TIMEOUT + value: "5" + - name: ACB_STALE_JOB_MINUTES + value: "15" + - name: ACB_MAX_CONSEC_FAILS + value: "3" + resources: + requests: + cpu: "50m" + memory: "128Mi" + limits: + memory: "256Mi" + imagePullSecrets: + - name: docker-hub-registry diff --git a/manifests/acb-worker-deployment.yml b/manifests/acb-worker-deployment.yml new file mode 100644 index 0000000..7e66aaa --- /dev/null +++ b/manifests/acb-worker-deployment.yml @@ -0,0 +1,102 @@ +# acb-worker: Match execution worker for AI Code Battle +# BRPOPs jobs from Valkey, runs matches, uploads replays to B2 (armor), +# writes results and Glicko-2 ratings to PostgreSQL. +# +# Staging file — sync to declarative-config/k8s/iad-acb/ai-code-battle/ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: acb-worker + namespace: ai-code-battle + labels: + app.kubernetes.io/component: worker + app.kubernetes.io/name: acb-worker + app.kubernetes.io/part-of: ai-code-battle + annotations: + argocd-image-updater.argoproj.io/image-list: app=ronaldraygun/acb-worker + argocd-image-updater.argoproj.io/app.update-strategy: name + argocd-image-updater.argoproj.io/app.allow-tags: 'regexp:^sha-[0-9a-f]+$' + argocd-image-updater.argoproj.io/write-back-method: argocd + reloader.stakater.com/auto: "true" +spec: + replicas: 2 + selector: + matchLabels: + app.kubernetes.io/name: acb-worker + template: + metadata: + labels: + app.kubernetes.io/component: worker + app.kubernetes.io/name: acb-worker + app.kubernetes.io/part-of: ai-code-battle + annotations: + reloader.stakater.com/auto: "true" + spec: + restartPolicy: Always + containers: + - name: worker + image: ronaldraygun/acb-worker@sha256:edd9616aaefb684a59779ea4b46b2bfe72679eecf6867e1be658273648e86bbe + imagePullPolicy: Always + args: + - "-poll=5s" + - "-heartbeat=30s" + - "-timeout=3s" + ports: + - containerPort: 9090 + name: metrics + protocol: TCP + env: + - name: ACB_POSTGRES_USER + valueFrom: + secretKeyRef: + name: acb-postgres-credentials + key: username + - name: ACB_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: acb-postgres-credentials + key: password + - name: ACB_DATABASE_URL + value: "postgresql://$(ACB_POSTGRES_USER):$(ACB_POSTGRES_PASSWORD)@acb-postgres:5432/ai_code_battle?sslmode=disable" + - name: ACB_B2_ENDPOINT + value: "http://armor:9000" + - name: ACB_B2_BUCKET + valueFrom: + secretKeyRef: + name: acb-armor-credentials + key: bucket + - name: ACB_B2_ACCESS_KEY + valueFrom: + secretKeyRef: + name: acb-armor-credentials + key: auth-access-key + - name: ACB_B2_SECRET_KEY + valueFrom: + secretKeyRef: + name: acb-armor-credentials + key: auth-secret-key + - name: ACB_B2_REGION + value: "us-east-1" + - name: ACB_METRICS_ADDR + value: ":9090" + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + memory: "512Mi" + livenessProbe: + httpGet: + path: /health + port: metrics + initialDelaySeconds: 5 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /ready + port: metrics + initialDelaySeconds: 5 + periodSeconds: 10 + imagePullSecrets: + - name: docker-hub-registry