Skip to content
Merged
259 changes: 259 additions & 0 deletions .github/actions/run-e2e-tests/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
name: 'Run E2E Tests'
description: >
Spins up the local docker-compose environment and runs the e2e test suite.
Callers are responsible for checking out the desired commit (and any
submodule) before invoking this action.

inputs:
image_tag:
description: 'The commit tag to use'
required: true
linea_besu_package_tag:
required: false
default: ''
coordinator_tag:
required: false
default: ''
postman_tag:
required: false
default: ''
prover_tag:
required: false
default: ''
tx_exclusion_api_tag:
required: false
default: ''
maru_tag:
required: false
default: ''
linea_coordinator_image_name:
description: 'Coordinator Docker image name (overrides the compose default)'
required: false
default: consensys/linea-coordinator
linea_coordinator_jar:
description: 'Coordinator JAR filename to launch'
required: false
default: coordinator.jar
linea_coordinator_artifact_name:
description: 'Artifact name prefix for the coordinator Docker image'
required: false
default: linea-coordinator
e2e-tests-with-ssh:
description: Run end to end tests with ability to ssh into environment
required: false
default: 'false'
e2e-tests-logs-dump:
description: Dump logs after running end to end tests
required: false
default: 'true'
e2e-tests-containers-list:
description: List containers before starting end to end tests
required: false
default: 'true'
working-directory:
description: 'Directory (relative to github.workspace) containing the checked-out monorepo'
required: false
default: '.'
dockerhub_username:
required: false
default: ''
dockerhub_token:
required: false
default: ''

outputs:
tests_outcome:
description: 'Outcome of the "Run e2e tests" step'
value: ${{ steps.run_e2e_tests.outcome }}

runs:
using: 'composite'
steps:
- name: Setup upterm session
if: ${{ inputs.e2e-tests-with-ssh == 'true' }}
uses: lhotari/action-upterm@b0357f23233f5ea6d58947c0c402e0631bab7334 #v1

- name: Setup nodejs environment
uses: ./.github/actions/setup-nodejs
with:
working-directory: ${{ inputs.working-directory }}
pnpm-install-options: '-F contracts -F "e2e..." --frozen-lockfile --prefer-offline'
commands: |
pnpm run -F "e2e^..." build

- name: Login to Docker Hub
if: ${{ inputs.dockerhub_username != '' && inputs.dockerhub_token != '' }}
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 #v3.7.0
with:
username: ${{ inputs.dockerhub_username }}
password: ${{ inputs.dockerhub_token }}

- name: Create directory for conflated traces
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
mkdir -p tmp/local/traces/v2/conflated
chmod -R a+rw tmp/local/

- name: Pull all external-to-monorepo images with retry
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 #v4.0.0
if: ${{ inputs.linea_besu_package_tag == '' }}
with:
max_attempts: 10
retry_on: error
retry_wait_seconds: 30
timeout_minutes: 10
command: |
cd ${{ inputs.working-directory }} && make docker-pull-images-external-to-monorepo

- name: Download local docker image artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
continue-on-error: true
with:
pattern: linea-*
path: ${{ github.workspace }}/${{ inputs.working-directory }}/tmp/artifacts
merge-multiple: true

- name: Load Docker images from artifacts or pull develop for unchanged services
Comment thread
fluentcrafter marked this conversation as resolved.
Outdated
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
LINEA_COORDINATOR_ARTIFACT_NAME: ${{ inputs.linea_coordinator_artifact_name }}
run: |
set -euo pipefail
for service in coordinator postman transaction-exclusion-api prover maru; do
if [ "$service" = "maru" ]; then
artifact_path="$GITHUB_WORKSPACE/${{ inputs.working-directory }}/tmp/artifacts/linea-maru-docker-image.tar.gz"
elif [ "$service" = "coordinator" ]; then
artifact_path="$GITHUB_WORKSPACE/${{ inputs.working-directory }}/tmp/artifacts/${LINEA_COORDINATOR_ARTIFACT_NAME}-docker-image.tar.gz"
else
artifact_path="$GITHUB_WORKSPACE/${{ inputs.working-directory }}/tmp/artifacts/linea-${service}-docker-image.tar.gz"
fi

if [ -f "$artifact_path" ]; then
echo "Loading ${service} from build artifact ${artifact_path}..."
gunzip -c "$artifact_path" | docker load
else
echo "No artifact found for ${service}, skipping."
fi
done

- name: Set Docker image tags
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
LINEA_COORDINATOR_ARTIFACT_NAME: ${{ inputs.linea_coordinator_artifact_name }}
LINEA_COORDINATOR_IMAGE_NAME: ${{ inputs.linea_coordinator_image_name }}
LINEA_COORDINATOR_JAR: ${{ inputs.linea_coordinator_jar }}
LINEA_COORDINATOR_TAG: ${{ inputs.coordinator_tag }}
LINEA_POSTMAN_TAG: ${{ inputs.postman_tag }}
LINEA_PROVER_TAG: ${{ inputs.prover_tag }}
LINEA_TRANSACTION_EXCLUSION_API_TAG: ${{ inputs.tx_exclusion_api_tag }}
MARU_TAG: ${{ inputs.maru_tag }}
run: |
set -euo pipefail
for service in coordinator postman transaction-exclusion-api prover maru; do
if [ "$service" = "maru" ]; then
artifact_path="$GITHUB_WORKSPACE/${{ inputs.working-directory }}/tmp/artifacts/linea-maru-docker-image.tar.gz"
env_var="MARU_TAG"
elif [ "$service" = "coordinator" ]; then
artifact_path="$GITHUB_WORKSPACE/${{ inputs.working-directory }}/tmp/artifacts/${LINEA_COORDINATOR_ARTIFACT_NAME}-docker-image.tar.gz"
env_var="LINEA_COORDINATOR_TAG"
else
artifact_path="$GITHUB_WORKSPACE/${{ inputs.working-directory }}/tmp/artifacts/linea-${service}-docker-image.tar.gz"
env_var="LINEA_$(echo "${service}" | tr '[:lower:]-' '[:upper:]_')_TAG"
fi

