From a41c2169742f92c316cf36f657eec3a95452bd65 Mon Sep 17 00:00:00 2001 From: joshieDo <93316087+joshieDo@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:43:46 +0200 Subject: [PATCH] chore(ci): improve `hive` workflow (#9320) --- .github/assets/hive/build_simulators.sh | 38 +++++++++++ .github/assets/hive/expected_failures.yaml | 8 --- .github/assets/hive/load_images.sh | 25 +++++++ .github/assets/hive/no_sim_build.diff | 53 +++++++++++++++ .github/assets/hive/run_simulator.sh | 38 +++++++++++ .github/workflows/hive.yml | 78 ++++++++++------------ 6 files changed, 188 insertions(+), 52 deletions(-) create mode 100755 .github/assets/hive/build_simulators.sh create mode 100755 .github/assets/hive/load_images.sh create mode 100644 .github/assets/hive/no_sim_build.diff create mode 100755 .github/assets/hive/run_simulator.sh diff --git a/.github/assets/hive/build_simulators.sh b/.github/assets/hive/build_simulators.sh new file mode 100755 index 000000000..45583d549 --- /dev/null +++ b/.github/assets/hive/build_simulators.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -eo pipefail + +# Create the hive_assets directory +mkdir hive_assets/ + +cd hivetests +go build . + +./hive -client reth # first builds and caches the client + +# Run each hive command in the background for each simulator and wait +echo "Building images" +./hive -client reth --sim "pyspec" -sim.timelimit 1s || true & +./hive -client reth --sim "ethereum/engine" -sim.timelimit 1s || true & +./hive -client reth --sim "devp2p" -sim.timelimit 1s || true & +./hive -client reth --sim "ethereum/rpc-compat" -sim.timelimit 1s || true & +./hive -client reth --sim "smoke/genesis" -sim.timelimit 1s || true & +./hive -client reth --sim "smoke/network" -sim.timelimit 1s || true & +./hive -client reth --sim "ethereum/sync" -sim.timelimit 1s || true & +wait + +# Run docker save in parallel and wait +echo "Saving images" +docker save hive/hiveproxy:latest -o ../hive_assets/hiveproxy.tar & +docker save hive/simulators/devp2p:latest -o ../hive_assets/devp2p.tar & +docker save hive/simulators/ethereum/engine:latest -o ../hive_assets/engine.tar & +docker save hive/simulators/ethereum/rpc-compat:latest -o ../hive_assets/rpc_compat.tar & +docker save hive/simulators/ethereum/pyspec:latest -o ../hive_assets/pyspec.tar & +docker save hive/simulators/smoke/genesis:latest -o ../hive_assets/smoke_genesis.tar & +docker save hive/simulators/smoke/network:latest -o ../hive_assets/smoke_network.tar & +docker save hive/simulators/ethereum/sync:latest -o ../hive_assets/ethereum_sync.tar & +wait + +# Make sure we don't rebuild images on the CI jobs +git apply ../.github/assets/hive/no_sim_build.diff +go build . +mv ./hive ../hive_assets/ \ No newline at end of file diff --git a/.github/assets/hive/expected_failures.yaml b/.github/assets/hive/expected_failures.yaml index 831cb966f..ba29ca5e7 100644 --- a/.github/assets/hive/expected_failures.yaml +++ b/.github/assets/hive/expected_failures.yaml @@ -36,14 +36,6 @@ engine-withdrawals: - Withdrawals Fork on Canonical Block 8 / Side Block 7 - 10 Block Re-Org Sync (Paris) (reth) - Withdrawals Fork on Canonical Block 8 / Side Block 9 - 10 Block Re-Org (Paris) (reth) - Withdrawals Fork on Canonical Block 8 / Side Block 9 - 10 Block Re-Org Sync (Paris) (reth) - - # https://github.com/paradigmxyz/reth/issues/8304#issuecomment-2208515839 - - Sync after 2 blocks - Withdrawals on Block 1 - Single Withdrawal Account - No Transactions (Paris) (reth) - - Sync after 2 blocks - Withdrawals on Block 1 - Single Withdrawal Account (Paris) (reth) - - Sync after 2 blocks - Withdrawals on Genesis - Single Withdrawal Account (Paris) (reth) - - Sync after 2 blocks - Withdrawals on Block 2 - Multiple Withdrawal Accounts - No Transactions (Paris) (reth) - - Sync after 2 blocks - Withdrawals on Block 2 - Multiple Withdrawal Accounts (Paris) (reth) - - Sync after 128 blocks - Withdrawals on Block 2 - Multiple Withdrawal Accounts (Paris) (reth) # https://github.com/paradigmxyz/reth/issues/8305 # https://github.com/paradigmxyz/reth/issues/6217 diff --git a/.github/assets/hive/load_images.sh b/.github/assets/hive/load_images.sh new file mode 100755 index 000000000..05e1cb990 --- /dev/null +++ b/.github/assets/hive/load_images.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -eo pipefail + +# List of tar files to load +IMAGES=( + "/tmp/hiveproxy.tar" + "/tmp/devp2p.tar" + "/tmp/engine.tar" + "/tmp/rpc_compat.tar" + "/tmp/pyspec.tar" + "/tmp/smoke_genesis.tar" + "/tmp/smoke_network.tar" + "/tmp/ethereum_sync.tar" + "/tmp/reth_image.tar" +) + +# Loop through the images and load them +for IMAGE_TAR in "${IMAGES[@]}"; do + echo "Loading image $IMAGE_TAR..." + docker load -i "$IMAGE_TAR" & +done + +wait + +docker image ls -a \ No newline at end of file diff --git a/.github/assets/hive/no_sim_build.diff b/.github/assets/hive/no_sim_build.diff new file mode 100644 index 000000000..0b109efe7 --- /dev/null +++ b/.github/assets/hive/no_sim_build.diff @@ -0,0 +1,53 @@ +diff --git a/internal/libdocker/builder.go b/internal/libdocker/builder.go +index 4731c9d..d717f52 100644 +--- a/internal/libdocker/builder.go ++++ b/internal/libdocker/builder.go +@@ -7,9 +7,7 @@ import ( + "fmt" + "io" + "io/fs" +- "os" + "path/filepath" +- "strings" + + "github.com/ethereum/hive/internal/libhive" + docker "github.com/fsouza/go-dockerclient" +@@ -53,24 +51,8 @@ func (b *Builder) BuildClientImage(ctx context.Context, client libhive.ClientDes + + // BuildSimulatorImage builds a docker image of a simulator. + func (b *Builder) BuildSimulatorImage(ctx context.Context, name string) (string, error) { +- dir := b.config.Inventory.SimulatorDirectory(name) +- buildContextPath := dir +- buildDockerfile := "Dockerfile" +- // build context dir of simulator can be overridden with "hive_context.txt" file containing the desired build path +- if contextPathBytes, err := os.ReadFile(filepath.Join(filepath.FromSlash(dir), "hive_context.txt")); err == nil { +- buildContextPath = filepath.Join(dir, strings.TrimSpace(string(contextPathBytes))) +- if strings.HasPrefix(buildContextPath, "../") { +- return "", fmt.Errorf("cannot access build directory outside of Hive root: %q", buildContextPath) +- } +- if p, err := filepath.Rel(buildContextPath, filepath.Join(filepath.FromSlash(dir), "Dockerfile")); err != nil { +- return "", fmt.Errorf("failed to derive relative simulator Dockerfile path: %v", err) +- } else { +- buildDockerfile = p +- } +- } + tag := fmt.Sprintf("hive/simulators/%s:latest", name) +- err := b.buildImage(ctx, buildContextPath, buildDockerfile, tag, nil) +- return tag, err ++ return tag, nil + } + + // BuildImage creates a container by archiving the given file system, +diff --git a/internal/libdocker/proxy.go b/internal/libdocker/proxy.go +index a53e5af..0bb2ea9 100644 +--- a/internal/libdocker/proxy.go ++++ b/internal/libdocker/proxy.go +@@ -16,7 +16,7 @@ const hiveproxyTag = "hive/hiveproxy" + + // Build builds the hiveproxy image. + func (cb *ContainerBackend) Build(ctx context.Context, b libhive.Builder) error { +- return b.BuildImage(ctx, hiveproxyTag, hiveproxy.Source) ++ return nil + } + + // ServeAPI starts the API server. diff --git a/.github/assets/hive/run_simulator.sh b/.github/assets/hive/run_simulator.sh new file mode 100755 index 000000000..018077bdc --- /dev/null +++ b/.github/assets/hive/run_simulator.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# set -x + +cd hivetests/ + +sim="${1}" +limit="${2}" + +run_hive() { + hive --sim "${sim}" --sim.limit "${limit}" --sim.parallelism 4 --client reth 2>&1 | tee /tmp/log || true +} + +check_log() { + tail -n 1 /tmp/log | sed -r 's/\x1B\[[0-9;]*[mK]//g' +} + +attempt=0 +max_attempts=5 + +while [ $attempt -lt $max_attempts ]; do + run_hive + + # Check if no tests were run. sed removes ansi colors + if check_log | grep -q "suites=0"; then + echo "no tests were run, retrying in 5 seconds" + sleep 5 + attempt=$((attempt + 1)) + continue + fi + + # Check the last line of the log for "finished", "tests failed", or "test failed" + if check_log | grep -Eq "(finished|tests? failed)"; then + exit 0 + else + exit 1 + fi +done +exit 1 \ No newline at end of file diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index d18ffd65f..65063dd01 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -16,7 +16,7 @@ concurrency: cancel-in-progress: true jobs: - prepare: + prepare-reth: if: github.repository == 'paradigmxyz/reth' timeout-minutes: 45 runs-on: @@ -44,6 +44,19 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Upload reth image + uses: actions/upload-artifact@v4 + with: + name: artifacts + path: ./artifacts + + prepare-hive: + if: github.repository == 'paradigmxyz/reth' + timeout-minutes: 45 + runs-on: + group: Reth + steps: + - uses: actions/checkout@v4 - name: Checkout hive tests uses: actions/checkout@v4 with: @@ -55,18 +68,15 @@ jobs: with: go-version: "^1.13.1" - run: go version - - name: Build hive tool - run: | - cd hivetests - go build . - mv ./hive ../artifacts/ - - name: Upload artifacts + - name: Build hive assets + run: .github/assets/hive/build_simulators.sh + + - name: Upload hive assets uses: actions/upload-artifact@v4 with: - name: artifacts - path: ./artifacts - + name: hive_assets + path: ./hive_assets test: timeout-minutes: 60 strategy: @@ -105,8 +115,6 @@ jobs: limit: engine-withdrawals - sim: ethereum/engine limit: engine-auth - - sim: ethereum/engine - limit: engine-transition - sim: ethereum/engine limit: engine-api - sim: ethereum/engine @@ -167,7 +175,9 @@ jobs: include: [homestead/] - sim: pyspec include: [frontier/] - needs: prepare + needs: + - prepare-reth + - prepare-hive name: run runs-on: group: Reth @@ -178,16 +188,21 @@ jobs: with: fetch-depth: 0 - - name: Download artifacts + - name: Download hive assets + uses: actions/download-artifact@v4 + with: + name: hive_assets + path: /tmp + + - name: Download reth image uses: actions/download-artifact@v4 with: name: artifacts path: /tmp - - name: Load Docker image - run: | - docker load --input /tmp/reth_image.tar - docker image ls -a + - name: Load Docker images + run: .github/assets/hive/load_images.sh + - name: Move hive binary run: | mv /tmp/hive /usr/local/bin @@ -201,37 +216,12 @@ jobs: path: hivetests - name: Run ${{ matrix.sim }} simulator - run: | - cd hivetests - hive --sim "${{ matrix.sim }}$" --sim.limit "${{matrix.limit}}/${{join(matrix.include, '|')}}" --sim.parallelism 2 --client reth || true + run: .github/assets/hive/run_simulator.sh "${{ matrix.sim }}$" "${{matrix.limit}}/${{join(matrix.include, '|')}}" - name: Parse hive output run: | find hivetests/workspace/logs -type f -name "*.json" ! -name "hive.json" | xargs -I {} python .github/assets/hive/parse.py {} --exclusion .github/assets/hive/expected_failures.yaml - - name: Create github issue if sim failed - env: - GH_TOKEN: ${{ github.token }} - if: ${{ failure() }} - run: | - echo "Simulator failed, creating issue" - # Check if issue already exists - # get all issues with the label C-hivetest, loop over each page and check if the issue already exists - - existing_issues=$(gh api /repos/paradigmxyz/reth/issues -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" -F "labels=C-hivetest" --method GET | jq '.[].title') - if [[ $existing_issues == *"Hive Test Failure: ${{ matrix.sim }}"* ]]; then - echo "Issue already exists" - exit 0 - fi - gh api \ - --method POST \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - /repos/${{ github.repository }}/issues \ - -f title='Hive Test Failure: ${{ matrix.sim }}' \ - -f body="!!!!!!! This is an automated issue created by the hive test failure !!!!!!!

The hive test for ${{ matrix.sim }} failed. Please investigate and fix the issue.

[Link to the failed run](https://github.com/paradigmxyz/reth/actions/runs/${{ github.run_id }})" \ - -f "labels[]=C-hivetest" - - name: Print simulator output if: ${{ failure() }} run: |