e2e-nitro-celestia #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: e2e-nitro-celestia | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| runner_label: | |
| description: Self-hosted runner label | |
| required: true | |
| default: gh-solutions | |
| testnode_repo: | |
| description: Repo for OffchainLabs testnode | |
| required: true | |
| default: OffchainLabs/nitro-testnode | |
| testnode_ref: | |
| description: Ref/branch/tag for testnode (release recommended) | |
| required: true | |
| default: release | |
| celestia_network: | |
| description: Celestia p2p network for the light node | |
| required: true | |
| default: mocha-4 | |
| das_image: | |
| description: Celestia DA server image tag | |
| required: true | |
| default: ghcr.io/celestiaorg/nitro-das-celestia:v0.5.3-mocha | |
| enforce_da_roundtrip: | |
| description: Fail if DA store/fetch can't be verified (true/false) | |
| required: true | |
| default: "true" | |
| concurrency: | |
| group: e2e-nitro-celestia-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| e2e: | |
| runs-on: ${{ inputs.runner_label }} | |
| timeout-minutes: 45 | |
| env: | |
| WORKDIR: ${{ github.workspace }}/.e2e | |
| COMPOSE_PROJECT_NAME: ndc-${{ github.run_id }} | |
| TESTNODE_REPO: ${{ inputs.testnode_repo }} | |
| TESTNODE_REF: ${{ inputs.testnode_ref }} | |
| CELESTIA_NET: ${{ inputs.celestia_network }} | |
| DAS_IMAGE: ${{ inputs.das_image }} | |
| ENFORCE_DA_ROUNDTRIP: ${{ inputs.enforce_da_roundtrip }} | |
| steps: | |
| - name: Checkout nitro-das-celestia (this repo) | |
| uses: actions/checkout@v4 | |
| - name: Prep folders | |
| run: | | |
| mkdir -p "$WORKDIR"/{logs,artifacts} | |
| - name: Docker info (pre) | |
| run: | | |
| docker info || true | |
| docker system df || true | |
| # ---------- 1) Bring up Nitro devnet via OffchainLabs testnode ---------- | |
| - name: Start Nitro + Celestia + DA concurrently | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Kick off Nitro testnode (init + start) in background | |
| ( | |
| cd "$WORKDIR/nitro-testnode" | |
| ./test-node.bash --init | |
| ./test-node.bash --start | |
| docker compose ps | |
| ) & | |
| # Start Celestia light node (RPC open, no auth) in background | |
| ( | |
| docker rm -f celestia-light 2>/dev/null || true | |
| docker run -d --name celestia-light --restart unless-stopped \ | |
| -p 26658:26658 \ | |
| ghcr.io/celestiaorg/celestia-node:latest \ | |
| celestia light start --rpc.skip-auth --p2p.network "${CELESTIA_NET}" | |
| ) & | |
| # Start DA server wired to the light node in background | |
| ( | |
| docker rm -f celestia-da 2>/dev/null || true | |
| # Ensure Linux can reach the host as host.docker.internal | |
| HGI=$(docker info --format '{{.HostGateway}}' 2>/dev/null || echo "") | |
| ADD_HOST_ARG="" | |
| if [ -n "$HGI" ]; then | |
| ADD_HOST_ARG="--add-host=host.docker.internal:${HGI}" | |
| fi | |
| docker run -d --name celestia-da --restart unless-stopped \ | |
| -p 9875:9875 \ | |
| $ADD_HOST_ARG \ | |
| "${DAS_IMAGE}" \ | |
| --enable-rpc --rpc-addr 0.0.0.0 --rpc-port 9875 \ | |
| --celestia.rpc http://host.docker.internal:26658 | |
| ) & | |
| # Wait for all background startups before running health checks | |
| wait | |
| # ---------- Health gates ---------- | |
| - name: Wait for Celestia RPC (26658) | |
| run: | | |
| set -e | |
| tries=90 | |
| until curl -sf http://localhost:26658/health >/dev/null 2>&1 || \ | |
| curl -sf http://localhost:26658 | head -c 1 >/dev/null 2>&1; do | |
| ((tries--)) || { echo "Celestia RPC not up"; exit 1; } | |
| sleep 5 | |
| done | |
| - name: Wait for DA server (9875) | |
| run: | | |
| set -e | |
| tries=90 | |
| until curl -sf http://localhost:9875/health >/dev/null 2>&1 || \ | |
| curl -sf http://localhost:9875 | head -c 1 >/dev/null 2>&1; do | |
| ((tries--)) || { echo "DA server not up"; exit 1; } | |
| sleep 5 | |
| done | |
| - name: Wait for L2 RPC (8547) | |
| run: | | |
| set -e | |
| tries=120 | |
| until curl -sf -H 'Content-Type: application/json' \ | |
| --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ | |
| http://localhost:8547 > /dev/null; do | |
| ((tries--)) || { echo "L2 RPC not up"; exit 1; } | |
| sleep 5 | |
| done | |
| - name: Assert L2 progresses | |
| run: | | |
| set -e | |
| getbn() { curl -s -H 'Content-Type: application/json' \ | |
| --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ | |
| http://localhost:8547 | jq -r .result; } | |
| b1=$(getbn); sleep 8; b2=$(getbn) | |
| echo "BlockNumber t0=$b1 t1=$b2" | |
| [ "$b1" != "null" ] && [ "$b2" != "null" ] || { echo "null block number"; exit 1; } | |
| [ $((b2)) -gt $((b1)) ] || { echo "L2 not progressing"; exit 1; } | |
| # ---------- Heavier E2E: DA roundtrip + L2 tx ---------- | |
| - name: DA store & (best effort) fetch | |
| run: | | |
| set -euo pipefail | |
| PAYLOAD=$(printf 'hello-celestia-%s' "${GITHUB_RUN_ID}" | xxd -p -c 256) | |
| OK=0 | |
| # Try known endpoints in order; capture first success | |
| try_store () { | |
| URL="$1"; BODY="$2"; DESC="$3" | |
| echo "Trying store via ${DESC} (${URL})" | |
| set +e | |
| RESP=$(curl -sS -X POST "$URL" -H "Content-Type: application/json" --data "$BODY") | |
| RC=$? | |
| set -e | |
| if [ $RC -eq 0 ] && [ -n "$RESP" ]; then | |
| echo "$RESP" > "$WORKDIR/artifacts/store.json" | |
| CMT=$(jq -r '(.commitment // .data.commitment // .result // empty)' "$WORKDIR/artifacts/store.json") | |
| if [ -n "$CMT" ] && [ "$CMT" != "null" ]; then | |
| echo "Got commitment: $CMT" | |
| echo "$CMT" > "$WORKDIR/artifacts/commitment.txt" | |
| return 0 | |
| fi | |
| fi | |
| return 1 | |
| } | |
| # Candidate API shapes (update to match your server if needed) | |
| try_store "http://localhost:9875/store" \ | |
| "{\"data\":\"0x${PAYLOAD}\"}" \ | |
| "/store (data hex)" | |
| if [ $? -ne 0 ]; then | |
| try_store "http://localhost:9875/v1/store" \ | |
| "{\"data\":\"0x${PAYLOAD}\"}" \ | |
| "/v1/store (data hex)" | |
| fi | |
| if [ -f "$WORKDIR/artifacts/commitment.txt" ]; then | |
| OK=1 | |
| fi | |
| if [ "$OK" -ne 1 ] && [ "${ENFORCE_DA_ROUNDTRIP}" = "true" ]; then | |
| echo "Failed to store payload via DA server with known endpoints." | |
| exit 1 | |
| fi | |
| # Best-effort fetch | |
| if [ -f "$WORKDIR/artifacts/commitment.txt" ]; then | |
| CMT=$(cat "$WORKDIR/artifacts/commitment.txt") | |
| set +e | |
| curl -sS "http://localhost:9875/get?commitment=${CMT}" \ | |
| | tee "$WORKDIR/artifacts/get.json" >/dev/null | |
| curl -sS "http://localhost:9875/v1/get?commitment=${CMT}" \ | |
| | tee -a "$WORKDIR/artifacts/get.json" >/dev/null | |
| set -e | |
| fi | |
| - name: L2 tx smoke (send to self) | |
| working-directory: ${{ env.WORKDIR }} | |
| run: | | |
| set -euo pipefail | |
| cat > send.json <<'EOF' | |
| {"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0xe2148eE53c0755215Df69b2616E552154EdC584f","to":"0xe2148eE53c0755215Df69b2616E552154EdC584f","value":"0x38d7ea4c68000"}],"id":7} | |
| EOF | |
| curl -sS -H 'Content-Type: application/json' --data @send.json http://localhost:8547 | tee artifacts/send-tx.json | |
| sleep 4 | |
| curl -sS -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":9}' http://localhost:8547 | tee artifacts/bn-after.json | |
| # ---------- Logs & cleanup ---------- | |
| - name: Snapshot docker state & logs | |
| if: always() | |
| run: | | |
| set -euo pipefail | |
| # testnode compose context (if present) | |
| (cd "$WORKDIR/nitro-testnode" && docker compose ps | tee "$WORKDIR/logs/compose-ps.txt") || true | |
| for c in $(docker ps -a --format '{{.Names}}'); do | |
| docker logs --tail=2000 "$c" > "$WORKDIR/logs/${c}.log" 2>&1 || true | |
| done | |
| - name: Upload artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-artifacts-${{ github.run_id }} | |
| path: | | |
| ${{ env.WORKDIR }}/logs | |
| ${{ env.WORKDIR }}/artifacts | |
| - name: Stop stacks | |
| if: always() | |
| run: | | |
| set -e | |
| (cd "$WORKDIR/nitro-testnode" && docker compose down -v) || true | |
| docker rm -f celestia-da celestia-light 2>/dev/null || true | |
| - name: Docker prune (post) | |
| if: always() | |
| run: | | |
| docker system prune -af || true | |
| docker volume prune -f || true |