if [ -f "$artifact_path" ]; then
echo "${env_var}=${{ inputs.image_tag }}" >> "$GITHUB_ENV"
elif [ -z "${!env_var:-}" ]; then
# Fall back to "develop" only when the job-level env var is unset or empty.
echo "${env_var}=develop" >> "$GITHUB_ENV"
fi
done
echo "LINEA_COORDINATOR_IMAGE_NAME=${LINEA_COORDINATOR_IMAGE_NAME}" >> "$GITHUB_ENV"
echo "LINEA_COORDINATOR_JAR=${LINEA_COORDINATOR_JAR}" >> "$GITHUB_ENV"

- name: Load linea-besu-package Docker image
if: ${{ inputs.linea_besu_package_tag != '' }}
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
set -euo pipefail
artifact_path="$GITHUB_WORKSPACE/${{ inputs.working-directory }}/tmp/artifacts/linea-besu-package-images.tar.gz"
if [ -f "$artifact_path" ]; then
gunzip -c "$artifact_path" | docker load
else
echo "No artifact at ${artifact_path}; skipping docker load."
fi

- name: Spin up fresh environment with retry
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
set -euo pipefail
Comment thread
fluentcrafter marked this conversation as resolved.
timeout 10m bash -c '
max=10
attempt=0
until make start-env-with-tracing-v2-ci CLEAN_PREVIOUS_ENV=false; do
attempt=$((attempt + 1))
if [ "$attempt" -ge "$max" ]; then
echo "All $max attempts failed"
exit 1
fi
echo "Attempt $attempt failed — cleaning up and retrying in 30 s..."
make clean-environment || true
sleep 30
done
'

- name: List docker containers/images
if: ${{ always() && inputs.e2e-tests-containers-list == 'true' }}
continue-on-error: true
shell: bash
run: |
docker ps -la && docker images
docker container ls -a

- name: Run e2e tests
id: run_e2e_tests
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
timeout 6m pnpm run -F e2e test:local

- name: Show e2e tests result
if: always()
shell: bash
run: |
echo "E2E_TESTS_RESULT: ${{ steps.run_e2e_tests.outcome }}"

- name: Dump logs
if: ${{ failure() && inputs.e2e-tests-logs-dump == 'true' }}
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
mkdir -p docker_logs
find tmp/local/ >> docker_logs/files_in_shared_dir.txt || true
docker ps -a >> docker_logs/docker_ps.txt || true
docker logs coordinator --since 1h &>> docker_logs/coordinator.txt || true
docker logs prover-v3 --since 1h &>> docker_logs/prover-v3.txt || true
docker logs shomei --since 1h &>> docker_logs/shomei.txt || true
docker logs shomei-frontend --since 1h &>> docker_logs/shomei-frontend.txt || true
docker logs postman --since 1h &>> docker_logs/postman.txt || true
docker logs l2-node-besu --since 1h &>> docker_logs/l2-node-besu.txt || true
docker logs transaction-exclusion-api --since 1h &>> docker_logs/transaction-exclusion-api.txt || true
docker logs sequencer --since 1h &>> docker_logs/sequencer.txt || true
docker logs l1-el-node --since 1h &>> docker_logs/l1-el-node.txt || true
docker logs l1-cl-node --since 1h &>> docker_logs/l1-cl-node.txt || true
docker logs maru --since 1h &>> docker_logs/maru.txt || true
docker exec -i -e PGPASSWORD=${POSTGRES_PASSWORD:-postgres} postgres pg_dumpall -U ${POSTGRES_USER:-postgres} > docker_logs/db_dump.sql || true

- name: Archive debug logs
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ failure() && inputs.e2e-tests-logs-dump == 'true' }}
with:
name: end-2-end-debug-logs
if-no-files-found: error
path: |
${{ inputs.working-directory }}/docker_logs/**/*
14 changes: 11 additions & 3 deletions .github/actions/setup-nodejs/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ inputs:
pnpm run build:libs
required: false
default: ''
working-directory:
description: 'Directory (relative to github.workspace) containing package.json/.nvmrc/pnpm-lock.yaml'
required: false
default: '.'

outputs:
node-version:
Expand All @@ -29,13 +33,16 @@ runs:
steps:
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
name: setup-pnpm
with:
package_json_file: ${{ inputs.working-directory }}/package.json

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
name: setup-nodejs
with:
node-version-file: .nvmrc
node-version-file: ${{ inputs.working-directory }}/.nvmrc
cache: 'pnpm'

cache-dependency-path: ${{ inputs.working-directory }}/pnpm-lock.yaml

- id: versions
name: Capture versions
shell: bash
Expand All @@ -44,11 +51,12 @@ runs:
echo "pnpm=$(pnpm -v)" >> "$GITHUB_OUTPUT"

- name: pnpm install
working-directory: ${{ inputs.working-directory }}
run: pnpm i ${{ inputs.pnpm-install-options }}
shell: bash

- name: Run post-install commands
if: inputs.commands != ''
working-directory: ${{ inputs.working-directory }}
shell: bash
run: ${{ inputs.commands }}

Loading
Loading