-
Notifications
You must be signed in to change notification settings - Fork 0
217 lines (199 loc) · 8.3 KB
/
Copy pathrelease-testnode-image.yml
File metadata and controls
217 lines (199 loc) · 8.3 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
name: Publish Testnode
# On a version tag (or manual dispatch), publish a testnode image for every
# variant x nitro-contracts-version we support. Each image's chain state is
# GENERATED inline in CI by running `init` (no pre-built snapshot release
# bundles, nothing to publish out of band). The intended (variant x version)
# matrix and the init flags per combo come from runtime.mjs resolvePublishMatrix.
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: "Image version tag (default: tag on push, else apps/cli package version)"
required: false
default: ""
type: string
variant:
description: "Variant to publish (or all)"
required: true
default: "all"
type: choice
options:
- all
- l2
- l2-timeboost
- l3-eth
- l3-custom-6
- l3-custom-16
- l3-custom-18
- l3-custom-20
nitro-contracts-version:
description: "Nitro contracts version (or all)"
required: true
default: "all"
type: choice
options:
- all
- v2.1
- v3.2
jobs:
resolve-publish-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
version: ${{ steps.ver.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Resolve image version
id: ver
run: |
set -euo pipefail
if [ "${{ github.ref_type }}" = "tag" ]; then
V="${{ github.ref_name }}"
elif [ -n "${{ inputs.version }}" ]; then
V="${{ inputs.version }}"
else
V="v$(node -p "require('./apps/cli/package.json').version")"
fi
echo "version=$V" >> "$GITHUB_OUTPUT"
echo "resolved image version: $V"
- name: Build publish matrix
id: matrix
env:
# On tag push: every variant x every supported version. On dispatch:
# the chosen filters. resolvePublishMatrix only emits supported combos
# (e.g. no v2.1 for L2-only variants).
VARIANT_FILTER: ${{ github.ref_type == 'tag' && 'all' || (github.event_name == 'workflow_dispatch' && inputs.variant || 'all') }}
VERSION_FILTER: ${{ github.ref_type == 'tag' && 'all' || (github.event_name == 'workflow_dispatch' && inputs.nitro-contracts-version || 'all') }}
run: >-
node --input-type=module -e
"import { resolvePublishMatrix } from './packages/testnode/src/runtime.mjs';
const include = resolvePublishMatrix(process.env.VARIANT_FILTER, process.env.VERSION_FILTER);
if (!include.length) throw new Error('empty publish matrix');
console.error('publish matrix:', JSON.stringify(include));
const { appendFileSync } = await import('node:fs');
appendFileSync(process.env.GITHUB_OUTPUT, 'matrix=' + JSON.stringify({ include }) + '\\n');"
publish-testnode-image:
needs: resolve-publish-matrix
runs-on: ubuntu-latest
timeout-minutes: 75
strategy:
fail-fast: false
# Each job runs a full init (4 docker containers + image builds). Cap
# concurrency so a release fan-out stays under runner/concurrency limits
# and avoids resource contention.
max-parallel: 4
matrix: ${{ fromJson(needs.resolve-publish-matrix.outputs.matrix) }}
permissions:
contents: read
packages: write
env:
# init resolves token-bridge-contracts to <repo-parent>/token-bridge-contracts;
# pin the location and the commit the contract-deployer Dockerfiles use.
TOKEN_BRIDGE_LOCAL_DIR: ${{ github.workspace }}/../token-bridge-contracts
TOKEN_BRIDGE_COMMIT: 5975d8f7360816341be7f94fd333ef240f4aec23
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Foundry (forge for token-bridge build)
uses: foundry-rs/foundry-toolchain@v1
- name: Install yarn (classic)
run: npm install -g yarn@1.22.22
- name: Prepare token-bridge-contracts host checkout
run: |
set -euxo pipefail
mkdir -p "$TOKEN_BRIDGE_LOCAL_DIR"
cd "$TOKEN_BRIDGE_LOCAL_DIR"
git init .
git remote add origin https://github.com/OffchainLabs/token-bridge-contracts.git
git fetch --depth 1 origin "$TOKEN_BRIDGE_COMMIT"
git checkout --detach FETCH_HEAD
yarn install --frozen-lockfile
yarn build
test -f node_modules/ts-node/dist/bin.js
test -f scripts/deployment/deployTokenBridgeCreator.ts
# Generate this combo's snapshot inline via init. init is flaky in CI
# (intermittently exits 0 at wait-l1 before capturing, ~50%), so success
# is driven off the manifest existing, with up to 3 attempts and a reset
# between. --skip-post-capture-verify because the in-place verify-restart's
# fixed 120s RPC budget is too tight for a cold runner.
- name: Generate snapshot (init, retry until captured)
env:
SNAPSHOT_ID: ${{ matrix.snapshotId }}
NC_VERSION: ${{ matrix.contractsVersion }}
DECIMALS: ${{ matrix.feeTokenDecimals }}
TIMEBOOST: ${{ matrix.timeboostEnabled }}
run: |
set -uo pipefail
MANIFEST="config/snapshots/$SNAPSHOT_ID/manifest.json"
EXTRA=""
if [ -n "${DECIMALS:-}" ] && [ "${DECIMALS}" != "null" ]; then
EXTRA="$EXTRA --fee-token-decimals $DECIMALS"
fi
if [ "${TIMEBOOST:-}" = "true" ]; then
EXTRA="$EXTRA --timeboost-enabled"
fi
max=3
for attempt in $(seq 1 "$max"); do
echo "::group::init attempt $attempt/$max ($SNAPSHOT_ID)"
# shellcheck disable=SC2086
# Bound each attempt so an unforeseen hang can't consume the whole
# job; 1500s comfortably exceeds a healthy ~10-15min init and keeps
# 3 attempts within timeout-minutes: 75. The retry loop resets with
# `docker compose ... down -v` below so a timed-out attempt recovers.
timeout 1500 pnpm dev init \
--nitro-contracts-version "$NC_VERSION" \
$EXTRA \
--capture-id "$SNAPSHOT_ID" \
--rebuild \
--skip-post-capture-verify || echo "init exited/timed out on attempt $attempt"
echo "::endgroup::"
if [ -f "$MANIFEST" ]; then
echo "snapshot captured on attempt $attempt"
break
fi
echo "attempt $attempt produced no snapshot; resetting and retrying"
docker compose -f docker/docker-compose.yaml -p arbitrum-testnode down -v || true
done
test -f "$MANIFEST"
- name: Dump docker state on failure
if: failure()
run: |
docker ps -a || true
docker compose -f docker/docker-compose.yaml -p arbitrum-testnode logs --tail=100 || true
- name: Prepare testnode context
run: >-
node scripts/ci/prepare-testnode-context.mjs
--variant "${{ matrix.variant }}"
--snapshot-id "${{ matrix.snapshotId }}"
--nitro-contracts-version "${{ matrix.contractsVersion }}"
- name: Lowercase owner
id: lower
run: echo "owner=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
- name: Contracts tag
id: nc
run: echo "tag=nc$(echo '${{ matrix.contractsVersion }}' | sed 's/^v//')" >> "$GITHUB_OUTPUT"
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push testnode image
uses: docker/build-push-action@v6
with:
context: .
file: docker/testnode.Dockerfile
push: true
tags: ghcr.io/${{ steps.lower.outputs.owner }}/arbitrum-testnode-ci:${{ needs.resolve-publish-matrix.outputs.version }}-${{ steps.nc.outputs.tag }}-${{ matrix.variant }}