Skip to content

refactor(e2e): only build zetanode once #2444

refactor(e2e): only build zetanode once

refactor(e2e): only build zetanode once #2444

Workflow file for this run

name: e2e
on:
push:
branches:
- develop
- release/*
pull_request:
merge_group:
schedule:
# run at 6AM UTC Daily
# 6AM UTC -> 11PM PT
- cron: "0 6 * * *"
workflow_dispatch:
inputs:
make-targets:
description: 'Comma separated list of make targets to run (without the start- prefix)'
required: true
default: ''
enable-monitoring:
description: 'Enable the monitoring stack'
required: true
type: boolean
default: false
concurrency:
group: e2e-${{ github.head_ref || github.sha }}
cancel-in-progress: true
jobs:
# this cannot run on forks as forks cannot push packages in pull request context
# forked pull request will fall back to slow build
build-zetanode:
runs-on: ubuntu-22.04
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'zeta-chain/node'
env:
DOCKER_IMAGE: ghcr.io/${{ github.repository_owner }}/zetanode
DOCKER_TAG: ${{ github.ref == 'refs/heads/develop' && 'develop' || github.sha }}
outputs:
image: ${{ fromJson(steps.build.outputs.metadata)['image.name'] }}
steps:
- uses: actions/checkout@v4
# configure docker to use the containerd snapshotter
# so that we can use the buildkit cache
- uses: depot/use-containerd-snapshotter-action@v1
- name: Login to Docker Hub registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_READ_ONLY }}
- name: Login to github docker registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Restore go cache
uses: actions/cache@v4
id: restore-go-cache
with:
path: |
go-cache
key: cache-${{ hashFiles('go.sum') }}
- name: Inject go cache into docker
uses: reproducible-containers/[email protected]
with:
cache-map: |
{
"go-cache": "/root/.cache/go-build"
}
skip-extraction: ${{ steps.restore-go-cache.outputs.cache-hit || github.event_name != 'push' }}
# this ensures that the version is consistent between cache build and make build
- name: Set version for cache
run: |
NODE_VERSION=$(./version.sh)
echo "NODE_VERSION=$NODE_VERSION" >> $GITHUB_ENV
NODE_COMMIT=$(git log -1 --format='%H')
echo "NODE_COMMIT=$NODE_COMMIT" >> $GITHUB_ENV
# build zetanode with cache options
- name: Build zetanode for cache
id: build
uses: docker/build-push-action@v6
env:
CACHE_FROM_CONFIG: "type=registry,ref=ghcr.io/${{ github.repository }}:buildcache"
CACHE_TO_CONFIG: "type=registry,ref=ghcr.io/${{ github.repository }}:buildcache,mode=max"
with:
context: .
file: ./Dockerfile-localnet
push: true
tags: ${{ env.DOCKER_IMAGE }}:${{ env.DOCKER_TAG }}
cache-from: ${{ env.CACHE_FROM_CONFIG }}
cache-to: ${{ github.event_name == 'push' && env.CACHE_TO_CONFIG || '' }}
target: latest-runtime
build-args: |
NODE_VERSION=${{ env.NODE_VERSION }}
NODE_COMMIT=${{ env.NODE_COMMIT }}
matrix-conditionals:
needs: build-zetanode
if: always()
runs-on: ubuntu-22.04
env:
GH_TOKEN: ${{ github.token }}
outputs:
DEFAULT_TESTS: ${{ steps.matrix-conditionals.outputs.DEFAULT_TESTS }}
UPGRADE_TESTS: ${{ steps.matrix-conditionals.outputs.UPGRADE_TESTS }}
UPGRADE_LIGHT_TESTS: ${{ steps.matrix-conditionals.outputs.UPGRADE_LIGHT_TESTS }}
UPGRADE_IMPORT_MAINNET_TESTS: ${{ steps.matrix-conditionals.outputs.UPGRADE_IMPORT_MAINNET_TESTS }}
ADMIN_TESTS: ${{ steps.matrix-conditionals.outputs.ADMIN_TESTS }}
PERFORMANCE_TESTS: ${{ steps.matrix-conditionals.outputs.PERFORMANCE_TESTS }}
STATEFUL_DATA_TESTS: ${{ steps.matrix-conditionals.outputs.STATEFUL_DATA_TESTS }}
TSS_MIGRATION_TESTS: ${{ steps.matrix-conditionals.outputs.TSS_MIGRATION_TESTS }}
SOLANA_TESTS: ${{ steps.matrix-conditionals.outputs.SOLANA_TESTS }}
TON_TESTS: ${{ steps.matrix-conditionals.outputs.TON_TESTS }}
V2_TESTS: ${{ steps.matrix-conditionals.outputs.V2_TESTS }}
V2_MIGRATION_TESTS: ${{ steps.matrix-conditionals.outputs.V2_MIGRATION_TESTS }}
ENABLE_MONITORING: ${{ steps.matrix-conditionals.outputs.ENABLE_MONITORING }}
steps:
# use api rather than event context to avoid race conditions (label added after push)
- id: matrix-conditionals
uses: actions/github-script@v7
with:
script: |
if (context.eventName === 'pull_request') {
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});
const labels = pr.labels.map(label => label.name);
console.log("labels:", labels);
core.setOutput('DEFAULT_TESTS', true);
core.setOutput('UPGRADE_TESTS', labels.includes('UPGRADE_TESTS'));
core.setOutput('UPGRADE_LIGHT_TESTS', labels.includes('UPGRADE_LIGHT_TESTS'));
core.setOutput('UPGRADE_IMPORT_MAINNET_TESTS', labels.includes('UPGRADE_IMPORT_MAINNET_TESTS'));
core.setOutput('ADMIN_TESTS', labels.includes('ADMIN_TESTS'));
core.setOutput('PERFORMANCE_TESTS', labels.includes('PERFORMANCE_TESTS'));
core.setOutput('STATEFUL_DATA_TESTS', labels.includes('STATEFUL_DATA_TESTS'));
core.setOutput('TSS_MIGRATION_TESTS', labels.includes('TSS_MIGRATION_TESTS'));
core.setOutput('SOLANA_TESTS', labels.includes('SOLANA_TESTS'));
core.setOutput('TON_TESTS', labels.includes('TON_TESTS'));
core.setOutput('V2_TESTS', labels.includes('V2_TESTS')); // for v2 tests, TODO: remove this once we fully migrate to v2 (https://github.com/zeta-chain/node/issues/2627)
core.setOutput('V2_MIGRATION_TESTS', labels.includes('V2_MIGRATION_TESTS')); // for v2 tests, TODO: remove this once we fully migrate to v2 (https://github.com/zeta-chain/node/issues/2627)
core.setOutput('ENABLE_MONITORING', labels.includes('ENABLE_MONITORING'));
} else if (context.eventName === 'merge_group') {
core.setOutput('DEFAULT_TESTS', true);
core.setOutput('UPGRADE_LIGHT_TESTS', true);
} else if (context.eventName === 'push' && context.ref === 'refs/heads/develop') {
core.setOutput('DEFAULT_TESTS', true);
} else if (context.eventName === 'push' && context.ref.startsWith('refs/heads/release/')) {
core.setOutput('DEFAULT_TESTS', true);
core.setOutput('UPGRADE_TESTS', true);
core.setOutput('UPGRADE_LIGHT_TESTS', true);
core.setOutput('UPGRADE_IMPORT_MAINNET_TESTS', true);
core.setOutput('ADMIN_TESTS', true);
core.setOutput('PERFORMANCE_TESTS', true);
core.setOutput('STATEFUL_DATA_TESTS', true);
core.setOutput('SOLANA_TESTS', true);
core.setOutput('TON_TESTS', true);
core.setOutput('V2_TESTS', true); // for v2 tests, TODO: remove this once we fully migrate to v2 (https://github.com/zeta-chain/node/issues/2627)
} else if (context.eventName === 'schedule') {
core.setOutput('DEFAULT_TESTS', true);
core.setOutput('UPGRADE_TESTS', true);
core.setOutput('UPGRADE_LIGHT_TESTS', true);
core.setOutput('UPGRADE_IMPORT_MAINNET_TESTS', true);
core.setOutput('ADMIN_TESTS', true);
core.setOutput('PERFORMANCE_TESTS', true);
core.setOutput('STATEFUL_DATA_TESTS', true);
core.setOutput('TSS_MIGRATION_TESTS', true);
core.setOutput('SOLANA_TESTS', true);
core.setOutput('TON_TESTS', true);
core.setOutput('V2_TESTS', true); // for v2 tests, TODO: remove this once we fully migrate to v2 (https://github.com/zeta-chain/node/issues/2627)
} else if (context.eventName === 'workflow_dispatch') {
const makeTargets = context.payload.inputs['make-targets'].split(',');
core.setOutput('DEFAULT_TESTS', makeTargets.includes('default-test'));
core.setOutput('UPGRADE_TESTS', makeTargets.includes('upgrade-test'));
core.setOutput('UPGRADE_LIGHT_TESTS', makeTargets.includes('upgrade-test-light'));
core.setOutput('UPGRADE_IMPORT_MAINNET_TESTS', makeTargets.includes('upgrade-import-mainnet-test'));
core.setOutput('ADMIN_TESTS', makeTargets.includes('admin-test'));
core.setOutput('PERFORMANCE_TESTS', makeTargets.includes('performance-test'));
core.setOutput('STATEFUL_DATA_TESTS', makeTargets.includes('import-mainnet-test'));
core.setOutput('TSS_MIGRATION_TESTS', makeTargets.includes('tss-migration-test'));
core.setOutput('SOLANA_TESTS', makeTargets.includes('solana-test'));
core.setOutput('TON_TESTS', makeTargets.includes('ton-test'));
core.setOutput('V2_TESTS', makeTargets.includes('v2-test')); // for v2 tests, TODO: remove this once we fully migrate to v2 (https://github.com/zeta-chain/node/issues/2627)
core.setOutput('V2_MIGRATION_TESTS', makeTargets.includes('v2-migration-test')); // for v2 tests, TODO: remove this once we fully migrate to v2 (https://github.com/zeta-chain/node/issues/2627)
core.setOutput('ENABLE_MONITORING', context.payload.inputs['enable-monitoring']);
}
e2e:
needs:
- build-zetanode
- matrix-conditionals
if: always()
strategy:
fail-fast: false
matrix:
include:
- make-target: "start-e2e-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.DEFAULT_TESTS == 'true' }}
- make-target: "start-upgrade-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.UPGRADE_TESTS == 'true' }}
- make-target: "start-upgrade-test-light"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.UPGRADE_LIGHT_TESTS == 'true' }}
- make-target: "start-upgrade-import-mainnet-test"
runs-on: buildjet-16vcpu-ubuntu-2204
run: ${{ needs.matrix-conditionals.outputs.UPGRADE_IMPORT_MAINNET_TESTS == 'true' }}
timeout-minutes: 40
- make-target: "start-e2e-admin-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.ADMIN_TESTS == 'true' }}
- make-target: "start-e2e-performance-test"
runs-on: buildjet-4vcpu-ubuntu-2204
run: ${{ needs.matrix-conditionals.outputs.PERFORMANCE_TESTS == 'true' }}
- make-target: "start-e2e-import-mainnet-test"
runs-on: buildjet-16vcpu-ubuntu-2204
run: ${{ needs.matrix-conditionals.outputs.STATEFUL_DATA_TESTS == 'true' }}
timeout-minutes: 40
- make-target: "start-tss-migration-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.TSS_MIGRATION_TESTS == 'true' }}
timeout-minutes: 40
- make-target: "start-solana-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.SOLANA_TESTS == 'true' }}
- make-target: "start-ton-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.TON_TESTS == 'true' }}
- make-target: "start-v2-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.V2_TESTS == 'true' }}
- make-target: "start-upgrade-v2-migration-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.V2_MIGRATION_TESTS == 'true' }}
name: ${{ matrix.make-target }}
uses: ./.github/workflows/reusable-e2e.yml
with:
make-target: ${{ matrix.make-target }}
runs-on: ${{ matrix.runs-on}}
run: ${{ matrix.run }}
timeout-minutes: "${{ matrix.timeout-minutes || 25 }}"
zetanode-image: ${{ needs.build-zetanode.outputs.image }}
enable-monitoring: ${{ needs.matrix-conditionals.outputs.ENABLE_MONITORING == 'true' }}
secrets: inherit
# this allows you to set a required status check
e2e-ok:
runs-on: ubuntu-22.04
needs:
- build-zetanode
- matrix-conditionals
- e2e
if: always()
steps:
- name: Send slack message with results
uses: actions/github-script@v7
if: ${{ github.event_name == 'schedule' || (github.event_name == 'push' && needs.e2e.result == 'failure') }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_ALERTS }}
with:
script: |
const {data} = await github.rest.actions.listJobsForWorkflowRunAttempt({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId,
attempt_number: ${{ github.run_attempt }},
});
const e2eJobs = data.jobs.filter(job => job.name.includes('/') && job.conclusion != 'skipped');
const e2eResults = e2eJobs.map(job => {
const icon = job.conclusion === 'success' ? ':white_check_mark:' : ':x:';
const cleanName = job.name.split("/")[0];
return `${icon} ${cleanName}`;
});
e2eResults.sort();
const overallResultStr = '${{ needs.e2e.result }}';
const overallResultPassing = overallResultStr === 'success' || overallResultStr === 'skipped';
const overallResultIcon = overallResultPassing ? ':white_check_mark:' : ':x:';
let overallResultText = `<https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}|E2E Test Run Results>`;
if (context.eventName === 'push') {
overallResultText += ` for push to ${context.ref}`;
} else if (context.eventName === 'schedule') {
overallResultText += ` for scheduled run`;
}
const msg = `${overallResultIcon} ${overallResultText}\n${e2eResults.join('\n')}`;
await fetch(process.env.SLACK_WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({text: msg}),
});
- run: |
result="${{ needs.build-zetanode.result }}"
if [[ $result == "failed" ]]; then
exit 1
fi
result="${{ needs.e2e.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
exit 1
fi