-
Notifications
You must be signed in to change notification settings - Fork 595
272 lines (246 loc) · 10.4 KB
/
deploy-network.yml
File metadata and controls
272 lines (246 loc) · 10.4 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
# 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-public, testnet, next-net)"
required: true
type: string
semver:
description: "Semver version (e.g., 2.3.4)"
required: true
type: string
docker_image_tag:
description: "Full docker image tag (optional, defaults to semver)"
required: false
type: string
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
workflow_dispatch:
inputs:
network:
description: "Network to deploy (e.g., staging-public, staging-ignition, testnet, next-net)"
required: true
type: choice
options:
- next-net
- staging-public
- testnet
- mainnet
semver:
description: "Semver version (e.g., 2.3.4)"
required: true
type: string
docker_image_tag:
description: "Full docker image tag (optional, defaults to semver)"
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
concurrency:
group: deploy-network-${{ inputs.network }}-${{ inputs.namespace || inputs.network }}-${{ 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@11bd71901bbe5b1630ceea73d27597364c9af683
with:
ref: ${{ steps.checkout-ref.outputs.ref }}
fetch-depth: 1
persist-credentials: false
submodules: recursive # Initialize git submodules for l1-contracts dependencies
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
- name: Validate inputs
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
# Validate semver format
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
# Extract major version for v2 check
major_version="${{ inputs.semver }}"
major_version="${major_version%%.*}"
echo "MAJOR_VERSION=$major_version" >> $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@v2
with:
install_components: "gke-gcloud-auth-plugin"
- name: Setup Terraform
uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1
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: "v${{ inputs.semver }}"
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
NAMESPACE: ${{ inputs.namespace }}
AZTEC_DOCKER_IMAGE: "aztecprotocol/aztec:${{ inputs.docker_image_tag || inputs.semver }}"
CREATE_ROLLUP_CONTRACTS: ${{ inputs.deploy_contracts == true && 'true' || '' }}
PROVER_AGENT_DOCKER_IMAGE: "aztecprotocol/aztec-prover-agent:${{ inputs.docker_image_tag || inputs.semver }}"
VALIDATOR_HA_DOCKER_IMAGE: ${{ inputs.ha_docker_image || '' }}
run: |
echo "Deploying network: ${{ inputs.network }}"
echo "Using image: $AZTEC_DOCKER_IMAGE"
echo "Using prover image: $PROVER_AGENT_DOCKER_IMAGE"
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 "| Semver | \`${{ inputs.semver }}\` |"
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()
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 }}"
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
TEXT="Deploy Network workflow FAILED for *${{ inputs.network }}* (version ${{ inputs.semver }}): <${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 }} (version ${{ inputs.semver }}) failed. \
Follow .claude/claudebox/deploy-investigation.md to investigate. \
GitHub Actions run: ${RUN_URL}. \
Network: ${{ inputs.network }}. Version: ${{ inputs.semver }}. \
Docker image: ${{ inputs.docker_image_tag || inputs.semver }}. \
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 }}" || 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 }}