Syncoor #3416
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: Syncoor | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| el-client: | |
| description: 'Comma-separated list of execution layer clients (geth,besu,nethermind,erigon,reth)' | |
| required: false | |
| default: '"geth","reth","nethermind","besu","erigon"' | |
| type: string | |
| cl-client: | |
| description: 'Comma-separated list of consensus layer clients (lighthouse,teku,prysm,nimbus,lodestar,grandine)' | |
| required: false | |
| default: '"lighthouse","teku","prysm","nimbus","lodestar","grandine"' | |
| type: string | |
| run-timeout-minutes: | |
| description: 'Timeout for the sync test (in minutes)' | |
| required: false | |
| default: '1800' | |
| type: string | |
| image: | |
| description: 'Syncoor Docker image' | |
| required: false | |
| default: 'docker.ethquokkaops.io/dh/ethpandaops/syncoor:master' | |
| type: string | |
| git-ref: | |
| description: 'Git reference (branch, tag, or commit) to checkout' | |
| required: false | |
| default: '' | |
| type: string | |
| config: | |
| description: 'Configuration JSON' | |
| required: false | |
| # network: Network to test (e.g., hoodi, mainnet) | |
| # consensus.syncType: checkpoint or genesis | |
| # consensus.nodeType: fullnode or supernode | |
| # consensus.checkpointSyncURL: Checkpoint sync URL (auto-generated based on network if not provided) | |
| default: >- | |
| { | |
| "network": "hoodi", | |
| "execution": { | |
| "images": { | |
| "besu": "hyperledger/besu:25.9.0", | |
| "geth": "ethereum/client-go:v1.16.4", | |
| "erigon": "erigontech/erigon:v3.2.0-rc1", | |
| "nethermind": "nethermind/nethermind:1.34.0", | |
| "reth": "ghcr.io/paradigmxyz/reth:v1.8.2", | |
| "nimbusel": "ethpandaops/nimbus-eth1:master" | |
| } | |
| }, | |
| "consensus": { | |
| "images": { | |
| "lighthouse": "sigp/lighthouse:v8.0.0-rc.0", | |
| "teku": "consensys/teku:25.9.3", | |
| "prysm": "gcr.io/offchainlabs/prysm/beacon-chain:v6.1.1", | |
| "nimbus": "statusim/nimbus-eth2:multiarch-v25.9.2", | |
| "lodestar": "chainsafe/lodestar:v1.35.0-rc.1", | |
| "grandine": "sifrai/grandine:2.0.0.rc0" | |
| }, | |
| "syncType": "checkpoint", | |
| "nodeType": "fullnode", | |
| "checkpointSyncURL": "" | |
| } | |
| } | |
| type: string | |
| runs-on: | |
| description: 'Runner configuration (JSON). Examples: "ubuntu-latest", {"group": "synctest", "labels": "Disk2TB"}' | |
| required: false | |
| default: '{"group": "synctest", "labels": "Disk2TB"}' | |
| type: string | |
| env: | |
| INSTALL_RCLONE_VERSION: v1.68.2 | |
| S3_BUCKET: ethpandaops-syncoor-data | |
| jobs: | |
| sync: | |
| # Timeouts from h to minutes: | |
| # - 4h -> 240m | |
| # - 6h -> 360m | |
| # - 8h -> 480m | |
| # - 12h -> 720m | |
| # - 24h -> 1440m | |
| # - 48h -> 2880m | |
| # - 72h -> 4320m | |
| timeout-minutes: ${{ fromJSON(inputs.run-timeout-minutes || '1800') }} | |
| runs-on: >- | |
| ${{ fromJSON(inputs.runs-on || '{"group": "synctest", "labels": "Disk2TB"}') }} | |
| concurrency: | |
| group: >- | |
| ${{ github.event_name }}-${{ matrix.network }}-${{ matrix.el-client }}-${{ matrix.cl-client }}-${{ matrix.cl-nodetype }}-${{ matrix.cl-synctype }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| network: >- | |
| ${{ | |
| fromJSON(format('["{0}"]', fromJSON(inputs.config || '{}').network || 'hoodi')) | |
| }} | |
| el-client: >- | |
| ${{ | |
| fromJSON(format('[{0}]', inputs.el-client || ' | |
| "besu", | |
| "erigon", | |
| "geth", | |
| "nethermind", | |
| "reth" | |
| '))}} | |
| cl-client: >- | |
| ${{ | |
| fromJSON(format('[{0}]', inputs.cl-client || ' | |
| "lighthouse", | |
| "teku", | |
| "prysm", | |
| "nimbus", | |
| "lodestar", | |
| "grandine" | |
| '))}} | |
| cl-nodetype: >- | |
| ${{ | |
| fromJSON(format('["{0}"]', fromJSON(inputs.config || '{}').consensus.nodeType || 'fullnode')) | |
| }} | |
| cl-synctype: >- | |
| ${{ | |
| fromJSON(format('["{0}"]', fromJSON(inputs.config || '{}').consensus.syncType || 'checkpoint')) | |
| }} | |
| steps: | |
| - name: Prepare inputs | |
| id: prepare | |
| env: | |
| CONFIG: ${{ inputs.config || '{}' }} | |
| run: | | |
| set -x | |
| # Parse config JSON | |
| if [ "$CONFIG" != '{}' ] && [ -n "$CONFIG" ]; then | |
| # Extract EL images from config | |
| EL_IMAGES=$(echo "$CONFIG" | jq -r '.execution.images // {}') | |
| if [ "$EL_IMAGES" != '{}' ] && [ "$EL_IMAGES" != 'null' ]; then | |
| EL_IMAGE=$(echo "$EL_IMAGES" | jq -r --arg client "${{ matrix.el-client }}" '.[$client] // ""') | |
| echo "el-image=$EL_IMAGE" >> $GITHUB_OUTPUT | |
| else | |
| echo "el-image=" >> $GITHUB_OUTPUT | |
| fi | |
| # Extract CL images from config | |
| CL_IMAGES=$(echo "$CONFIG" | jq -r '.consensus.images // {}') | |
| if [ "$CL_IMAGES" != '{}' ] && [ "$CL_IMAGES" != 'null' ]; then | |
| CL_IMAGE=$(echo "$CL_IMAGES" | jq -r --arg client "${{ matrix.cl-client }}" '.[$client] // ""') | |
| echo "cl-image=$CL_IMAGE" >> $GITHUB_OUTPUT | |
| else | |
| echo "cl-image=" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "el-image=" >> $GITHUB_OUTPUT | |
| echo "cl-image=" >> $GITHUB_OUTPUT | |
| fi | |
| NETWORK="${{ matrix.network }}" | |
| # Generate checkpoint sync URL based on network or use from config | |
| if [ "$CONFIG" != '{}' ] && [ -n "$CONFIG" ]; then | |
| CHECKPOINT_SYNC_URL=$(echo "$CONFIG" | jq -r '.consensus.checkpointSyncURL // ""') | |
| if [ -z "$CHECKPOINT_SYNC_URL" ] || [ "$CHECKPOINT_SYNC_URL" = "null" ]; then | |
| CHECKPOINT_SYNC_URL="https://checkpoint-sync.${NETWORK}.ethpandaops.io" | |
| fi | |
| else | |
| CHECKPOINT_SYNC_URL="https://checkpoint-sync.${NETWORK}.ethpandaops.io" | |
| fi | |
| echo "checkpoint-sync-url=$CHECKPOINT_SYNC_URL" >> $GITHUB_OUTPUT | |
| # Set checkpoint sync enabled based on cl-synctype | |
| if [ "${{ matrix.cl-synctype }}" = "checkpoint" ]; then | |
| CHECKPOINT_SYNC_ENABLED="true" | |
| else | |
| CHECKPOINT_SYNC_ENABLED="false" | |
| fi | |
| echo "checkpoint-sync-enabled=$CHECKPOINT_SYNC_ENABLED" >> $GITHUB_OUTPUT | |
| # Generate syncoor server address based on network | |
| SERVER_URL="https://syncoor-api.${NETWORK}.ethpandaops.io" | |
| echo "syncoor-server-url=$SERVER_URL" >> $GITHUB_OUTPUT | |
| # Generate S3 path based on network, cl-nodetype, and checkpoint sync | |
| S3_PATH="networks/${NETWORK}" | |
| if [ "${{ matrix.cl-nodetype }}" = "supernode" ]; then | |
| S3_PATH="${S3_PATH}-clsupernode" | |
| fi | |
| if [ "$CHECKPOINT_SYNC_ENABLED" = "false" ]; then | |
| S3_PATH="${S3_PATH}-clcheckpointsyncdisabled" | |
| fi | |
| echo "s3-path=$S3_PATH" >> $GITHUB_OUTPUT | |
| # Calculate timeout (subtract 10 minutes) | |
| TIMEOUT=$(( ${{ fromJSON(inputs.run-timeout-minutes || '1800') }} - 10 )) | |
| echo "run-timeout-minutes=$TIMEOUT" >> $GITHUB_OUTPUT | |
| - name: Run Syncoor Test | |
| uses: ethpandaops/syncoor@master | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| server: ${{ steps.prepare.outputs.syncoor-server-url }} | |
| server-auth: ${{ secrets.SYNCOOR_SERVER_AUTH }} | |
| log-force-colors: true | |
| client-logs: true | |
| public: true | |
| network: ${{ matrix.network }} | |
| el-client: ${{ matrix.el-client }} | |
| cl-client: ${{ matrix.cl-client }} | |
| el-image: ${{ steps.prepare.outputs.el-image }} | |
| cl-image: ${{ steps.prepare.outputs.cl-image }} | |
| el-extra-args: >- | |
| ${{ | |
| (matrix.el-client == 'reth') && '["--full"]' || | |
| (matrix.el-client == 'erigon') && '["--prune.mode=full"]' || | |
| '[]' | |
| }} | |
| check-interval: 30s | |
| run-timeout: ${{ steps.prepare.outputs.run-timeout-minutes }}m | |
| log-level: info | |
| s3-upload: true | |
| s3-bucket: ${{ env.S3_BUCKET }} | |
| s3-path: ${{ steps.prepare.outputs.s3-path }} | |
| rclone-config: ${{ secrets.SYNCOOR_RCLONE_CONFIG }} | |
| rclone-version: ${{ env.INSTALL_RCLONE_VERSION }} | |
| checkpoint-sync-enabled: ${{ steps.prepare.outputs.checkpoint-sync-enabled }} | |
| checkpoint-sync-url: ${{ steps.prepare.outputs.checkpoint-sync-url }} | |
| supernode: ${{ matrix.cl-nodetype == 'supernode' }} | |
| image: ${{ inputs.image || 'docker.ethquokkaops.io/dh/ethpandaops/syncoor:master' }} | |
| git-ref: ${{ inputs.git-ref }} | |
| - name: Update test results index | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| await github.rest.actions.createWorkflowDispatch({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| workflow_id: 'syncoor-generate-index.yaml', | |
| ref: context.ref, | |
| inputs: { | |
| 's3-path': '${{ steps.prepare.outputs.s3-path }}' | |
| } | |
| }); |