infra: deterministic deploys — pin images to semver, Renovate + dispatch

- All images pinned to semver tags (no :latest/:main anywhere)
- Renovate scans manifests/*.yml + k8s/*.yaml for docker version bumps
- Auto-merge minor+patch for zooai/*, patch-only for hanzoai/*
- Pin digests enabled for reproducible deploys
- update-image.yml: repository_dispatch callback creates PRs on new tags
- Renovate packagePatterns updated: zooai (not zoo-labs)
This commit is contained in:
Hanzo AI
2026-04-09 22:26:42 -07:00
parent 2845aa4718
commit 7cb3092c1e
12 changed files with 145 additions and 56 deletions
+73
View File
@@ -0,0 +1,73 @@
name: Update service image
on:
repository_dispatch:
types: [image-published]
permissions:
contents: write
pull-requests: write
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Update manifest
env:
SERVICE: ${{ github.event.client_payload.service }}
IMAGE: ${{ github.event.client_payload.image }}
TAG: ${{ github.event.client_payload.tag }}
SHA: ${{ github.event.client_payload.sha }}
run: |
echo "Updating $SERVICE to $IMAGE:$TAG (sha: $SHA)"
# Update all manifest files
for f in manifests/*.yml; do
# Update image tag
sed -i "s|image: ${IMAGE}:[^ ]*|image: ${IMAGE}:${TAG}|g" "$f"
# Update sha field for the service
# Uses yq-style sed: find service block, update sha
if [ -n "$SHA" ]; then
python3 -c "
import re, sys
text = open('$f').read()
# Match the service block and update sha
pattern = r'(image: ${IMAGE}:${TAG}\n\s+sha: )\"\"|(\s+sha: )\"\"'
text = re.sub(r'(image: \Q${IMAGE}\E:[^\n]*\n\s+sha: )\"\"', r'\g<1>\"${SHA}\"', text)
open('$f', 'w').write(text)
" 2>/dev/null || true
fi
done
# Update k8s manifests
find k8s/ -name '*.yaml' -exec \
sed -i "s|${IMAGE}:[^ ]*|${IMAGE}:${TAG}|g" {} +
- name: Create PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
SERVICE="${{ github.event.client_payload.service }}"
TAG="${{ github.event.client_payload.tag }}"
BRANCH="update/${SERVICE}-${TAG}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b "$BRANCH"
git add -A
if git diff --cached --quiet; then
echo "No changes"
exit 0
fi
git commit -m "chore(deps): update ${SERVICE} to ${TAG}"
git push origin "$BRANCH"
gh pr create \
--title "chore(deps): update ${SERVICE} to ${TAG}" \
--body "Automated image update from CI build." \
--label "renovate,dependencies" \
--base main
+4 -4
View File
@@ -12,7 +12,7 @@
services:
# Auth Gateway — web2 → on-chain translation layer
auth-gateway:
image: ghcr.io/zooai/auth-gateway:latest
image: ghcr.io/zooai/auth-gateway:0.1.0
ports:
- "8080:8080"
environment:
@@ -32,7 +32,7 @@ services:
# Validator Node 1 (bootstrap)
node-1:
image: ghcr.io/luxfi/node:latest
image: ghcr.io/luxfi/node:1.24.11
environment:
LUX_NETWORK_ID: "200200"
LUX_HTTP_PORT: "9650"
@@ -54,7 +54,7 @@ services:
# Validator Node 2
node-2:
image: ghcr.io/luxfi/node:latest
image: ghcr.io/luxfi/node:1.24.11
environment:
LUX_NETWORK_ID: "200200"
LUX_BOOTSTRAP_IPS: "node-1:9651"
@@ -70,7 +70,7 @@ services:
# Validator Node 3
node-3:
image: ghcr.io/luxfi/node:latest
image: ghcr.io/luxfi/node:1.24.11
environment:
LUX_NETWORK_ID: "200200"
LUX_BOOTSTRAP_IPS: "node-1:9651"
+1 -1
View File
@@ -23,7 +23,7 @@ spec:
- name: hanzo
containers:
- name: bridge
image: ghcr.io/zooai/bridge:latest
image: ghcr.io/zooai/bridge:0.1.0
imagePullPolicy: Always
ports:
- containerPort: 3000
+1 -1
View File
@@ -23,7 +23,7 @@ spec:
- name: hanzo
containers:
- name: operator
image: ghcr.io/zooai/operator:latest
image: ghcr.io/zooai/operator:0.1.0
imagePullPolicy: Always
args: ["--namespace", ""]
ports:
+2 -2
View File
@@ -36,7 +36,7 @@ spec:
spec:
initContainers:
- name: replicate-restore
image: ghcr.io/hanzoai/replicate:latest
image: ghcr.io/hanzoai/replicate:0.6.0
args: ["restore", "-if-db-not-exists", "-if-replica-exists", "/app/data/data.db"]
volumeMounts:
- name: data
@@ -65,7 +65,7 @@ spec:
- name: data
mountPath: /app/data
- name: replicate
image: ghcr.io/hanzoai/replicate:latest
image: ghcr.io/hanzoai/replicate:0.6.0
args: ["replicate"]
volumeMounts:
- name: data
+1 -1
View File
@@ -45,7 +45,7 @@ spec:
- name: hanzo
containers:
- name: s3
image: ghcr.io/hanzoai/s3:latest
image: ghcr.io/hanzoai/s3:1.0.0
imagePullPolicy: Always
ports:
- containerPort: 9000
+1 -1
View File
@@ -15,7 +15,7 @@ spec:
spec:
containers:
- name: auth-gateway
image: ghcr.io/zooai/auth-gateway:latest
image: ghcr.io/zooai/auth-gateway:0.1.0
ports:
- containerPort: 8080
name: http
+1 -1
View File
@@ -16,7 +16,7 @@ spec:
spec:
containers:
- name: node
image: ghcr.io/luxfi/node:latest
image: ghcr.io/luxfi/node:1.24.11
ports:
- containerPort: 9650
name: http
+13 -13
View File
@@ -16,7 +16,7 @@ services:
app_type: frontend
app_name: zoo-ngo
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-ngo:dev
image: ghcr.io/zooai/zoo-ngo:0.1.0
sha: ""
updated_at: ""
@@ -25,7 +25,7 @@ services:
app_type: frontend
app_name: zoo-exchange
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-exchange:dev
image: ghcr.io/zooai/zoo-exchange:0.1.0
sha: ""
updated_at: ""
@@ -34,7 +34,7 @@ services:
app_type: frontend
app_name: zoo-vote
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-vote:dev
image: ghcr.io/zooai/zoo-vote:0.1.0
sha: ""
updated_at: ""
@@ -43,7 +43,7 @@ services:
app_type: frontend
app_name: zoo-fund
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-fund:dev
image: ghcr.io/zooai/zoo-fund:0.1.0
sha: ""
updated_at: ""
@@ -52,7 +52,7 @@ services:
app_type: frontend
app_name: zoo-foundation
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-foundation:dev
image: ghcr.io/zooai/zoo-foundation:0.1.0
sha: ""
updated_at: ""
@@ -61,7 +61,7 @@ services:
app_type: frontend
app_name: zoo-lab
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-lab:dev
image: ghcr.io/zooai/zoo-lab:0.1.0
sha: ""
updated_at: ""
@@ -70,7 +70,7 @@ services:
app_type: frontend
app_name: zoo-network
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-network:dev
image: ghcr.io/zooai/zoo-network:0.1.0
sha: ""
updated_at: ""
@@ -79,7 +79,7 @@ services:
app_type: frontend
app_name: zoo-voyage
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-voyage:dev
image: ghcr.io/zooai/zoo-voyage:0.1.0
sha: ""
updated_at: ""
@@ -90,7 +90,7 @@ services:
app_type: backend
app_name: zoo-node
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-node:dev
image: ghcr.io/zooai/zoo-node:0.1.0
sha: ""
updated_at: ""
@@ -99,7 +99,7 @@ services:
app_type: backend
app_name: zoo-bridge
namespace: zoo-devnet
image: ghcr.io/zooai/zoo-bridge:dev
image: ghcr.io/zooai/zoo-bridge:0.1.0
sha: ""
updated_at: ""
@@ -110,7 +110,7 @@ services:
app_type: backend
app_name: iam
namespace: zoo-devnet
image: ghcr.io/hanzoai/iam:latest
image: ghcr.io/hanzoai/iam:1.0.0
sha: ""
updated_at: ""
@@ -119,7 +119,7 @@ services:
app_type: backend
app_name: kms
namespace: zoo-devnet
image: ghcr.io/hanzoai/kms:latest
image: ghcr.io/hanzoai/kms:1.0.0
sha: ""
updated_at: ""
@@ -128,6 +128,6 @@ services:
app_type: backend
app_name: gateway
namespace: zoo-devnet
image: ghcr.io/hanzoai/gateway:latest
image: ghcr.io/hanzoai/gateway:1.0.0
sha: ""
updated_at: ""
+13 -13
View File
@@ -11,7 +11,7 @@ services:
app_type: frontend
app_name: zoo-ngo
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-ngo:main
image: ghcr.io/zooai/zoo-ngo:0.1.0
sha: ""
updated_at: ""
@@ -20,7 +20,7 @@ services:
app_type: frontend
app_name: zoo-exchange
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-exchange:main
image: ghcr.io/zooai/zoo-exchange:0.1.0
sha: ""
updated_at: ""
@@ -29,7 +29,7 @@ services:
app_type: frontend
app_name: zoo-vote
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-vote:main
image: ghcr.io/zooai/zoo-vote:0.1.0
sha: ""
updated_at: ""
@@ -38,7 +38,7 @@ services:
app_type: frontend
app_name: zoo-fund
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-fund:main
image: ghcr.io/zooai/zoo-fund:0.1.0
sha: ""
updated_at: ""
@@ -47,7 +47,7 @@ services:
app_type: frontend
app_name: zoo-foundation
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-foundation:main
image: ghcr.io/zooai/zoo-foundation:0.1.0
sha: ""
updated_at: ""
@@ -56,7 +56,7 @@ services:
app_type: frontend
app_name: zoo-lab
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-lab:main
image: ghcr.io/zooai/zoo-lab:0.1.0
sha: ""
updated_at: ""
@@ -65,7 +65,7 @@ services:
app_type: frontend
app_name: zoo-network
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-network:main
image: ghcr.io/zooai/zoo-network:0.1.0
sha: ""
updated_at: ""
@@ -74,7 +74,7 @@ services:
app_type: frontend
app_name: zoo-voyage
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-voyage:main
image: ghcr.io/zooai/zoo-voyage:0.1.0
sha: ""
updated_at: ""
@@ -85,7 +85,7 @@ services:
app_type: backend
app_name: zoo-node
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-node:main
image: ghcr.io/zooai/zoo-node:0.1.0
sha: ""
updated_at: ""
@@ -94,7 +94,7 @@ services:
app_type: backend
app_name: zoo-bridge
namespace: zoo-mainnet
image: ghcr.io/zooai/zoo-bridge:main
image: ghcr.io/zooai/zoo-bridge:0.1.0
sha: ""
updated_at: ""
@@ -105,7 +105,7 @@ services:
app_type: backend
app_name: iam
namespace: zoo-mainnet
image: ghcr.io/hanzoai/iam:latest
image: ghcr.io/hanzoai/iam:1.0.0
sha: ""
updated_at: ""
@@ -114,7 +114,7 @@ services:
app_type: backend
app_name: kms
namespace: zoo-mainnet
image: ghcr.io/hanzoai/kms:latest
image: ghcr.io/hanzoai/kms:1.0.0
sha: ""
updated_at: ""
@@ -123,6 +123,6 @@ services:
app_type: backend
app_name: gateway
namespace: zoo-mainnet
image: ghcr.io/hanzoai/gateway:latest
image: ghcr.io/hanzoai/gateway:1.0.0
sha: ""
updated_at: ""
+13 -13
View File
@@ -11,7 +11,7 @@ services:
app_type: frontend
app_name: zoo-ngo
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-ngo:test
image: ghcr.io/zooai/zoo-ngo:0.1.0
sha: ""
updated_at: ""
@@ -20,7 +20,7 @@ services:
app_type: frontend
app_name: zoo-exchange
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-exchange:test
image: ghcr.io/zooai/zoo-exchange:0.1.0
sha: ""
updated_at: ""
@@ -29,7 +29,7 @@ services:
app_type: frontend
app_name: zoo-vote
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-vote:test
image: ghcr.io/zooai/zoo-vote:0.1.0
sha: ""
updated_at: ""
@@ -38,7 +38,7 @@ services:
app_type: frontend
app_name: zoo-fund
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-fund:test
image: ghcr.io/zooai/zoo-fund:0.1.0
sha: ""
updated_at: ""
@@ -47,7 +47,7 @@ services:
app_type: frontend
app_name: zoo-foundation
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-foundation:test
image: ghcr.io/zooai/zoo-foundation:0.1.0
sha: ""
updated_at: ""
@@ -56,7 +56,7 @@ services:
app_type: frontend
app_name: zoo-lab
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-lab:test
image: ghcr.io/zooai/zoo-lab:0.1.0
sha: ""
updated_at: ""
@@ -65,7 +65,7 @@ services:
app_type: frontend
app_name: zoo-network
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-network:test
image: ghcr.io/zooai/zoo-network:0.1.0
sha: ""
updated_at: ""
@@ -74,7 +74,7 @@ services:
app_type: frontend
app_name: zoo-voyage
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-voyage:test
image: ghcr.io/zooai/zoo-voyage:0.1.0
sha: ""
updated_at: ""
@@ -85,7 +85,7 @@ services:
app_type: backend
app_name: zoo-node
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-node:test
image: ghcr.io/zooai/zoo-node:0.1.0
sha: ""
updated_at: ""
@@ -94,7 +94,7 @@ services:
app_type: backend
app_name: zoo-bridge
namespace: zoo-testnet
image: ghcr.io/zooai/zoo-bridge:test
image: ghcr.io/zooai/zoo-bridge:0.1.0
sha: ""
updated_at: ""
@@ -105,7 +105,7 @@ services:
app_type: backend
app_name: iam
namespace: zoo-testnet
image: ghcr.io/hanzoai/iam:latest
image: ghcr.io/hanzoai/iam:1.0.0
sha: ""
updated_at: ""
@@ -114,7 +114,7 @@ services:
app_type: backend
app_name: kms
namespace: zoo-testnet
image: ghcr.io/hanzoai/kms:latest
image: ghcr.io/hanzoai/kms:1.0.0
sha: ""
updated_at: ""
@@ -123,6 +123,6 @@ services:
app_type: backend
app_name: gateway
namespace: zoo-testnet
image: ghcr.io/hanzoai/gateway:latest
image: ghcr.io/hanzoai/gateway:1.0.0
sha: ""
updated_at: ""
+22 -6
View File
@@ -1,23 +1,26 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"enabledManagers": ["custom.regex"],
"enabledManagers": ["custom.regex", "kubernetes"],
"kubernetes": {
"fileMatch": ["^k8s/.+\\.yaml$"]
},
"customManagers": [
{
"customType": "regex",
"fileMatch": ["^manifests/.*\\.yml$"],
"matchStrings": [
"image:\\s*(?<depName>[\\w.\\-/]+):v?(?<currentValue>[\\d]+\\.[\\d]+\\.[\\d]+)"
"image:\\s*(?<depName>[\\w.\\-/]+):(?<currentValue>[\\w][\\w.\\-]+)"
],
"datasourceTemplate": "docker",
"versioningTemplate": "semver"
"versioningTemplate": "docker"
}
],
"packageRules": [
{
"description": "Auto-merge minor + patch for all Zoo images",
"description": "Auto-merge minor + patch for Zoo images",
"matchDatasources": ["docker"],
"matchPackagePatterns": ["ghcr.io/zoo-labs/.*"],
"matchPackagePatterns": ["ghcr.io/zooai/.*"],
"automerge": true,
"automergeType": "pr",
"matchUpdateTypes": ["minor", "patch"]
@@ -25,7 +28,15 @@
{
"description": "Auto-merge patch for Hanzo infra images",
"matchDatasources": ["docker"],
"matchPackagePatterns": ["hanzoai/.*", "ghcr.io/hanzoai/.*"],
"matchPackagePatterns": ["ghcr.io/hanzoai/.*"],
"automerge": true,
"automergeType": "pr",
"matchUpdateTypes": ["patch"]
},
{
"description": "Auto-merge patch for Lux images",
"matchDatasources": ["docker"],
"matchPackagePatterns": ["ghcr.io/luxfi/.*"],
"automerge": true,
"automergeType": "pr",
"matchUpdateTypes": ["patch"]
@@ -36,6 +47,11 @@
"matchUpdateTypes": ["major"],
"automerge": false,
"labels": ["major-upgrade"]
},
{
"description": "Pin digests for deterministic deploys",
"matchDatasources": ["docker"],
"pinDigests": true
}
],
"schedule": ["every 15 minutes"],