-
Notifications
You must be signed in to change notification settings - Fork 614
341 lines (309 loc) · 13.6 KB
/
Copy pathdeploy-network.yml
File metadata and controls
341 lines (309 loc) · 13.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# Low-level workflow to deploy a single network
# This is called by other deployment workflows
name: Deploy Network
on:
workflow_call:
inputs:
network:
description: "Network to deploy (e.g., staging, testnet, next-net)"
required: true
type: string
semver:
description: "Semver version (e.g., 2.3.4). Used to construct docker image if aztec_docker_image is not set."
required: false
type: string
aztec_docker_image:
description: "Full Aztec docker image (e.g., aztecprotocol/aztec:2.3.4). If not set, constructed from semver."
required: false
type: string
prover_docker_image:
description: "Full Prover docker image URL. If not set defaults to aztec_docker_image."
required: false
type: string
use_internal_docker_registry:
description: "Construct Aztec docker images from INTERNAL_DOCKER_REGISTRY and semver."
required: false
type: boolean
default: false
ref:
description: "Git ref to checkout"
required: false
type: string
namespace:
description: "Kubernetes namespace override (optional, defaults to env file value)"
required: false
type: string
deploy_contracts:
description: "Whether to deploy contracts fresh (true for first patch, false to read from network config)"
required: false
type: boolean
default: false
ha_docker_image:
description: "Full docker image for HA validator nodes (optional, defaults to aztec docker image)"
required: false
type: string
source_tag:
description: "Source tag that triggered this deploy"
required: false
type: string
skip_notify_on_failure:
description: "Whether this workflow should skip its own failure notification"
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
network:
description: "Network to deploy (e.g., staging, testnet, next-net)"
required: true
type: choice
options:
- next-net
- staging-public
- staging-internal
- testnet
- mainnet
semver:
description: "Semver version (e.g., 2.3.4). Used to construct docker image if aztec_docker_image is not set."
required: false
type: string
aztec_docker_image:
description: "Full Aztec docker image (e.g., aztecprotocol/aztec:2.3.4). If not set, constructed from semver."
required: false
type: string
prover_docker_image:
description: "Full Prover docker image URL. If not set defaults to aztec_docker_image."
required: false
type: string
use_internal_docker_registry:
description: "Construct Aztec docker images from INTERNAL_DOCKER_REGISTRY and semver."
required: false
type: boolean
default: false
namespace:
description: "Kubernetes namespace override (optional, defaults to env file value)"
required: false
type: string
deploy_contracts:
description: "Whether to deploy contracts fresh (true for first patch, false to read from network config)"
required: false
type: boolean
default: false
ha_docker_image:
description: "Full docker image for HA validator nodes (optional, defaults to aztec docker image)"
required: false
type: string
source_tag:
description: "Source tag that triggered this deploy"
required: false
type: string
concurrency:
group: deploy-network-${{ inputs.network }}-${{ inputs.namespace || inputs.network }}-${{ inputs.aztec_docker_image || inputs.semver }}-${{ github.ref || github.ref_name }}
cancel-in-progress: true
jobs:
deploy-network:
runs-on: ubuntu-latest
env:
GOOGLE_APPLICATION_CREDENTIALS: /tmp/gcp-key.json
outputs:
cluster: ${{ steps.deploy-network.outputs.cluster }}
steps:
- name: Determine checkout ref
id: checkout-ref
run: |
# Use inputs.ref if provided (workflow_call), otherwise use github.ref
if [[ -n "${{ inputs.ref }}" ]]; then
echo "ref=${{ inputs.ref }}" >> $GITHUB_OUTPUT
else
echo "ref=${{ github.ref }}" >> $GITHUB_OUTPUT
fi
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
ref: ${{ steps.checkout-ref.outputs.ref }}
# Full history so recursive submodules can checkout pinned commits (not only branch tips).
fetch-depth: 0
lfs: true
persist-credentials: false
submodules: recursive # Initialize git submodules for l1-contracts dependencies
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: 22
- name: Validate inputs
env:
INTERNAL_DOCKER_REGISTRY: ${{ secrets.INTERNAL_DOCKER_REGISTRY }}
run: |
# Validate network
if [[ ! -f "spartan/environments/${{ inputs.network }}.env" ]]; then
echo "Error: Environment file not found for network '${{ inputs.network }}'"
echo "Available networks:"
ls -1 spartan/environments/ | grep -v '\.local\.env$' || echo "No environment files found"
exit 1
fi
# Require at least one of aztec_docker_image or semver
if [[ -z "${{ inputs.aztec_docker_image }}" && -z "${{ inputs.semver }}" ]]; then
echo "Error: Either 'aztec_docker_image' or 'semver' must be provided"
exit 1
fi
# Validate semver format if provided
if [[ -n "${{ inputs.semver }}" ]]; then
if ! echo "${{ inputs.semver }}" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-.*)?$'; then
echo "Error: Invalid semver format '${{ inputs.semver }}'. Expected format: X.Y.Z or X.Y.Z-suffix"
exit 1
fi
fi
if [[ "${{ inputs.use_internal_docker_registry }}" == "true" && -z "${{ inputs.semver }}" ]]; then
echo "Error: semver must be provided when use_internal_docker_registry is true"
exit 1
fi
# Resolve the docker image
AZTEC_DOCKER_IMAGE="${{ inputs.aztec_docker_image }}"
PROVER_AGENT_DOCKER_IMAGE="${{ inputs.prover_docker_image }}"
INTERNAL_REGISTRY_BASE_URL=""
if [[ "${{ inputs.use_internal_docker_registry }}" == "true" ]]; then
INTERNAL_REGISTRY_BASE_URL="${INTERNAL_DOCKER_REGISTRY%/}"
echo "::add-mask::$INTERNAL_REGISTRY_BASE_URL"
fi
if [[ -z "$AZTEC_DOCKER_IMAGE" ]]; then
if [[ -n "$INTERNAL_REGISTRY_BASE_URL" ]]; then
AZTEC_DOCKER_IMAGE="$INTERNAL_REGISTRY_BASE_URL/aztec:${{ inputs.semver }}"
echo "::add-mask::$AZTEC_DOCKER_IMAGE"
else
AZTEC_DOCKER_IMAGE="aztecprotocol/aztec:${{ inputs.semver }}"
fi
fi
if [[ -z "$PROVER_AGENT_DOCKER_IMAGE" ]]; then
if [[ -n "$INTERNAL_REGISTRY_BASE_URL" ]]; then
PROVER_AGENT_DOCKER_IMAGE="$INTERNAL_REGISTRY_BASE_URL/aztec-prover-agent:${{ inputs.semver }}"
echo "::add-mask::$PROVER_AGENT_DOCKER_IMAGE"
elif [[ -z "${{ inputs.aztec_docker_image }}" && -n "${{ inputs.semver }}" ]]; then
PROVER_AGENT_DOCKER_IMAGE="aztecprotocol/aztec-prover-agent:${{ inputs.semver }}"
fi
fi
echo "AZTEC_DOCKER_IMAGE=$AZTEC_DOCKER_IMAGE" >> $GITHUB_ENV
echo "PROVER_AGENT_DOCKER_IMAGE=$PROVER_AGENT_DOCKER_IMAGE" >> $GITHUB_ENV
- name: Store the GCP key in a file
env:
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
run: |
set +x
umask 077
printf '%s' "$GCP_SA_KEY" > "$GOOGLE_APPLICATION_CREDENTIALS"
jq -e . "$GOOGLE_APPLICATION_CREDENTIALS" >/dev/null
- name: Setup GCP authentication
run: |
gcloud auth activate-service-account --key-file="$GOOGLE_APPLICATION_CREDENTIALS"
- name: Setup gcloud and install GKE auth plugin
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db
with:
install_components: "gke-gcloud-auth-plugin"
- name: Setup Terraform
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e
with:
terraform_version: "1.7.5"
terraform_wrapper: false # Disable the wrapper that adds debug output, this messes with reading terraform output
- name: Setup SSH key for CI Redis
env:
BUILD_INSTANCE_SSH_KEY: ${{ secrets.BUILD_INSTANCE_SSH_KEY }}
run: |
if [ -n "${BUILD_INSTANCE_SSH_KEY:-}" ]; then
mkdir -p ~/.ssh
echo "${BUILD_INSTANCE_SSH_KEY}" | base64 --decode > ~/.ssh/build_instance_key
chmod 600 ~/.ssh/build_instance_key
fi
- name: Deploy network
id: deploy-network
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GITHUB_TOKEN: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }}
RUN_ID: ${{ github.run_id }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
GOOGLE_APPLICATION_CREDENTIALS: ${{ env.GOOGLE_APPLICATION_CREDENTIALS }}
REF_NAME: ${{ inputs.semver && format('v{0}', inputs.semver) || '' }}
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
NAMESPACE: ${{ inputs.namespace }}
AZTEC_DOCKER_IMAGE: ${{ env.AZTEC_DOCKER_IMAGE }}
CREATE_ROLLUP_CONTRACTS: ${{ inputs.deploy_contracts == true && 'true' || '' }}
PROVER_AGENT_DOCKER_IMAGE: ${{ env.PROVER_AGENT_DOCKER_IMAGE || env.AZTEC_DOCKER_IMAGE }}
VALIDATOR_HA_DOCKER_IMAGE: ${{ inputs.ha_docker_image || '' }}
run: |
echo "Deploying network: ${{ inputs.network }}"
echo "Using branch/ref: ${{ steps.checkout-ref.outputs.ref }}"
cd spartan
./scripts/install_deps.sh
./scripts/network_deploy.sh "${{ inputs.network }}"
# need to source this for CLUSTER
source "./environments/${{ inputs.network }}.env"
if [ -n "$CLUSTER" ]; then
echo "cluster=$CLUSTER" >> $GITHUB_OUTPUT
else
echo "cluster=" >> $GITHUB_OUTPUT
fi
- name: Step summary
if: always()
run: |
{
echo "## Deploy Network"
echo ""
echo "| Item | Value |"
echo "|------|-------|"
echo "| Network | \`${{ inputs.network }}\` |"
echo "| Ref | \`${{ steps.checkout-ref.outputs.ref }}\` |"
if [[ -n "${{ inputs.source_tag }}" ]]; then
echo "| Source Tag | [\`${{ inputs.source_tag }}\`](https://github.com/${{ github.repository }}/releases/tag/${{ inputs.source_tag }}) |"
fi
} >> "$GITHUB_STEP_SUMMARY"
- name: Notify Slack and dispatch ClaudeBox on failure
if: failure() && !inputs.skip_notify_on_failure
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
GH_TOKEN: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }}
run: |
if [ -z "${SLACK_BOT_TOKEN:-}" ]; then
echo "No SLACK_BOT_TOKEN, skipping notification"
exit 0
fi
CHANNEL="#alerts-${{ inputs.network }}"
# staging-internal deploy failures are routed to the staging-public alerts channel.
if [ "${{ inputs.network }}" = "staging-internal" ]; then
CHANNEL="#alerts-staging-public"
fi
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
TEXT="Deploy Network workflow FAILED for *${{ inputs.network }}*: <${RUN_URL}|View Run> (🤖)"
# Post to Slack and capture timestamp for permalink
RESP=$(curl -sS -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-type: application/json" \
-d "$(jq -n --arg c "$CHANNEL" --arg t "$TEXT" '{channel:$c, text:$t}')")
echo "Slack response: $RESP"
TS=$(echo "$RESP" | jq -r '.ts // empty')
CHANNEL_ID=$(echo "$RESP" | jq -r '.channel // empty')
LINK=""
if [[ -n "$TS" && -n "$CHANNEL_ID" ]]; then
LINK="https://aztecprotocol.slack.com/archives/$CHANNEL_ID/p${TS//./}"
fi
# Dispatch ClaudeBox to investigate the failure
PROMPT="Deployment of ${{ inputs.network }} failed. \
Follow .claude/claudebox/deploy-investigation.md to investigate. \
GitHub Actions run: ${RUN_URL}. \
Network: ${{ inputs.network }}. \
Git ref: ${{ steps.checkout-ref.outputs.ref }}. \
Namespace: ${{ inputs.namespace || inputs.network }}. \
Deploy contracts: ${{ inputs.deploy_contracts }}."
gh workflow run claudebox.yml \
-f prompt="$PROMPT" \
-f link="${LINK:-$RUN_URL}" \
-f target_ref="${{ steps.checkout-ref.outputs.ref }}" \
-f slack_channel="$CHANNEL_ID" \
-f slack_thread_ts="$TS" || true
update-irm:
needs: deploy-network
if: inputs.network == 'testnet' || inputs.network == 'mainnet'
uses: ./.github/workflows/deploy-irm.yml
secrets: inherit
with:
network: ${{ inputs.network }}
l1_network: ${{ inputs.network == 'mainnet' && 'mainnet' || 'sepolia' }}
cluster: ${{ needs.deploy-network.outputs.cluster }}