From 09bf9dfe329fd17bdd408279db6ee2de18f64644 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Fri, 17 Oct 2025 16:41:27 +0100 Subject: [PATCH 01/25] make docker build work on linux with non-root user --- .dockerignore | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..7aab47b6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +# Exclude database and execution data directories from Docker build context +blockscout-postgres-data/ +execution-data/ +blockscout-db-data/ + +# Exclude git directory +.git/ +.gitmodules + +# Exclude deployment artifacts +deployment/ + +# Exclude environment files +.env +.env.* + +# Exclude docker compose files (not needed in build context) +docker-compose*.yml + +# Exclude any other data directories +*-data/ +data/ From 368d9e06c2192c31fabc0cf1f6abc5bb0a37dc5c Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Fri, 17 Oct 2025 18:16:39 +0000 Subject: [PATCH 02/25] non-root build docker issues; ci check script --- .dockerignore | 5 + .../workflows/daily-devnet-health-check.yml | 103 +++++++++++ .gitignore | 12 +- blockscout-postgres-data/.gitkeep | 0 execution-data/.gitkeep | 0 mysql-data/.gitkeep | 0 rabbitmq/.gitkeep | 0 script/test-health-check.sh | 164 ++++++++++++++++++ surge-protocol-deployer.sh | 164 +++++++++++------- surge-remover.sh | 21 ++- surge-stack-deployer.sh | 116 +++++++------ 11 files changed, 461 insertions(+), 124 deletions(-) create mode 100644 .github/workflows/daily-devnet-health-check.yml create mode 100644 blockscout-postgres-data/.gitkeep create mode 100644 execution-data/.gitkeep create mode 100644 mysql-data/.gitkeep create mode 100644 rabbitmq/.gitkeep create mode 100755 script/test-health-check.sh diff --git a/.dockerignore b/.dockerignore index 7aab47b6..8c427131 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,6 +2,8 @@ blockscout-postgres-data/ execution-data/ blockscout-db-data/ +mysql-data/ +rabbitmq/ # Exclude git directory .git/ @@ -20,3 +22,6 @@ docker-compose*.yml # Exclude any other data directories *-data/ data/ + +# Exclude temporary files +tmp/ diff --git a/.github/workflows/daily-devnet-health-check.yml b/.github/workflows/daily-devnet-health-check.yml new file mode 100644 index 00000000..dc43e11b --- /dev/null +++ b/.github/workflows/daily-devnet-health-check.yml @@ -0,0 +1,103 @@ +name: Daily Devnet Health Check + +on: + schedule: + # Run daily at 2 AM UTC + - cron: '0 2 * * *' + workflow_dispatch: + +jobs: + run-health-check: + runs-on: ubuntu-latest + timeout-minutes: 90 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y bc jq + + - name: Run health check script + id: health_check + run: | + ./script/test-health-check.sh + continue-on-error: true + + - name: Upload deployment artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: deployment-artifacts + path: | + deployment/*.json + deployment/*.lock + retention-days: 7 + + - name: Upload logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: execution-logs + path: | + execution-data/logs + retention-days: 7 + + - name: Check health check result + if: steps.health_check.outcome == 'failure' + run: | + echo "Health check failed" + exit 1 + + notify-on-failure: + runs-on: ubuntu-latest + needs: [run-health-check] + if: failure() + + steps: + - name: Create issue on failure + uses: actions/github-script@v7 + with: + script: | + const title = `Daily Devnet Health Check Failed - ${new Date().toISOString().split('T')[0]}`; + const body = `The daily devnet health check failed. Please investigate. + + **Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + + **Status:** ${{ needs.run-health-check.result }} + + See the workflow artifacts for deployment artifacts and execution logs. + `; + + const issues = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'daily-health-check' + }); + + const existingIssue = issues.data.find(issue => issue.title.includes('Daily Devnet Health Check Failed')); + + if (!existingIssue) { + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: body, + labels: ['daily-health-check', 'bug'] + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: existingIssue.number, + body: `Another failure occurred:\n\n${body}` + }); + } diff --git a/.gitignore b/.gitignore index 8b21338f..1ea3574a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,14 @@ .idea/ -/mysql-data/ -/rabbitmq/ -/execution-data/ +/mysql-data/* +!/mysql-data/.gitkeep +/rabbitmq/* +!/rabbitmq/.gitkeep +/execution-data/* +!/execution-data/.gitkeep /deployment/*.json /deployment/*.lock /configs/*.json -/blockscout-postgres-data/ +/blockscout-postgres-data/* +!/blockscout-postgres-data/.gitkeep diff --git a/blockscout-postgres-data/.gitkeep b/blockscout-postgres-data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/execution-data/.gitkeep b/execution-data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/mysql-data/.gitkeep b/mysql-data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rabbitmq/.gitkeep b/rabbitmq/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/script/test-health-check.sh b/script/test-health-check.sh new file mode 100755 index 00000000..971ebfca --- /dev/null +++ b/script/test-health-check.sh @@ -0,0 +1,164 @@ +#!/bin/bash + +set -e + +echo "==========================================" +echo "Starting Local Devnet Health Check" +echo "==========================================" +echo + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +print_success() { + echo -e "${GREEN}✓ $1${NC}" +} + +print_error() { + echo -e "${RED}✗ $1${NC}" +} + +print_info() { + echo -e "${YELLOW}ℹ $1${NC}" +} + +# Ensure we're in the project root +cd "$(dirname "$0")/.." + +# Step 1: Clean up any existing deployment +echo "==========================================" +echo "Step 1: Cleanup existing deployment" +echo "==========================================" +print_info "Running surge-remover.sh --devnet-non-interactive" +if ./surge-remover.sh --devnet-non-interactive; then + print_success "Cleanup completed" +else + print_error "Cleanup failed" + exit 1 +fi + +# Initialize data directories with correct permissions +print_info "Initializing data directories with current user permissions" +if ./script/init-data-directories.sh; then + print_success "Data directories initialized" +else + print_error "Failed to initialize data directories" + exit 1 +fi +echo + +# Step 2: Ensure .env file exists +echo "==========================================" +echo "Step 2: Prepare environment" +echo "==========================================" +if [ ! -f .env ]; then + print_info "Copying .env.devnet to .env" + cp .env.devnet .env + print_success ".env file created" +else + print_info ".env file already exists" +fi +echo + +# Step 3: Deploy protocol +echo "==========================================" +echo "Step 3: Deploy protocol (L1 contracts)" +echo "==========================================" +print_info "Running surge-protocol-deployer.sh --devnet-non-interactive" +if ./surge-protocol-deployer.sh --devnet-non-interactive; then + print_success "Protocol deployment completed" +else + print_error "Protocol deployment failed" + exit 1 +fi +echo + +# Step 4: Verify protocol deployment artifacts +echo "==========================================" +echo "Step 4: Verify protocol deployment" +echo "==========================================" +if [ ! -f "deployment/deploy_l1.json" ]; then + print_error "deploy_l1.json not found" + exit 1 +else + print_success "deploy_l1.json found" +fi + +if [ ! -f "deployment/proposer_wrappers.json" ]; then + print_error "proposer_wrappers.json not found" + exit 1 +else + print_success "proposer_wrappers.json found" +fi +echo + +# Step 5: Deploy stack +echo "==========================================" +echo "Step 5: Deploy L2 stack" +echo "==========================================" +print_info "Running surge-stack-deployer.sh --devnet-non-interactive" +if ./surge-stack-deployer.sh --devnet-non-interactive; then + print_success "Stack deployment completed" +else + print_error "Stack deployment failed" + exit 1 +fi +echo + +# Step 6: Verify services are running +echo "==========================================" +echo "Step 6: Verify services" +echo "==========================================" +print_info "Checking running containers" +docker compose ps +echo + +# Step 7: Wait for L2 execution client to be ready +echo "==========================================" +echo "Step 7: Health check L2 execution client" +echo "==========================================" +print_info "Waiting 30 seconds for services to stabilize..." +sleep 30 + +print_info "Testing L2 RPC endpoint at http://localhost:8547" +if curl -f http://localhost:8547 -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then + echo + print_success "L2 execution client is healthy" +else + echo + print_error "L2 execution client health check failed" + exit 1 +fi +echo + +# Step 8: Optional - Check container logs for errors +echo "==========================================" +echo "Step 8: Check for errors in logs" +echo "==========================================" +print_info "Checking for errors in container logs (last 50 lines)" +if docker compose logs --tail=50 | grep -i "error\|fatal\|panic" | grep -v "error_code" | head -20; then + print_info "Found some errors in logs (review above)" +else + print_success "No critical errors found in recent logs" +fi +echo + +# Final summary +echo "==========================================" +echo "Health Check Summary" +echo "==========================================" +print_success "All health checks passed!" +echo +print_info "Services are running. You can now:" +echo " - Access L2 RPC: http://localhost:8547" +echo " - Access L2 Blockscout: http://localhost:3000" +echo " - Access L1 RPC: http://localhost:32003" +echo " - View logs: docker compose logs -f" +echo +print_info "To clean up when done:" +echo " ./surge-remover.sh --devnet-non-interactive" +echo diff --git a/surge-protocol-deployer.sh b/surge-protocol-deployer.sh index 0f8b87a1..d20f39f6 100755 --- a/surge-protocol-deployer.sh +++ b/surge-protocol-deployer.sh @@ -4,41 +4,53 @@ set -e git submodule update --init --recursive -# Select which Surge environment to use -echo -echo "╔══════════════════════════════════════════════════════════════╗" -echo " ⚠️ Select which Surge environment to use: " -echo "║══════════════════════════════════════════════════════════════║" -echo "║ 1 for Devnet ║" -echo "║ 2 for Staging ║" -echo "║ 3 for Testnet ║" -echo "║ [default: Devnet] ║" -echo "╚══════════════════════════════════════════════════════════════╝" -echo -read -r surge_environment - -SURGE_ENVIRONMENT=${surge_environment:-1} +NON_INTERACTIVE=false +if [ "$1" = "--devnet-non-interactive" ]; then + NON_INTERACTIVE=true +fi -if [ "$SURGE_ENVIRONMENT" = "1" ]; then +if [ "$NON_INTERACTIVE" = "true" ]; then + SURGE_ENVIRONMENT=1 + REMOTE_OR_LOCAL=0 +else + # Select which Surge environment to use echo echo "╔══════════════════════════════════════════════════════════════╗" - echo " 🚀 Using Devnet Environment " + echo " ⚠️ Select which Surge environment to use: " + echo "║══════════════════════════════════════════════════════════════║" + echo "║ 1 for Devnet ║" + echo "║ 2 for Staging ║" + echo "║ 3 for Testnet ║" + echo "║ [default: Devnet] ║" echo "╚══════════════════════════════════════════════════════════════╝" echo + read -r surge_environment - # Select remote or local + SURGE_ENVIRONMENT=${surge_environment:-1} +fi + +if [ "$SURGE_ENVIRONMENT" = "1" ]; then echo echo "╔══════════════════════════════════════════════════════════════╗" - echo " ⚠️ Select remote or local: " - echo "║══════════════════════════════════════════════════════════════║" - echo "║ 0 for local ║" - echo "║ 1 for remote ║" - echo "║ [default: local] ║" + echo " 🚀 Using Devnet Environment " echo "╚══════════════════════════════════════════════════════════════╝" echo - read -r remote_or_local -REMOTE_OR_LOCAL=${remote_or_local:-0} + if [ "$NON_INTERACTIVE" = "false" ]; then + # Select remote or local + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo " ⚠️ Select remote or local: " + echo "║══════════════════════════════════════════════════════════════║" + echo "║ 0 for local ║" + echo "║ 1 for remote ║" + echo "║ [default: local] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r remote_or_local + + REMOTE_OR_LOCAL=${remote_or_local:-0} + fi if [ "$REMOTE_OR_LOCAL" = "1" ]; then # Select which devnet machine to use echo @@ -344,17 +356,21 @@ deploy_l1() { # Check if deployment is already completed if [ -f "deployment/deploy_l1.json" ]; then - # Prompt user for starting a new deployment if the deployment results are already present - echo - echo "╔══════════════════════════════════════════════════════════════╗" - echo " ⚠️ Surge L1 deployment already completed " - echo " (deploy_l1.json exists) " - echo "║══════════════════════════════════════════════════════════════║" - echo "║ Start a new deployment? (true/false) [default: false] ║" - echo "╚══════════════════════════════════════════════════════════════╝" - echo - read -r start_new_deployment - START_NEW_DEPLOYMENT=${start_new_deployment:-false} + if [ "$NON_INTERACTIVE" = "true" ]; then + START_NEW_DEPLOYMENT=false + else + # Prompt user for starting a new deployment if the deployment results are already present + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo " ⚠️ Surge L1 deployment already completed " + echo " (deploy_l1.json exists) " + echo "║══════════════════════════════════════════════════════════════║" + echo "║ Start a new deployment? (true/false) [default: false] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r start_new_deployment + START_NEW_DEPLOYMENT=${start_new_deployment:-false} + fi if [ "$START_NEW_DEPLOYMENT" = "true" ]; then echo @@ -400,15 +416,19 @@ deploy_l1() { echo "╚══════════════════════════════════════════════════════════════╝" echo - # Prompt user for USE_TIMELOCKED_OWNER with default to false - echo - echo "╔══════════════════════════════════════════════════════════════╗" - echo "║ Use timelocked owner? (true/false) [default: false] ║" - echo "╚══════════════════════════════════════════════════════════════╝" - echo - read -r timelocked_owner + if [ "$NON_INTERACTIVE" = "true" ]; then + export USE_TIMELOCKED_OWNER=false + else + # Prompt user for USE_TIMELOCKED_OWNER with default to false + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ Use timelocked owner? (true/false) [default: false] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r timelocked_owner - export USE_TIMELOCKED_OWNER=${timelocked_owner:-false} + export USE_TIMELOCKED_OWNER=${timelocked_owner:-false} + fi # Update USE_TIMELOCKED_OWNER in env file for other functions and scripts to use update_env_var ".env" "USE_TIMELOCKED_OWNER" "$USE_TIMELOCKED_OWNER" @@ -569,15 +589,19 @@ extract_surge_proposer_wrapper() { } deploy_provers() { - # Prompt user for RUNNING_PROVERS with default to false - echo - echo "╔══════════════════════════════════════════════════════════════╗" - echo "║ Running provers? (true/false) [default: false] ║" - echo "╚══════════════════════════════════════════════════════════════╝" - echo - read -r running_provers + if [ "$NON_INTERACTIVE" = "true" ]; then + RUNNING_PROVERS=false + else + # Prompt user for RUNNING_PROVERS with default to false + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ Running provers? (true/false) [default: false] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r running_provers - RUNNING_PROVERS=${running_provers:-false} + RUNNING_PROVERS=${running_provers:-false} + fi # If running provers is true, set up the verifiers if [ "$RUNNING_PROVERS" = "true" ]; then @@ -783,26 +807,34 @@ deposit_bond() { echo "╚══════════════════════════════════════════════════════════════╝" echo - # Prompt user for deposit bond - echo - echo "╔══════════════════════════════════════════════════════════════╗" - echo "║ Deposit bond? (true/false) [default: true] ║" - echo "╚══════════════════════════════════════════════════════════════╝" - echo - read -r deposit_bond - - DEPOSIT_BOND=${deposit_bond:-true} - - if [ "$DEPOSIT_BOND" = "true" ]; then - # Prompt user for BOND_AMOUNT + if [ "$NON_INTERACTIVE" = "true" ]; then + DEPOSIT_BOND=true + else + # Prompt user for deposit bond echo echo "╔══════════════════════════════════════════════════════════════╗" - echo "║ Enter bond amount (in ETH, default: 1000) ║" + echo "║ Deposit bond? (true/false) [default: true] ║" echo "╚══════════════════════════════════════════════════════════════╝" echo - read -r bond_amount + read -r deposit_bond + + DEPOSIT_BOND=${deposit_bond:-true} + fi - BOND_AMOUNT=${bond_amount:-1000} + if [ "$DEPOSIT_BOND" = "true" ]; then + if [ "$NON_INTERACTIVE" = "true" ]; then + BOND_AMOUNT=1000 + else + # Prompt user for BOND_AMOUNT + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ Enter bond amount (in ETH, default: 1000) ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r bond_amount + + BOND_AMOUNT=${bond_amount:-1000} + fi # Convert to wei export BOND_AMOUNT=$(echo "$BOND_AMOUNT * 1000000000000000000" | bc | cut -d. -f1) diff --git a/surge-remover.sh b/surge-remover.sh index a40e8b6c..ac7c2576 100755 --- a/surge-remover.sh +++ b/surge-remover.sh @@ -2,6 +2,11 @@ set -e +NON_INTERACTIVE=false +if [ "$1" = "--devnet-non-interactive" ]; then + NON_INTERACTIVE=true +fi + remove_l2_stack() { echo echo "╔══════════════════════════════════════════════════════════════╗" @@ -49,11 +54,17 @@ remove_db() { echo "╚══════════════════════════════════════════════════════════════╝" echo - # Remove DB - rm -rf ./execution-data - rm -rf ./blockscout-postgres-data - rm -rf ./mysql-data - rm -rf ./rabbitmq + # Remove DB contents but preserve directory structure with .gitkeep + rm -rf ./execution-data/* + rm -rf ./blockscout-postgres-data/* + rm -rf ./mysql-data/* + rm -rf ./rabbitmq/* + + # Recreate .gitkeep files + touch ./execution-data/.gitkeep + touch ./blockscout-postgres-data/.gitkeep + touch ./mysql-data/.gitkeep + touch ./rabbitmq/.gitkeep echo echo "╔══════════════════════════════════════════════════════════════╗" diff --git a/surge-stack-deployer.sh b/surge-stack-deployer.sh index e6c606ef..51bce27a 100755 --- a/surge-stack-deployer.sh +++ b/surge-stack-deployer.sh @@ -4,6 +4,11 @@ set -e git submodule update --init --recursive +NON_INTERACTIVE=false +if [ "$1" = "--devnet-non-interactive" ]; then + NON_INTERACTIVE=true +fi + check_env_file() { if [ -f .env ]; then echo @@ -63,34 +68,39 @@ prepare_blockscout_for_remote() { sed -i.bak 's/^BLOCKSCOUT_L2_HOST=.*/BLOCKSCOUT_L2_HOST='$MACHINE_IP'/g' .env } -# Select which Surge environment to use -echo -echo "╔══════════════════════════════════════════════════════════════╗" -echo " ⚠️ Select which Surge environment to use: " -echo "║══════════════════════════════════════════════════════════════║" -echo "║ 1 for Devnet ║" -echo "║ 2 for Staging ║" -echo "║ 3 for Testnet ║" -echo "║ [default: Devnet] ║" -echo "╚══════════════════════════════════════════════════════════════╝" -echo -read -r surge_environment - -SURGE_ENVIRONMENT=${surge_environment:-1} - -# Select remote or local -echo -echo "╔══════════════════════════════════════════════════════════════╗" -echo " ⚠️ Select remote or local: " -echo "║══════════════════════════════════════════════════════════════║" -echo "║ 0 for local ║" -echo "║ 1 for remote ║" -echo "║ [default: local] ║" -echo "╚══════════════════════════════════════════════════════════════╝" -echo -read -r remote_or_local - -REMOTE_OR_LOCAL=${remote_or_local:-0} +if [ "$NON_INTERACTIVE" = "true" ]; then + SURGE_ENVIRONMENT=1 + REMOTE_OR_LOCAL=0 +else + # Select which Surge environment to use + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo " ⚠️ Select which Surge environment to use: " + echo "║══════════════════════════════════════════════════════════════║" + echo "║ 1 for Devnet ║" + echo "║ 2 for Staging ║" + echo "║ 3 for Testnet ║" + echo "║ [default: Devnet] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r surge_environment + + SURGE_ENVIRONMENT=${surge_environment:-1} + + # Select remote or local + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo " ⚠️ Select remote or local: " + echo "║══════════════════════════════════════════════════════════════║" + echo "║ 0 for local ║" + echo "║ 1 for remote ║" + echo "║ [default: local] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r remote_or_local + + REMOTE_OR_LOCAL=${remote_or_local:-0} +fi if [ "$REMOTE_OR_LOCAL" = "1" ]; then echo @@ -208,19 +218,23 @@ start_l2_stack() { echo "╚══════════════════════════════════════════════════════════════╝" echo - # Prompt user for L2_STACK_OPTION - echo - echo "╔══════════════════════════════════════════════════════════════╗" - echo "║ Enter L2 stack option: ║" - echo "║ 1 for driver only ║" - echo "║ 2 for driver + proposer ║" - echo "║ 3 for driver + proposer + spammer ║" - echo "║ 4 for driver + proposer + prover + spammer ║" - echo "║ 5 for all except spammer ║" - echo "║ [default: all] ║" - echo "╚══════════════════════════════════════════════════════════════╝" - echo - read -r l2_stack_option + if [ "$NON_INTERACTIVE" = "true" ]; then + l2_stack_option="" + else + # Prompt user for L2_STACK_OPTION + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ Enter L2 stack option: ║" + echo "║ 1 for driver only ║" + echo "║ 2 for driver + proposer ║" + echo "║ 3 for driver + proposer + spammer ║" + echo "║ 4 for driver + proposer + prover + spammer ║" + echo "║ 5 for all except spammer ║" + echo "║ [default: all] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r l2_stack_option + fi if [ "$l2_stack_option" = "1" ]; then docker compose --profile driver --profile blockscout up -d --remove-orphans @@ -261,15 +275,19 @@ deploy_l2() { } start_relayers() { - # Prompt user for START_RELAYERS - echo - echo "╔══════════════════════════════════════════════════════════════╗" - echo "║ Start relayers? (true/false) [default: true] ║" - echo "╚══════════════════════════════════════════════════════════════╝" - echo - read -r start_relayers + if [ "$NON_INTERACTIVE" = "true" ]; then + START_RELAYERS=true + else + # Prompt user for START_RELAYERS + echo + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ Start relayers? (true/false) [default: true] ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo + read -r start_relayers - START_RELAYERS=${start_relayers:-true} + START_RELAYERS=${start_relayers:-true} + fi if [ "$START_RELAYERS" = "true" ]; then if [ "$SURGE_ENVIRONMENT" = "1" ]; then From 24434e38f89c98eaf927fdf185d03460985415eb Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Fri, 17 Oct 2025 18:21:58 +0000 Subject: [PATCH 03/25] rename --- .../workflows/daily-devnet-health-check.yml | 103 ------------------ ...check.sh => devnet-e2e-provision-check.sh} | 0 2 files changed, 103 deletions(-) delete mode 100644 .github/workflows/daily-devnet-health-check.yml rename script/{test-health-check.sh => devnet-e2e-provision-check.sh} (100%) diff --git a/.github/workflows/daily-devnet-health-check.yml b/.github/workflows/daily-devnet-health-check.yml deleted file mode 100644 index dc43e11b..00000000 --- a/.github/workflows/daily-devnet-health-check.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: Daily Devnet Health Check - -on: - schedule: - # Run daily at 2 AM UTC - - cron: '0 2 * * *' - workflow_dispatch: - -jobs: - run-health-check: - runs-on: ubuntu-latest - timeout-minutes: 90 - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y bc jq - - - name: Run health check script - id: health_check - run: | - ./script/test-health-check.sh - continue-on-error: true - - - name: Upload deployment artifacts - if: always() - uses: actions/upload-artifact@v4 - with: - name: deployment-artifacts - path: | - deployment/*.json - deployment/*.lock - retention-days: 7 - - - name: Upload logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: execution-logs - path: | - execution-data/logs - retention-days: 7 - - - name: Check health check result - if: steps.health_check.outcome == 'failure' - run: | - echo "Health check failed" - exit 1 - - notify-on-failure: - runs-on: ubuntu-latest - needs: [run-health-check] - if: failure() - - steps: - - name: Create issue on failure - uses: actions/github-script@v7 - with: - script: | - const title = `Daily Devnet Health Check Failed - ${new Date().toISOString().split('T')[0]}`; - const body = `The daily devnet health check failed. Please investigate. - - **Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - **Status:** ${{ needs.run-health-check.result }} - - See the workflow artifacts for deployment artifacts and execution logs. - `; - - const issues = await github.rest.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - labels: 'daily-health-check' - }); - - const existingIssue = issues.data.find(issue => issue.title.includes('Daily Devnet Health Check Failed')); - - if (!existingIssue) { - await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: title, - body: body, - labels: ['daily-health-check', 'bug'] - }); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: existingIssue.number, - body: `Another failure occurred:\n\n${body}` - }); - } diff --git a/script/test-health-check.sh b/script/devnet-e2e-provision-check.sh similarity index 100% rename from script/test-health-check.sh rename to script/devnet-e2e-provision-check.sh From b65668d0e6749e81b967b76d8e8239254ad8edf8 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Sat, 18 Oct 2025 07:49:31 +0000 Subject: [PATCH 04/25] check containers --- script/devnet-e2e-provision-check.sh | 48 ++++++++++++++++++++-------- surge-remover.sh | 20 +++++++++--- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/script/devnet-e2e-provision-check.sh b/script/devnet-e2e-provision-check.sh index 971ebfca..127ad8b7 100755 --- a/script/devnet-e2e-provision-check.sh +++ b/script/devnet-e2e-provision-check.sh @@ -40,15 +40,6 @@ else print_error "Cleanup failed" exit 1 fi - -# Initialize data directories with correct permissions -print_info "Initializing data directories with current user permissions" -if ./script/init-data-directories.sh; then - print_success "Data directories initialized" -else - print_error "Failed to initialize data directories" - exit 1 -fi echo # Step 2: Ensure .env file exists @@ -117,9 +108,30 @@ print_info "Checking running containers" docker compose ps echo -# Step 7: Wait for L2 execution client to be ready +print_info "Checking critical containers are healthy..." +# Check L2 execution client container +if docker compose ps | grep "l2-nethermind-execution-client" | grep -q "(healthy)"; then + print_success "L2 execution client container is healthy" +else + print_error "L2 execution client container is not healthy" + exit 1 +fi + +# Check other critical containers are running +CRITICAL_CONTAINERS=("l2-taiko-consensus-client" "l2-taiko-proposer-client" "relayer-l1-indexer" "relayer-l2-indexer") +for container in "${CRITICAL_CONTAINERS[@]}"; do + if docker compose ps | grep "$container" | grep -q "Up"; then + print_success "$container is running" + else + print_error "$container is not running" + exit 1 + fi +done +echo + +# Step 7: Health check L2 RPC endpoints echo "==========================================" -echo "Step 7: Health check L2 execution client" +echo "Step 7: Health check L2 RPC endpoints" echo "==========================================" print_info "Waiting 30 seconds for services to stabilize..." sleep 30 @@ -127,10 +139,20 @@ sleep 30 print_info "Testing L2 RPC endpoint at http://localhost:8547" if curl -f http://localhost:8547 -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then echo - print_success "L2 execution client is healthy" + print_success "L2 execution client RPC is responding" +else + echo + print_error "L2 execution client RPC health check failed" + exit 1 +fi + +print_info "Testing L2 WebSocket endpoint at ws://localhost:8548" +if curl -f http://localhost:8548 -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then + echo + print_success "L2 WebSocket endpoint is responding" else echo - print_error "L2 execution client health check failed" + print_error "L2 WebSocket endpoint health check failed" exit 1 fi echo diff --git a/surge-remover.sh b/surge-remover.sh index ac7c2576..e53b130e 100755 --- a/surge-remover.sh +++ b/surge-remover.sh @@ -55,10 +55,22 @@ remove_db() { echo # Remove DB contents but preserve directory structure with .gitkeep - rm -rf ./execution-data/* - rm -rf ./blockscout-postgres-data/* - rm -rf ./mysql-data/* - rm -rf ./rabbitmq/* + # Use sudo for directories that might be owned by root + if [ -d "./execution-data" ] && [ "$(ls -A ./execution-data 2>/dev/null | wc -l)" -gt 0 ]; then + sudo rm -rf ./execution-data/* || echo "Warning: Could not remove some execution-data files" + fi + + if [ -d "./blockscout-postgres-data" ] && [ "$(ls -A ./blockscout-postgres-data 2>/dev/null | wc -l)" -gt 0 ]; then + sudo rm -rf ./blockscout-postgres-data/* || echo "Warning: Could not remove some blockscout-postgres-data files" + fi + + if [ -d "./mysql-data" ] && [ "$(ls -A ./mysql-data 2>/dev/null | wc -l)" -gt 0 ]; then + sudo rm -rf ./mysql-data/* || echo "Warning: Could not remove some mysql-data files" + fi + + if [ -d "./rabbitmq" ] && [ "$(ls -A ./rabbitmq 2>/dev/null | wc -l)" -gt 0 ]; then + sudo rm -rf ./rabbitmq/* || echo "Warning: Could not remove some rabbitmq files" + fi # Recreate .gitkeep files touch ./execution-data/.gitkeep From ff95414b8bd8a5c991e1a4219413c5876cfaa7e6 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 09:23:29 +0100 Subject: [PATCH 05/25] feat(ci): add e2e check --- .github/workflows/devnet-e2e-test.yml | 217 ++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 .github/workflows/devnet-e2e-test.yml diff --git a/.github/workflows/devnet-e2e-test.yml b/.github/workflows/devnet-e2e-test.yml new file mode 100644 index 00000000..a8716e44 --- /dev/null +++ b/.github/workflows/devnet-e2e-test.yml @@ -0,0 +1,217 @@ +name: Devnet E2E Test + +on: + schedule: + # Run nightly at 2 AM UTC + - cron: '0 2 * * *' + workflow_dispatch: + # Allow manual trigger + pull_request: + paths: + - 'docker-compose*.yml' + - 'surge-*.sh' + - 'script/devnet-e2e-provision-check.sh' + - '.github/workflows/devnet-e2e-test.yml' + +env: + SURGE_ETHEREUM_PACKAGE_REPO: 'NethermindEth/surge-ethereum-package' + SURGE_ETHEREUM_PACKAGE_REF: 'main' + +jobs: + devnet-e2e-test: + name: Full Devnet E2E Test + runs-on: ubuntu-22.04 + timeout-minutes: 60 + + steps: + - name: Maximize build space + uses: easimon/maximize-build-space@master + with: + root-reserve-mb: 30720 + remove-dotnet: 'true' + remove-android: 'true' + remove-haskell: 'true' + remove-codeql: 'true' + + - name: Checkout simple-surge-node + uses: actions/checkout@v4 + with: + path: simple-surge-node + + - name: Checkout surge-ethereum-package + uses: actions/checkout@v4 + with: + repository: ${{ env.SURGE_ETHEREUM_PACKAGE_REPO }} + ref: ${{ env.SURGE_ETHEREUM_PACKAGE_REF }} + path: surge-ethereum-package + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y curl jq + + - name: Install Kurtosis CLI + run: | + echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list + sudo apt-get update + sudo apt-get install -y kurtosis-cli + kurtosis version + + - name: Verify Docker installation + run: | + docker --version + docker compose version + docker info + + - name: Update e2e script with L1 deployment paths + working-directory: simple-surge-node + run: | + # Create a wrapper script that handles L1 deployment + cat > script/devnet-e2e-provision-check-ci.sh << 'EOF' + #!/bin/bash + + set -e + + echo "Starting CI Devnet E2E Health Check" + echo + + print_success() { + echo "[SUCCESS] $1" + } + + print_error() { + echo "[ERROR] $1" + } + + print_info() { + echo "[INFO] $1" + } + + # Navigate to project root + cd "$(dirname "$0")/.." + + # Step 0: Deploy L1 Devnet + echo "Step 0: Deploy L1 Devnet" + L1_DEPLOY_SCRIPT="../surge-ethereum-package/deploy-surge-devnet-l1.sh" + + if [ -f "$L1_DEPLOY_SCRIPT" ]; then + print_info "Running L1 deployment from surge-ethereum-package" + if "$L1_DEPLOY_SCRIPT" --environment local --mode silence; then + print_success "L1 deployment completed" + else + print_error "L1 deployment failed" + exit 1 + fi + else + print_error "L1 deployment script not found at $L1_DEPLOY_SCRIPT" + print_info "Current directory: $(pwd)" + print_info "Looking for: $L1_DEPLOY_SCRIPT" + ls -la ../ + exit 1 + fi + echo + + # Step 0.5: Wait for L1 to be ready + echo "Step 0.5: Verify L1 is ready" + print_info "Waiting 20 seconds for L1 to stabilize..." + sleep 20 + + print_info "Testing L1 RPC endpoint at http://localhost:32003" + max_retries=10 + retry_count=0 + + while [ $retry_count -lt $max_retries ]; do + if curl -f http://localhost:32003 -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then + echo + print_success "L1 RPC is responding" + break + else + retry_count=$((retry_count + 1)) + if [ $retry_count -eq $max_retries ]; then + echo + print_error "L1 RPC failed to respond after $max_retries retries" + exit 1 + fi + print_info "Retry $retry_count/$max_retries - waiting 10s..." + sleep 10 + fi + done + echo + + # Run the actual e2e provision check + echo "Running E2E Provision Check" + ./script/devnet-e2e-provision-check.sh + EOF + + chmod +x script/devnet-e2e-provision-check-ci.sh + + - name: Run E2E Devnet Test + working-directory: simple-surge-node + run: | + ./script/devnet-e2e-provision-check-ci.sh + + - name: Collect Docker logs on failure + if: failure() + working-directory: simple-surge-node + run: | + echo "Docker Compose Services Status" + docker compose ps || true + + echo "Docker Compose Logs (last 100 lines)" + docker compose logs --tail=100 || true + + echo "Kurtosis Enclaves" + kurtosis enclave ls || true + + echo "Kurtosis Services (surge-devnet)" + kurtosis enclave inspect surge-devnet || true + + - name: Cleanup - Stop L2 services + if: always() + working-directory: simple-surge-node + run: | + ./surge-remover.sh --devnet-non-interactive || true + + - name: Cleanup - Stop L1 devnet + if: always() + run: | + ../surge-ethereum-package/remove-surge-devnet-l1.sh --force || true + working-directory: simple-surge-node + + - name: Cleanup - Kurtosis + if: always() + run: | + kurtosis clean -a || true + + - name: Cleanup - Docker + if: always() + run: | + docker system prune -af --volumes || true + + - name: Upload test artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: devnet-e2e-logs + path: | + simple-surge-node/deployment/*.json + simple-surge-node/*.log + retention-days: 7 + if-no-files-found: ignore + + - name: Notify on failure + if: failure() && github.event_name == 'schedule' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Nightly Devnet E2E Test Failed', + body: `The nightly devnet E2E test failed on ${new Date().toISOString()}\n\nWorkflow run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, + labels: ['bug', 'devnet', 'e2e-test', 'automated'] + }) From 6fc5cadb4918691b7bcfc56bde2aaecb082c0d35 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 09:51:17 +0100 Subject: [PATCH 06/25] feat(ci): e2e check fix --- .github/workflows/devnet-e2e-test.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/devnet-e2e-test.yml b/.github/workflows/devnet-e2e-test.yml index a8716e44..a8e31208 100644 --- a/.github/workflows/devnet-e2e-test.yml +++ b/.github/workflows/devnet-e2e-test.yml @@ -95,20 +95,23 @@ jobs: # Step 0: Deploy L1 Devnet echo "Step 0: Deploy L1 Devnet" - L1_DEPLOY_SCRIPT="../surge-ethereum-package/deploy-surge-devnet-l1.sh" + L1_PACKAGE_DIR="../surge-ethereum-package" - if [ -f "$L1_DEPLOY_SCRIPT" ]; then + if [ -d "$L1_PACKAGE_DIR" ]; then print_info "Running L1 deployment from surge-ethereum-package" - if "$L1_DEPLOY_SCRIPT" --environment local --mode silence; then + cd "$L1_PACKAGE_DIR" + if ./deploy-surge-devnet-l1.sh --environment local --mode silence; then + cd - print_success "L1 deployment completed" else + cd - print_error "L1 deployment failed" exit 1 fi else - print_error "L1 deployment script not found at $L1_DEPLOY_SCRIPT" + print_error "surge-ethereum-package directory not found at $L1_PACKAGE_DIR" print_info "Current directory: $(pwd)" - print_info "Looking for: $L1_DEPLOY_SCRIPT" + print_info "Looking for: $L1_PACKAGE_DIR" ls -la ../ exit 1 fi @@ -179,8 +182,7 @@ jobs: - name: Cleanup - Stop L1 devnet if: always() run: | - ../surge-ethereum-package/remove-surge-devnet-l1.sh --force || true - working-directory: simple-surge-node + cd surge-ethereum-package && ./remove-surge-devnet-l1.sh --force || true - name: Cleanup - Kurtosis if: always() @@ -212,6 +214,7 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, title: 'Nightly Devnet E2E Test Failed', - body: `The nightly devnet E2E test failed on ${new Date().toISOString()}\n\nWorkflow run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, + body: `The nightly devnet E2E test failed on ${new Date().toISOString()}\n\nWorkflow run: ${context.serverUrl}/${context.repo.o +wner}/${context.repo.repo}/actions/runs/${context.runId}`, labels: ['bug', 'devnet', 'e2e-test', 'automated'] }) From e20faeeeb33dac770166f3de0dff76ee9eec223f Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 10:05:35 +0100 Subject: [PATCH 07/25] linting issue --- .github/workflows/devnet-e2e-test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/devnet-e2e-test.yml b/.github/workflows/devnet-e2e-test.yml index a8e31208..bd0a98e2 100644 --- a/.github/workflows/devnet-e2e-test.yml +++ b/.github/workflows/devnet-e2e-test.yml @@ -214,7 +214,6 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, title: 'Nightly Devnet E2E Test Failed', - body: `The nightly devnet E2E test failed on ${new Date().toISOString()}\n\nWorkflow run: ${context.serverUrl}/${context.repo.o -wner}/${context.repo.repo}/actions/runs/${context.runId}`, + body: 'The nightly devnet E2E test failed on ' + new Date().toISOString() + '\n\nWorkflow run: ' + context.serverUrl + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, labels: ['bug', 'devnet', 'e2e-test', 'automated'] }) From 12b394683228c7846b85a2415678bfb2d4b1b76f Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 10:09:41 +0100 Subject: [PATCH 08/25] remove cleanup --- .github/workflows/devnet-e2e-test.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/devnet-e2e-test.yml b/.github/workflows/devnet-e2e-test.yml index bd0a98e2..30e7094f 100644 --- a/.github/workflows/devnet-e2e-test.yml +++ b/.github/workflows/devnet-e2e-test.yml @@ -24,15 +24,6 @@ jobs: timeout-minutes: 60 steps: - - name: Maximize build space - uses: easimon/maximize-build-space@master - with: - root-reserve-mb: 30720 - remove-dotnet: 'true' - remove-android: 'true' - remove-haskell: 'true' - remove-codeql: 'true' - - name: Checkout simple-surge-node uses: actions/checkout@v4 with: From 885d01ccf7a7b5b29ec175b2af3589726a74a1ab Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 10:16:00 +0100 Subject: [PATCH 09/25] no cleanup --- .github/workflows/devnet-e2e-test.yml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/.github/workflows/devnet-e2e-test.yml b/.github/workflows/devnet-e2e-test.yml index 30e7094f..dc948c8d 100644 --- a/.github/workflows/devnet-e2e-test.yml +++ b/.github/workflows/devnet-e2e-test.yml @@ -164,26 +164,6 @@ jobs: echo "Kurtosis Services (surge-devnet)" kurtosis enclave inspect surge-devnet || true - - name: Cleanup - Stop L2 services - if: always() - working-directory: simple-surge-node - run: | - ./surge-remover.sh --devnet-non-interactive || true - - - name: Cleanup - Stop L1 devnet - if: always() - run: | - cd surge-ethereum-package && ./remove-surge-devnet-l1.sh --force || true - - - name: Cleanup - Kurtosis - if: always() - run: | - kurtosis clean -a || true - - - name: Cleanup - Docker - if: always() - run: | - docker system prune -af --volumes || true - name: Upload test artifacts if: failure() From 2720c2db72201dfb277808748ba21566fb9e3d8b Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 10:34:28 +0100 Subject: [PATCH 10/25] skip removal on start --- script/devnet-e2e-provision-check.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/script/devnet-e2e-provision-check.sh b/script/devnet-e2e-provision-check.sh index 127ad8b7..f24d9dd9 100755 --- a/script/devnet-e2e-provision-check.sh +++ b/script/devnet-e2e-provision-check.sh @@ -30,17 +30,17 @@ print_info() { cd "$(dirname "$0")/.." # Step 1: Clean up any existing deployment -echo "==========================================" -echo "Step 1: Cleanup existing deployment" -echo "==========================================" -print_info "Running surge-remover.sh --devnet-non-interactive" -if ./surge-remover.sh --devnet-non-interactive; then - print_success "Cleanup completed" -else - print_error "Cleanup failed" - exit 1 -fi -echo +#echo "==========================================" +#echo "Step 1: Cleanup existing deployment" +#echo "==========================================" +#print_info "Running surge-remover.sh --devnet-non-interactive" +#if ./surge-remover.sh --devnet-non-interactive; then +# print_success "Cleanup completed" +#else +# print_error "Cleanup failed" +# exit 1 +#fi +#echo # Step 2: Ensure .env file exists echo "==========================================" From 726497b26fc19dcdeca185338affc17fd5579f22 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 11:33:47 +0100 Subject: [PATCH 11/25] remove websocket health check --- script/devnet-e2e-provision-check.sh | 9 --------- 1 file changed, 9 deletions(-) diff --git a/script/devnet-e2e-provision-check.sh b/script/devnet-e2e-provision-check.sh index f24d9dd9..7b554369 100755 --- a/script/devnet-e2e-provision-check.sh +++ b/script/devnet-e2e-provision-check.sh @@ -146,15 +146,6 @@ else exit 1 fi -print_info "Testing L2 WebSocket endpoint at ws://localhost:8548" -if curl -f http://localhost:8548 -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then - echo - print_success "L2 WebSocket endpoint is responding" -else - echo - print_error "L2 WebSocket endpoint health check failed" - exit 1 -fi echo # Step 8: Optional - Check container logs for errors From b824122ab2d9d6b47b0ceb072675069fe39011d7 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 14:34:31 +0100 Subject: [PATCH 12/25] rename CI action --- ...2e-test.yml => devnet-test-no-provers.yml} | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) rename .github/workflows/{devnet-e2e-test.yml => devnet-test-no-provers.yml} (79%) diff --git a/.github/workflows/devnet-e2e-test.yml b/.github/workflows/devnet-test-no-provers.yml similarity index 79% rename from .github/workflows/devnet-e2e-test.yml rename to .github/workflows/devnet-test-no-provers.yml index dc948c8d..cbdba6c1 100644 --- a/.github/workflows/devnet-e2e-test.yml +++ b/.github/workflows/devnet-test-no-provers.yml @@ -1,4 +1,4 @@ -name: Devnet E2E Test +name: Devnet Test (No Provers) on: schedule: @@ -11,17 +11,17 @@ on: - 'docker-compose*.yml' - 'surge-*.sh' - 'script/devnet-e2e-provision-check.sh' - - '.github/workflows/devnet-e2e-test.yml' + - '.github/workflows/devnet-test-no-provers.yml' env: SURGE_ETHEREUM_PACKAGE_REPO: 'NethermindEth/surge-ethereum-package' SURGE_ETHEREUM_PACKAGE_REF: 'main' jobs: - devnet-e2e-test: - name: Full Devnet E2E Test + devnet-test-no-provers: + name: Devnet Test (No Provers) runs-on: ubuntu-22.04 - timeout-minutes: 60 + timeout-minutes: 45 steps: - name: Checkout simple-surge-node @@ -57,7 +57,7 @@ jobs: docker compose version docker info - - name: Update e2e script with L1 deployment paths + - name: Update provision check script with L1 deployment paths working-directory: simple-surge-node run: | # Create a wrapper script that handles L1 deployment @@ -66,7 +66,7 @@ jobs: set -e - echo "Starting CI Devnet E2E Health Check" + echo "Starting CI Devnet Provision Health Check" echo print_success() { @@ -136,14 +136,26 @@ jobs: done echo - # Run the actual e2e provision check - echo "Running E2E Provision Check" + # Step 0.6: Disable provers for faster CI testing + echo "Step 0.6: Configure environment for no-prover testing" + print_info "Disabling provers in .env.devnet" + if [ -f ".env.devnet" ]; then + sed -i 's/^ENABLE_PROVER=true/ENABLE_PROVER=false/' .env.devnet + print_success "Provers disabled" + else + print_error ".env.devnet not found" + exit 1 + fi + echo + + # Run the actual provision check + echo "Running Devnet Provision Check" ./script/devnet-e2e-provision-check.sh EOF chmod +x script/devnet-e2e-provision-check-ci.sh - - name: Run E2E Devnet Test + - name: Run Devnet Test (No Provers) working-directory: simple-surge-node run: | ./script/devnet-e2e-provision-check-ci.sh @@ -169,7 +181,7 @@ jobs: if: failure() uses: actions/upload-artifact@v4 with: - name: devnet-e2e-logs + name: devnet-test-no-provers-logs path: | simple-surge-node/deployment/*.json simple-surge-node/*.log @@ -184,7 +196,7 @@ jobs: github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, - title: 'Nightly Devnet E2E Test Failed', - body: 'The nightly devnet E2E test failed on ' + new Date().toISOString() + '\n\nWorkflow run: ' + context.serverUrl + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, - labels: ['bug', 'devnet', 'e2e-test', 'automated'] - }) + title: 'Nightly Devnet Test (No Provers) Failed', + body: 'The nightly devnet test (no provers) failed on ' + new Date().toISOString() + '\n\nWorkflow run: ' + context.serverUrl +'/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, + labels: ['bug', 'devnet', 'test-no-provers', 'automated'] + }) \ No newline at end of file From 82b9ddda89ff5237bcfc0732ffe7386f978db293 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 15:32:16 +0100 Subject: [PATCH 13/25] refactor --- .github/workflows/devnet-test-no-provers.yml | 125 +----- script/devnet-e2e-provision-check.sh | 409 +++++++++++-------- script/devnet-provision-check-ci.sh | 48 +++ script/util/common.sh | 88 ++++ 4 files changed, 386 insertions(+), 284 deletions(-) create mode 100755 script/devnet-provision-check-ci.sh create mode 100755 script/util/common.sh diff --git a/.github/workflows/devnet-test-no-provers.yml b/.github/workflows/devnet-test-no-provers.yml index cbdba6c1..9ae0e3a0 100644 --- a/.github/workflows/devnet-test-no-provers.yml +++ b/.github/workflows/devnet-test-no-provers.yml @@ -1,4 +1,4 @@ -name: Devnet Test (No Provers) +name: Devnet Provision Check (No Provers) on: schedule: @@ -11,6 +11,8 @@ on: - 'docker-compose*.yml' - 'surge-*.sh' - 'script/devnet-e2e-provision-check.sh' + - 'script/devnet-provision-check-ci.sh' + - 'script/util/common.sh' - '.github/workflows/devnet-test-no-provers.yml' env: @@ -18,8 +20,8 @@ env: SURGE_ETHEREUM_PACKAGE_REF: 'main' jobs: - devnet-test-no-provers: - name: Devnet Test (No Provers) + devnet-provision-check-no-provers: + name: Devnet Provision Check (No Provers) runs-on: ubuntu-22.04 timeout-minutes: 45 @@ -57,108 +59,17 @@ jobs: docker compose version docker info - - name: Update provision check script with L1 deployment paths + - name: Run Devnet Provision Check (No Provers) working-directory: simple-surge-node + env: + L1_PACKAGE_DIR: ../surge-ethereum-package + L1_ENVIRONMENT: local + L1_MODE: silence + L1_RPC_URL: http://localhost:32003 + L1_STABILIZE_WAIT: 20 + ENABLE_PROVER: false run: | - # Create a wrapper script that handles L1 deployment - cat > script/devnet-e2e-provision-check-ci.sh << 'EOF' - #!/bin/bash - - set -e - - echo "Starting CI Devnet Provision Health Check" - echo - - print_success() { - echo "[SUCCESS] $1" - } - - print_error() { - echo "[ERROR] $1" - } - - print_info() { - echo "[INFO] $1" - } - - # Navigate to project root - cd "$(dirname "$0")/.." - - # Step 0: Deploy L1 Devnet - echo "Step 0: Deploy L1 Devnet" - L1_PACKAGE_DIR="../surge-ethereum-package" - - if [ -d "$L1_PACKAGE_DIR" ]; then - print_info "Running L1 deployment from surge-ethereum-package" - cd "$L1_PACKAGE_DIR" - if ./deploy-surge-devnet-l1.sh --environment local --mode silence; then - cd - - print_success "L1 deployment completed" - else - cd - - print_error "L1 deployment failed" - exit 1 - fi - else - print_error "surge-ethereum-package directory not found at $L1_PACKAGE_DIR" - print_info "Current directory: $(pwd)" - print_info "Looking for: $L1_PACKAGE_DIR" - ls -la ../ - exit 1 - fi - echo - - # Step 0.5: Wait for L1 to be ready - echo "Step 0.5: Verify L1 is ready" - print_info "Waiting 20 seconds for L1 to stabilize..." - sleep 20 - - print_info "Testing L1 RPC endpoint at http://localhost:32003" - max_retries=10 - retry_count=0 - - while [ $retry_count -lt $max_retries ]; do - if curl -f http://localhost:32003 -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then - echo - print_success "L1 RPC is responding" - break - else - retry_count=$((retry_count + 1)) - if [ $retry_count -eq $max_retries ]; then - echo - print_error "L1 RPC failed to respond after $max_retries retries" - exit 1 - fi - print_info "Retry $retry_count/$max_retries - waiting 10s..." - sleep 10 - fi - done - echo - - # Step 0.6: Disable provers for faster CI testing - echo "Step 0.6: Configure environment for no-prover testing" - print_info "Disabling provers in .env.devnet" - if [ -f ".env.devnet" ]; then - sed -i 's/^ENABLE_PROVER=true/ENABLE_PROVER=false/' .env.devnet - print_success "Provers disabled" - else - print_error ".env.devnet not found" - exit 1 - fi - echo - - # Run the actual provision check - echo "Running Devnet Provision Check" - ./script/devnet-e2e-provision-check.sh - EOF - - chmod +x script/devnet-e2e-provision-check-ci.sh - - - name: Run Devnet Test (No Provers) - working-directory: simple-surge-node - run: | - ./script/devnet-e2e-provision-check-ci.sh + ./script/devnet-provision-check-ci.sh - name: Collect Docker logs on failure if: failure() @@ -181,7 +92,7 @@ jobs: if: failure() uses: actions/upload-artifact@v4 with: - name: devnet-test-no-provers-logs + name: devnet-provision-check-no-provers-logs path: | simple-surge-node/deployment/*.json simple-surge-node/*.log @@ -196,7 +107,7 @@ jobs: github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, - title: 'Nightly Devnet Test (No Provers) Failed', - body: 'The nightly devnet test (no provers) failed on ' + new Date().toISOString() + '\n\nWorkflow run: ' + context.serverUrl +'/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, - labels: ['bug', 'devnet', 'test-no-provers', 'automated'] + title: 'Nightly Devnet Provision Check (No Provers) Failed', + body: 'The nightly devnet provision check (no provers) failed on ' + new Date().toISOString() + '\n\nWorkflow run: ' + context.serverUrl +'/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, + labels: ['bug', 'devnet', 'provision-check', 'automated'] }) \ No newline at end of file diff --git a/script/devnet-e2e-provision-check.sh b/script/devnet-e2e-provision-check.sh index 7b554369..aea90438 100755 --- a/script/devnet-e2e-provision-check.sh +++ b/script/devnet-e2e-provision-check.sh @@ -1,177 +1,232 @@ -#!/bin/bash - -set -e - -echo "==========================================" -echo "Starting Local Devnet Health Check" -echo "==========================================" -echo - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Function to print colored output -print_success() { - echo -e "${GREEN}✓ $1${NC}" -} - -print_error() { - echo -e "${RED}✗ $1${NC}" -} - -print_info() { - echo -e "${YELLOW}ℹ $1${NC}" -} - -# Ensure we're in the project root -cd "$(dirname "$0")/.." - -# Step 1: Clean up any existing deployment -#echo "==========================================" -#echo "Step 1: Cleanup existing deployment" -#echo "==========================================" -#print_info "Running surge-remover.sh --devnet-non-interactive" -#if ./surge-remover.sh --devnet-non-interactive; then -# print_success "Cleanup completed" -#else -# print_error "Cleanup failed" -# exit 1 -#fi -#echo - -# Step 2: Ensure .env file exists -echo "==========================================" -echo "Step 2: Prepare environment" -echo "==========================================" -if [ ! -f .env ]; then - print_info "Copying .env.devnet to .env" - cp .env.devnet .env - print_success ".env file created" -else - print_info ".env file already exists" -fi -echo - -# Step 3: Deploy protocol -echo "==========================================" -echo "Step 3: Deploy protocol (L1 contracts)" -echo "==========================================" -print_info "Running surge-protocol-deployer.sh --devnet-non-interactive" -if ./surge-protocol-deployer.sh --devnet-non-interactive; then - print_success "Protocol deployment completed" -else - print_error "Protocol deployment failed" - exit 1 -fi -echo - -# Step 4: Verify protocol deployment artifacts -echo "==========================================" -echo "Step 4: Verify protocol deployment" -echo "==========================================" -if [ ! -f "deployment/deploy_l1.json" ]; then - print_error "deploy_l1.json not found" - exit 1 -else - print_success "deploy_l1.json found" -fi - -if [ ! -f "deployment/proposer_wrappers.json" ]; then - print_error "proposer_wrappers.json not found" - exit 1 -else - print_success "proposer_wrappers.json found" -fi -echo - -# Step 5: Deploy stack -echo "==========================================" -echo "Step 5: Deploy L2 stack" -echo "==========================================" -print_info "Running surge-stack-deployer.sh --devnet-non-interactive" -if ./surge-stack-deployer.sh --devnet-non-interactive; then - print_success "Stack deployment completed" -else - print_error "Stack deployment failed" - exit 1 -fi -echo - -# Step 6: Verify services are running -echo "==========================================" -echo "Step 6: Verify services" -echo "==========================================" -print_info "Checking running containers" -docker compose ps -echo - -print_info "Checking critical containers are healthy..." -# Check L2 execution client container -if docker compose ps | grep "l2-nethermind-execution-client" | grep -q "(healthy)"; then - print_success "L2 execution client container is healthy" -else - print_error "L2 execution client container is not healthy" - exit 1 -fi - -# Check other critical containers are running -CRITICAL_CONTAINERS=("l2-taiko-consensus-client" "l2-taiko-proposer-client" "relayer-l1-indexer" "relayer-l2-indexer") -for container in "${CRITICAL_CONTAINERS[@]}"; do - if docker compose ps | grep "$container" | grep -q "Up"; then - print_success "$container is running" - else - print_error "$container is not running" - exit 1 - fi -done -echo - -# Step 7: Health check L2 RPC endpoints -echo "==========================================" -echo "Step 7: Health check L2 RPC endpoints" -echo "==========================================" -print_info "Waiting 30 seconds for services to stabilize..." -sleep 30 - -print_info "Testing L2 RPC endpoint at http://localhost:8547" -if curl -f http://localhost:8547 -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then - echo - print_success "L2 execution client RPC is responding" -else - echo - print_error "L2 execution client RPC health check failed" - exit 1 -fi - -echo - -# Step 8: Optional - Check container logs for errors -echo "==========================================" -echo "Step 8: Check for errors in logs" -echo "==========================================" -print_info "Checking for errors in container logs (last 50 lines)" -if docker compose logs --tail=50 | grep -i "error\|fatal\|panic" | grep -v "error_code" | head -20; then - print_info "Found some errors in logs (review above)" -else - print_success "No critical errors found in recent logs" -fi -echo - -# Final summary -echo "==========================================" -echo "Health Check Summary" -echo "==========================================" -print_success "All health checks passed!" -echo -print_info "Services are running. You can now:" -echo " - Access L2 RPC: http://localhost:8547" -echo " - Access L2 Blockscout: http://localhost:3000" -echo " - Access L1 RPC: http://localhost:32003" -echo " - View logs: docker compose logs -f" -echo -print_info "To clean up when done:" -echo " ./surge-remover.sh --devnet-non-interactive" -echo +name: Devnet E2E Test (No Provers) + +on: + schedule: + # Run nightly at 2 AM UTC + - cron: '0 2 * * *' + workflow_dispatch: + # Allow manual trigger + pull_request: + paths: + - 'docker-compose*.yml' + - 'surge-*.sh' + - 'script/devnet-e2e-provision-check.sh' + - '.github/workflows/devnet-e2e-test.yml' + +env: + SURGE_ETHEREUM_PACKAGE_REPO: 'NethermindEth/surge-ethereum-package' + SURGE_ETHEREUM_PACKAGE_REF: 'main' + +jobs: + devnet-e2e-test: + name: Devnet E2E Test (No Provers) + runs-on: ubuntu-22.04 + timeout-minutes: 45 + + steps: + - name: Maximize build space + uses: easimon/maximize-build-space@master + with: + root-reserve-mb: 30720 + remove-dotnet: 'true' + remove-android: 'true' + remove-haskell: 'true' + remove-codeql: 'true' + + - name: Checkout simple-surge-node + uses: actions/checkout@v4 + with: + path: simple-surge-node + + - name: Checkout surge-ethereum-package + uses: actions/checkout@v4 + with: + repository: ${{ env.SURGE_ETHEREUM_PACKAGE_REPO }} + ref: ${{ env.SURGE_ETHEREUM_PACKAGE_REF }} + path: surge-ethereum-package + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y curl jq + + - name: Install Kurtosis CLI + run: | + echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list + sudo apt-get update + sudo apt-get install -y kurtosis-cli + kurtosis version + + - name: Verify Docker installation + run: | + docker --version + docker compose version + docker info + + - name: Update e2e script with L1 deployment paths + working-directory: simple-surge-node + run: | + # Create a wrapper script that handles L1 deployment + cat > script/devnet-e2e-provision-check-ci.sh << 'EOF' + #!/bin/bash + + set -e + + echo "Starting CI Devnet E2E Health Check" + echo + + print_success() { + echo "[SUCCESS] $1" + } + + print_error() { + echo "[ERROR] $1" + } + + print_info() { + echo "[INFO] $1" + } + + # Navigate to project root + cd "$(dirname "$0")/.." + + # Step 0: Deploy L1 Devnet + echo "Step 0: Deploy L1 Devnet" + L1_PACKAGE_DIR="../surge-ethereum-package" + + if [ -d "$L1_PACKAGE_DIR" ]; then + print_info "Running L1 deployment from surge-ethereum-package" + cd "$L1_PACKAGE_DIR" + if ./deploy-surge-devnet-l1.sh --environment local --mode silence; then + cd - + print_success "L1 deployment completed" + else + cd - + print_error "L1 deployment failed" + exit 1 + fi + else + print_error "surge-ethereum-package directory not found at $L1_PACKAGE_DIR" + print_info "Current directory: $(pwd)" + print_info "Looking for: $L1_PACKAGE_DIR" + ls -la ../ + exit 1 + fi + echo + + # Step 0.5: Wait for L1 to be ready + echo "Step 0.5: Verify L1 is ready" + print_info "Waiting 20 seconds for L1 to stabilize..." + sleep 20 + + print_info "Testing L1 RPC endpoint at http://localhost:32003" + max_retries=10 + retry_count=0 + + while [ $retry_count -lt $max_retries ]; do + if curl -f http://localhost:32003 -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then + echo + print_success "L1 RPC is responding" + break + else + retry_count=$((retry_count + 1)) + if [ $retry_count -eq $max_retries ]; then + echo + print_error "L1 RPC failed to respond after $max_retries retries" + exit 1 + fi + print_info "Retry $retry_count/$max_retries - waiting 10s..." + sleep 10 + fi + done + echo + + # Step 0.6: Disable provers for faster CI testing + echo "Step 0.6: Configure environment for no-prover testing" + print_info "Disabling provers in .env.devnet" + if [ -f ".env.devnet" ]; then + sed -i 's/^ENABLE_PROVER=true/ENABLE_PROVER=false/' .env.devnet + print_success "Provers disabled" + else + print_error ".env.devnet not found" + exit 1 + fi + echo + + # Run the actual e2e provision check + echo "Running E2E Provision Check" + ./script/devnet-e2e-provision-check.sh + EOF + + chmod +x script/devnet-e2e-provision-check-ci.sh + + - name: Run E2E Devnet Test + working-directory: simple-surge-node + run: | + ./script/devnet-e2e-provision-check-ci.sh + + - name: Collect Docker logs on failure + if: failure() + working-directory: simple-surge-node + run: | + echo "Docker Compose Services Status" + docker compose ps || true + + echo "Docker Compose Logs (last 100 lines)" + docker compose logs --tail=100 || true + + echo "Kurtosis Enclaves" + kurtosis enclave ls || true + + echo "Kurtosis Services (surge-devnet)" + kurtosis enclave inspect surge-devnet || true + + - name: Cleanup - Stop L2 services + if: always() + working-directory: simple-surge-node + run: | + ./surge-remover.sh --devnet-non-interactive || true + + - name: Cleanup - Stop L1 devnet + if: always() + run: | + cd surge-ethereum-package && ./remove-surge-devnet-l1.sh --force || true + + - name: Cleanup - Kurtosis + if: always() + run: | + kurtosis clean -a || true + + - name: Cleanup - Docker + if: always() + run: | + docker system prune -af --volumes || true + + - name: Upload test artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: devnet-e2e-logs + path: | + simple-surge-node/deployment/*.json + simple-surge-node/*.log + retention-days: 7 + if-no-files-found: ignore + + - name: Notify on failure + if: failure() && github.event_name == 'schedule' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Nightly Devnet E2E Test (No Provers) Failed', + body: 'The nightly devnet E2E test (no provers) failed on ' + new Date().toISOString() + '\n\nWorkflow run: ' + context.serverUr +l + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, + labels: ['bug', 'devnet', 'e2e-test', 'automated'] + }) \ No newline at end of file diff --git a/script/devnet-provision-check-ci.sh b/script/devnet-provision-check-ci.sh new file mode 100755 index 00000000..bd567cd1 --- /dev/null +++ b/script/devnet-provision-check-ci.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# Source common utilities +source "$SCRIPT_DIR/util/common.sh" + +# Configuration with defaults +L1_PACKAGE_DIR="${L1_PACKAGE_DIR:-../surge-ethereum-package}" +L1_ENVIRONMENT="${L1_ENVIRONMENT:-local}" +L1_MODE="${L1_MODE:-silence}" +L1_RPC_URL="${L1_RPC_URL:-http://localhost:32003}" +L1_STABILIZE_WAIT="${L1_STABILIZE_WAIT:-20}" +ENABLE_PROVER="${ENABLE_PROVER:-false}" +ENV_FILE="${ENV_FILE:-.env.devnet}" + +echo "Starting CI Devnet Provision Check (No Provers)" +echo + +# Navigate to project root +cd "$PROJECT_ROOT" + +# Step 0: Deploy L1 Devnet +echo "Step 0: Deploy L1 Devnet" +deploy_l1 "$L1_PACKAGE_DIR" "$L1_ENVIRONMENT" "$L1_MODE" +echo + +# Step 0.5: Wait for L1 to be ready +echo "Step 0.5: Verify L1 is ready" +print_info "Waiting ${L1_STABILIZE_WAIT} seconds for L1 to stabilize..." +sleep "$L1_STABILIZE_WAIT" + +wait_for_rpc "$L1_RPC_URL" +echo + +# Step 0.6: Configure environment for no-prover testing +if [ "$ENABLE_PROVER" = "false" ]; then + echo "Step 0.6: Configure environment for no-prover testing" + configure_env_no_provers "$ENV_FILE" + echo +fi + +# Run the actual provision check +echo "Running Devnet Provision Check" +"$SCRIPT_DIR/devnet-e2e-provision-check.sh" diff --git a/script/util/common.sh b/script/util/common.sh new file mode 100755 index 00000000..a1c86569 --- /dev/null +++ b/script/util/common.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# Common utility functions for Surge devnet scripts + +set -o pipefail + +print_success() { + echo "[SUCCESS] $1" +} + +print_error() { + echo "[ERROR] $1" +} + +print_info() { + echo "[INFO] $1" +} + +wait_for_rpc() { + local rpc_url="$1" + local max_retries="${2:-10}" + local retry_delay="${3:-10}" + + print_info "Testing RPC endpoint at $rpc_url" + local retry_count=0 + + while [ $retry_count -lt $max_retries ]; do + if curl -f "$rpc_url" -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then + echo + print_success "RPC is responding" + return 0 + else + retry_count=$((retry_count + 1)) + if [ $retry_count -eq $max_retries ]; then + echo + print_error "RPC failed to respond after $max_retries retries" + return 1 + fi + print_info "Retry $retry_count/$max_retries - waiting ${retry_delay}s..." + sleep "$retry_delay" + fi + done +} + +deploy_l1() { + local l1_package_dir="${1:-../surge-ethereum-package}" + local environment="${2:-local}" + local mode="${3:-silence}" + + echo "Deploying L1 Devnet" + + if [ ! -d "$l1_package_dir" ]; then + print_error "surge-ethereum-package directory not found at $l1_package_dir" + print_info "Current directory: $(pwd)" + ls -la ../ + return 1 + fi + + print_info "Running L1 deployment from $l1_package_dir" + pushd "$l1_package_dir" > /dev/null + + if ./deploy-surge-devnet-l1.sh --environment "$environment" --mode "$mode"; then + popd > /dev/null + print_success "L1 deployment completed" + return 0 + else + popd > /dev/null + print_error "L1 deployment failed" + return 1 + fi +} + +configure_env_no_provers() { + local env_file="${1:-.env.devnet}" + + echo "Configuring environment for no-prover testing" + print_info "Disabling provers in $env_file" + + if [ ! -f "$env_file" ]; then + print_error "$env_file not found" + return 1 + fi + + sed -i 's/^ENABLE_PROVER=true/ENABLE_PROVER=false/' "$env_file" + print_success "Provers disabled" + return 0 +} From 409a233946a562063874d963cc001e841f5e2ece Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 15:33:31 +0100 Subject: [PATCH 14/25] cleanup --- script/devnet-e2e-provision-check.sh | 232 --------------------------- 1 file changed, 232 deletions(-) delete mode 100755 script/devnet-e2e-provision-check.sh diff --git a/script/devnet-e2e-provision-check.sh b/script/devnet-e2e-provision-check.sh deleted file mode 100755 index aea90438..00000000 --- a/script/devnet-e2e-provision-check.sh +++ /dev/null @@ -1,232 +0,0 @@ -name: Devnet E2E Test (No Provers) - -on: - schedule: - # Run nightly at 2 AM UTC - - cron: '0 2 * * *' - workflow_dispatch: - # Allow manual trigger - pull_request: - paths: - - 'docker-compose*.yml' - - 'surge-*.sh' - - 'script/devnet-e2e-provision-check.sh' - - '.github/workflows/devnet-e2e-test.yml' - -env: - SURGE_ETHEREUM_PACKAGE_REPO: 'NethermindEth/surge-ethereum-package' - SURGE_ETHEREUM_PACKAGE_REF: 'main' - -jobs: - devnet-e2e-test: - name: Devnet E2E Test (No Provers) - runs-on: ubuntu-22.04 - timeout-minutes: 45 - - steps: - - name: Maximize build space - uses: easimon/maximize-build-space@master - with: - root-reserve-mb: 30720 - remove-dotnet: 'true' - remove-android: 'true' - remove-haskell: 'true' - remove-codeql: 'true' - - - name: Checkout simple-surge-node - uses: actions/checkout@v4 - with: - path: simple-surge-node - - - name: Checkout surge-ethereum-package - uses: actions/checkout@v4 - with: - repository: ${{ env.SURGE_ETHEREUM_PACKAGE_REPO }} - ref: ${{ env.SURGE_ETHEREUM_PACKAGE_REF }} - path: surge-ethereum-package - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y curl jq - - - name: Install Kurtosis CLI - run: | - echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list - sudo apt-get update - sudo apt-get install -y kurtosis-cli - kurtosis version - - - name: Verify Docker installation - run: | - docker --version - docker compose version - docker info - - - name: Update e2e script with L1 deployment paths - working-directory: simple-surge-node - run: | - # Create a wrapper script that handles L1 deployment - cat > script/devnet-e2e-provision-check-ci.sh << 'EOF' - #!/bin/bash - - set -e - - echo "Starting CI Devnet E2E Health Check" - echo - - print_success() { - echo "[SUCCESS] $1" - } - - print_error() { - echo "[ERROR] $1" - } - - print_info() { - echo "[INFO] $1" - } - - # Navigate to project root - cd "$(dirname "$0")/.." - - # Step 0: Deploy L1 Devnet - echo "Step 0: Deploy L1 Devnet" - L1_PACKAGE_DIR="../surge-ethereum-package" - - if [ -d "$L1_PACKAGE_DIR" ]; then - print_info "Running L1 deployment from surge-ethereum-package" - cd "$L1_PACKAGE_DIR" - if ./deploy-surge-devnet-l1.sh --environment local --mode silence; then - cd - - print_success "L1 deployment completed" - else - cd - - print_error "L1 deployment failed" - exit 1 - fi - else - print_error "surge-ethereum-package directory not found at $L1_PACKAGE_DIR" - print_info "Current directory: $(pwd)" - print_info "Looking for: $L1_PACKAGE_DIR" - ls -la ../ - exit 1 - fi - echo - - # Step 0.5: Wait for L1 to be ready - echo "Step 0.5: Verify L1 is ready" - print_info "Waiting 20 seconds for L1 to stabilize..." - sleep 20 - - print_info "Testing L1 RPC endpoint at http://localhost:32003" - max_retries=10 - retry_count=0 - - while [ $retry_count -lt $max_retries ]; do - if curl -f http://localhost:32003 -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then - echo - print_success "L1 RPC is responding" - break - else - retry_count=$((retry_count + 1)) - if [ $retry_count -eq $max_retries ]; then - echo - print_error "L1 RPC failed to respond after $max_retries retries" - exit 1 - fi - print_info "Retry $retry_count/$max_retries - waiting 10s..." - sleep 10 - fi - done - echo - - # Step 0.6: Disable provers for faster CI testing - echo "Step 0.6: Configure environment for no-prover testing" - print_info "Disabling provers in .env.devnet" - if [ -f ".env.devnet" ]; then - sed -i 's/^ENABLE_PROVER=true/ENABLE_PROVER=false/' .env.devnet - print_success "Provers disabled" - else - print_error ".env.devnet not found" - exit 1 - fi - echo - - # Run the actual e2e provision check - echo "Running E2E Provision Check" - ./script/devnet-e2e-provision-check.sh - EOF - - chmod +x script/devnet-e2e-provision-check-ci.sh - - - name: Run E2E Devnet Test - working-directory: simple-surge-node - run: | - ./script/devnet-e2e-provision-check-ci.sh - - - name: Collect Docker logs on failure - if: failure() - working-directory: simple-surge-node - run: | - echo "Docker Compose Services Status" - docker compose ps || true - - echo "Docker Compose Logs (last 100 lines)" - docker compose logs --tail=100 || true - - echo "Kurtosis Enclaves" - kurtosis enclave ls || true - - echo "Kurtosis Services (surge-devnet)" - kurtosis enclave inspect surge-devnet || true - - - name: Cleanup - Stop L2 services - if: always() - working-directory: simple-surge-node - run: | - ./surge-remover.sh --devnet-non-interactive || true - - - name: Cleanup - Stop L1 devnet - if: always() - run: | - cd surge-ethereum-package && ./remove-surge-devnet-l1.sh --force || true - - - name: Cleanup - Kurtosis - if: always() - run: | - kurtosis clean -a || true - - - name: Cleanup - Docker - if: always() - run: | - docker system prune -af --volumes || true - - - name: Upload test artifacts - if: failure() - uses: actions/upload-artifact@v4 - with: - name: devnet-e2e-logs - path: | - simple-surge-node/deployment/*.json - simple-surge-node/*.log - retention-days: 7 - if-no-files-found: ignore - - - name: Notify on failure - if: failure() && github.event_name == 'schedule' - uses: actions/github-script@v7 - with: - script: | - github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: 'Nightly Devnet E2E Test (No Provers) Failed', - body: 'The nightly devnet E2E test (no provers) failed on ' + new Date().toISOString() + '\n\nWorkflow run: ' + context.serverUr -l + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId, - labels: ['bug', 'devnet', 'e2e-test', 'automated'] - }) \ No newline at end of file From c9e571ff44cea13d2c6046577815a9bf8218a683 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 17:35:48 +0100 Subject: [PATCH 15/25] rename steps --- .github/workflows/devnet-test-no-provers.yml | 2 +- script/devnet-provision-check-ci.sh | 26 ++- script/devnet-provision-check.sh | 163 +++++++++++++++++++ 3 files changed, 176 insertions(+), 15 deletions(-) create mode 100755 script/devnet-provision-check.sh diff --git a/.github/workflows/devnet-test-no-provers.yml b/.github/workflows/devnet-test-no-provers.yml index 9ae0e3a0..7828c5f8 100644 --- a/.github/workflows/devnet-test-no-provers.yml +++ b/.github/workflows/devnet-test-no-provers.yml @@ -10,7 +10,7 @@ on: paths: - 'docker-compose*.yml' - 'surge-*.sh' - - 'script/devnet-e2e-provision-check.sh' + - 'script/devnet-provision-check.sh' - 'script/devnet-provision-check-ci.sh' - 'script/util/common.sh' - '.github/workflows/devnet-test-no-provers.yml' diff --git a/script/devnet-provision-check-ci.sh b/script/devnet-provision-check-ci.sh index bd567cd1..ae56e863 100755 --- a/script/devnet-provision-check-ci.sh +++ b/script/devnet-provision-check-ci.sh @@ -9,40 +9,38 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" source "$SCRIPT_DIR/util/common.sh" # Configuration with defaults -L1_PACKAGE_DIR="${L1_PACKAGE_DIR:-../surge-ethereum-package}" +L1_PACKAGE_DIR="${L1_PACKAGE_DIR:-$PROJECT_ROOT/../surge-ethereum-package}" L1_ENVIRONMENT="${L1_ENVIRONMENT:-local}" L1_MODE="${L1_MODE:-silence}" L1_RPC_URL="${L1_RPC_URL:-http://localhost:32003}" L1_STABILIZE_WAIT="${L1_STABILIZE_WAIT:-20}" ENABLE_PROVER="${ENABLE_PROVER:-false}" -ENV_FILE="${ENV_FILE:-.env.devnet}" +ENV_FILE="${ENV_FILE:-$PROJECT_ROOT/.env.devnet}" echo "Starting CI Devnet Provision Check (No Provers)" echo -# Navigate to project root -cd "$PROJECT_ROOT" - -# Step 0: Deploy L1 Devnet -echo "Step 0: Deploy L1 Devnet" +# Step 1: Deploy L1 Devnet +echo "Step 1: Deploy L1 Devnet" deploy_l1 "$L1_PACKAGE_DIR" "$L1_ENVIRONMENT" "$L1_MODE" echo -# Step 0.5: Wait for L1 to be ready -echo "Step 0.5: Verify L1 is ready" +# Step 2: Verify L1 is ready +echo "Step 2: Verify L1 is ready" print_info "Waiting ${L1_STABILIZE_WAIT} seconds for L1 to stabilize..." sleep "$L1_STABILIZE_WAIT" wait_for_rpc "$L1_RPC_URL" echo -# Step 0.6: Configure environment for no-prover testing +# Step 3: Configure environment for no-prover testing if [ "$ENABLE_PROVER" = "false" ]; then - echo "Step 0.6: Configure environment for no-prover testing" + echo "Step 3: Configure environment for no-prover testing" configure_env_no_provers "$ENV_FILE" echo fi -# Run the actual provision check -echo "Running Devnet Provision Check" -"$SCRIPT_DIR/devnet-e2e-provision-check.sh" +# Step 4: Run L2 Devnet Provision Check +echo "Step 4: Run L2 Devnet Provision Check" +cd "$PROJECT_ROOT" +"$SCRIPT_DIR/devnet-provision-check.sh" diff --git a/script/devnet-provision-check.sh b/script/devnet-provision-check.sh new file mode 100755 index 00000000..978eddce --- /dev/null +++ b/script/devnet-provision-check.sh @@ -0,0 +1,163 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# Source common utilities if available, otherwise define locally +if [ -f "$SCRIPT_DIR/util/common.sh" ]; then + source "$SCRIPT_DIR/util/common.sh" +else + print_success() { echo "[SUCCESS] $1"; } + print_error() { echo "[ERROR] $1"; } + print_info() { echo "[INFO] $1"; } +fi + +# Ensure we're in the project root +cd "$PROJECT_ROOT" + +echo "Starting Devnet Provision Check (No Provers)" +echo + +# Step 1: Clean up any existing deployment +echo "Step 1: Cleanup existing deployment" +print_info "Running surge-remover.sh --devnet-non-interactive" +if ./surge-remover.sh --devnet-non-interactive; then + print_success "Cleanup completed" +else + print_error "Cleanup failed" + exit 1 +fi +echo + +# Step 2: Prepare environment +echo "Step 2: Prepare environment" +if [ ! -f .env ]; then + print_info "Copying .env.devnet to .env" + cp .env.devnet .env + print_success ".env file created" +else + print_info ".env file already exists" +fi +echo + +# Step 3: Deploy protocol +echo "Step 3: Deploy protocol (L1 contracts)" +print_info "Running surge-protocol-deployer.sh --devnet-non-interactive" +if ./surge-protocol-deployer.sh --devnet-non-interactive; then + print_success "Protocol deployment completed" +else + print_error "Protocol deployment failed" + exit 1 +fi +echo + +# Step 4: Verify protocol deployment artifacts +echo "Step 4: Verify protocol deployment" +if [ ! -f "deployment/deploy_l1.json" ]; then + print_error "deploy_l1.json not found" + exit 1 +else + print_success "deploy_l1.json found" +fi + +if [ ! -f "deployment/proposer_wrappers.json" ]; then + print_error "proposer_wrappers.json not found" + exit 1 +else + print_success "proposer_wrappers.json found" +fi +echo + +# Step 5: Deploy stack +echo "Step 5: Deploy L2 stack" +print_info "Running surge-stack-deployer.sh --devnet-non-interactive" +if ./surge-stack-deployer.sh --devnet-non-interactive; then + print_success "Stack deployment completed" +else + print_error "Stack deployment failed" + exit 1 +fi +echo + +# Step 6: Verify services are running +echo "Step 6: Verify services" +print_info "Checking running containers" +docker compose ps +echo + +print_info "Checking critical containers are healthy..." +# Check L2 execution client container +if docker compose ps | grep "l2-nethermind-execution-client" | grep -q "(healthy)"; then + print_success "L2 execution client container is healthy" +else + print_error "L2 execution client container is not healthy" + exit 1 +fi + +# Check other critical containers are running +CRITICAL_CONTAINERS=("l2-taiko-consensus-client" "l2-taiko-proposer-client" "relayer-l1-indexer" "relayer-l2-indexer") +for container in "${CRITICAL_CONTAINERS[@]}"; do + if docker compose ps | grep "$container" | grep -q "Up"; then + print_success "$container is running" + else + print_error "$container is not running" + exit 1 + fi +done +echo + +# Step 7: Health check L2 RPC endpoints +echo "Step 7: Health check L2 RPC endpoints" +print_info "Waiting 30 seconds for services to stabilize..." +sleep 30 + +print_info "Testing L2 RPC endpoint at http://localhost:8547" +if curl -f http://localhost:8547 -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then + echo + print_success "L2 execution client RPC is responding" +else + echo + print_error "L2 execution client RPC health check failed" + exit 1 +fi + +print_info "Testing L2 WebSocket endpoint at ws://localhost:8548" +if curl -f http://localhost:8548 -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then + echo + print_success "L2 WebSocket endpoint is responding" +else + echo + print_error "L2 WebSocket endpoint health check failed" + exit 1 +fi +echo + +# Step 8: Check for errors in logs +echo "Step 8: Check for errors in logs" +print_info "Checking for errors in container logs (last 50 lines)" +if docker compose logs --tail=50 | grep -i "error\|fatal\|panic" | grep -v "error_code" | head -20; then + print_info "Found some errors in logs (review above)" +else + print_success "No critical errors found in recent logs" +fi +echo + +# Final summary +echo "==========================================" +echo "Provision Check Summary" +echo "==========================================" +print_success "All provision checks passed!" +echo +print_info "Services are running. You can now:" +echo " - Access L2 RPC: http://localhost:8547" +echo " - Access L2 Blockscout: http://localhost:3000" +echo " - Access L1 RPC: http://localhost:32003" +echo " - View logs: docker compose logs -f" +echo +print_info "To clean up when done:" +echo " ./surge-remover.sh --devnet-non-interactive" +echo From f22cd96dd9ea240a8170e99f9df12cd293d2ca98 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 17:53:23 +0100 Subject: [PATCH 16/25] cleanup refactor --- script/devnet-provision-check.sh | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/script/devnet-provision-check.sh b/script/devnet-provision-check.sh index 978eddce..ead53948 100755 --- a/script/devnet-provision-check.sh +++ b/script/devnet-provision-check.sh @@ -22,12 +22,16 @@ echo # Step 1: Clean up any existing deployment echo "Step 1: Cleanup existing deployment" -print_info "Running surge-remover.sh --devnet-non-interactive" -if ./surge-remover.sh --devnet-non-interactive; then - print_success "Cleanup completed" +if [ -f "deployment/deploy_l1.json" ] || docker compose ps --services 2>/dev/null | grep -q .; then + print_info "Found existing deployment, running cleanup" + if ./surge-remover.sh --devnet-non-interactive; then + print_success "Cleanup completed" + else + print_error "Cleanup failed" + exit 1 + fi else - print_error "Cleanup failed" - exit 1 + print_info "No existing deployment found, skipping cleanup" fi echo From 7dbb05009f9ce378d03d9583f95e0b7052beaedf Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 18:04:57 +0100 Subject: [PATCH 17/25] remove ws check --- script/devnet-provision-check.sh | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/script/devnet-provision-check.sh b/script/devnet-provision-check.sh index ead53948..28239796 100755 --- a/script/devnet-provision-check.sh +++ b/script/devnet-provision-check.sh @@ -112,8 +112,8 @@ for container in "${CRITICAL_CONTAINERS[@]}"; do done echo -# Step 7: Health check L2 RPC endpoints -echo "Step 7: Health check L2 RPC endpoints" +# Step 7: Health check L2 RPC endpoint +echo "Step 7: Health check L2 RPC endpoint" print_info "Waiting 30 seconds for services to stabilize..." sleep 30 @@ -127,17 +127,6 @@ else print_error "L2 execution client RPC health check failed" exit 1 fi - -print_info "Testing L2 WebSocket endpoint at ws://localhost:8548" -if curl -f http://localhost:8548 -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' 2>/dev/null; then - echo - print_success "L2 WebSocket endpoint is responding" -else - echo - print_error "L2 WebSocket endpoint health check failed" - exit 1 -fi echo # Step 8: Check for errors in logs From d1563ab35ca530360162396d9dd1144519da1baa Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Tue, 21 Oct 2025 18:19:43 +0100 Subject: [PATCH 18/25] add cleanup ci --- .github/workflows/devnet-test-no-provers.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/devnet-test-no-provers.yml b/.github/workflows/devnet-test-no-provers.yml index 7828c5f8..ef95bfc4 100644 --- a/.github/workflows/devnet-test-no-provers.yml +++ b/.github/workflows/devnet-test-no-provers.yml @@ -87,6 +87,21 @@ jobs: echo "Kurtosis Services (surge-devnet)" kurtosis enclave inspect surge-devnet || true + - name: Cleanup - Stop L2 services + if: always() + working-directory: simple-surge-node + run: | + ./surge-remover.sh --devnet-non-interactive || true + + - name: Cleanup - Stop L1 devnet + if: always() + run: | + cd surge-ethereum-package && ./remove-surge-devnet-l1.sh --force || true + + - name: Cleanup - Docker system prune + if: always() + run: | + docker system prune -af --volumes || true - name: Upload test artifacts if: failure() From aa685131a531d914faa0721e74837bb3fa0e44ae Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Wed, 22 Oct 2025 08:49:43 +0100 Subject: [PATCH 19/25] pin action --- .github/workflows/devnet-test-no-provers.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/devnet-test-no-provers.yml b/.github/workflows/devnet-test-no-provers.yml index ef95bfc4..a1314dbe 100644 --- a/.github/workflows/devnet-test-no-provers.yml +++ b/.github/workflows/devnet-test-no-provers.yml @@ -39,7 +39,7 @@ jobs: path: surge-ethereum-package - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Install system dependencies run: | From fd6b87420e257847208c7871d948ad91b65cdc41 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Mon, 27 Oct 2025 15:55:06 +0000 Subject: [PATCH 20/25] fix non-user uid --- docker-compose-relayer.yml | 1 + docker-compose.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/docker-compose-relayer.yml b/docker-compose-relayer.yml index caca2c1c..ec1c57c4 100644 --- a/docker-compose-relayer.yml +++ b/docker-compose-relayer.yml @@ -3,6 +3,7 @@ services: relayer-db: image: mysql:8.0 container_name: relayer-db + user: "${UID:-1000}:${GID:-1000}" cap_add: - SYS_NICE restart: always diff --git a/docker-compose.yml b/docker-compose.yml index 52f3711b..5f17f33f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -256,6 +256,7 @@ services: blockscout-postgres: image: postgres:alpine container_name: l2-blockscout-postgres + user: "${UID:-1000}:${GID:-1000}" restart: unless-stopped pull_policy: always volumes: From a1381f279a60ec1f52c9f8c367a4371decdf1adf Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Wed, 29 Oct 2025 08:27:05 +0000 Subject: [PATCH 21/25] fix --- docker-compose-relayer.yml | 3 ++- docker-compose.yml | 3 ++- surge-protocol-deployer.sh | 6 ++++++ surge-stack-deployer.sh | 6 ++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docker-compose-relayer.yml b/docker-compose-relayer.yml index ec1c57c4..f738b132 100644 --- a/docker-compose-relayer.yml +++ b/docker-compose-relayer.yml @@ -3,7 +3,8 @@ services: relayer-db: image: mysql:8.0 container_name: relayer-db - user: "${UID:-1000}:${GID:-1000}" + # Only set user if DOCKER_USER is explicitly provided (local dev), not in CI + user: "${DOCKER_USER:-}" cap_add: - SYS_NICE restart: always diff --git a/docker-compose.yml b/docker-compose.yml index 5f17f33f..856d76d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -256,7 +256,8 @@ services: blockscout-postgres: image: postgres:alpine container_name: l2-blockscout-postgres - user: "${UID:-1000}:${GID:-1000}" + # Only set user if DOCKER_USER is explicitly provided (local dev), not in CI + user: "${DOCKER_USER:-}" restart: unless-stopped pull_policy: always volumes: diff --git a/surge-protocol-deployer.sh b/surge-protocol-deployer.sh index d20f39f6..20f4d198 100755 --- a/surge-protocol-deployer.sh +++ b/surge-protocol-deployer.sh @@ -9,6 +9,12 @@ if [ "$1" = "--devnet-non-interactive" ]; then NON_INTERACTIVE=true fi +# Export DOCKER_USER for local development to avoid permission issues with database containers +# In CI (NON_INTERACTIVE=true), this remains unset so containers run as root for proper initialization +if [ "$NON_INTERACTIVE" = "false" ] && [ -z "$DOCKER_USER" ]; then + export DOCKER_USER="$(id -u):$(id -g)" +fi + if [ "$NON_INTERACTIVE" = "true" ]; then SURGE_ENVIRONMENT=1 REMOTE_OR_LOCAL=0 diff --git a/surge-stack-deployer.sh b/surge-stack-deployer.sh index 51bce27a..0607401b 100755 --- a/surge-stack-deployer.sh +++ b/surge-stack-deployer.sh @@ -9,6 +9,12 @@ if [ "$1" = "--devnet-non-interactive" ]; then NON_INTERACTIVE=true fi +# Export DOCKER_USER for local development to avoid permission issues with database containers +# In CI (NON_INTERACTIVE=true), this remains unset so containers run as root for proper initialization +if [ "$NON_INTERACTIVE" = "false" ] && [ -z "$DOCKER_USER" ]; then + export DOCKER_USER="$(id -u):$(id -g)" +fi + check_env_file() { if [ -f .env ]; then echo From 63bf1c7a17582725b974cbb55839eb03eeb84488 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Thu, 30 Oct 2025 12:21:30 +0000 Subject: [PATCH 22/25] cleanup --- surge-remover.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/surge-remover.sh b/surge-remover.sh index e53b130e..6cc938ec 100755 --- a/surge-remover.sh +++ b/surge-remover.sh @@ -55,21 +55,20 @@ remove_db() { echo # Remove DB contents but preserve directory structure with .gitkeep - # Use sudo for directories that might be owned by root if [ -d "./execution-data" ] && [ "$(ls -A ./execution-data 2>/dev/null | wc -l)" -gt 0 ]; then - sudo rm -rf ./execution-data/* || echo "Warning: Could not remove some execution-data files" + rm -rf ./execution-data/* || echo "Warning: Could not remove some execution-data files" fi if [ -d "./blockscout-postgres-data" ] && [ "$(ls -A ./blockscout-postgres-data 2>/dev/null | wc -l)" -gt 0 ]; then - sudo rm -rf ./blockscout-postgres-data/* || echo "Warning: Could not remove some blockscout-postgres-data files" + rm -rf ./blockscout-postgres-data/* || echo "Warning: Could not remove some blockscout-postgres-data files" fi if [ -d "./mysql-data" ] && [ "$(ls -A ./mysql-data 2>/dev/null | wc -l)" -gt 0 ]; then - sudo rm -rf ./mysql-data/* || echo "Warning: Could not remove some mysql-data files" + rm -rf ./mysql-data/* || echo "Warning: Could not remove some mysql-data files" fi if [ -d "./rabbitmq" ] && [ "$(ls -A ./rabbitmq 2>/dev/null | wc -l)" -gt 0 ]; then - sudo rm -rf ./rabbitmq/* || echo "Warning: Could not remove some rabbitmq files" + rm -rf ./rabbitmq/* || echo "Warning: Could not remove some rabbitmq files" fi # Recreate .gitkeep files From 266b81d12bae9ef95129a098d259d4d8b7f93b31 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Thu, 30 Oct 2025 16:31:47 +0000 Subject: [PATCH 23/25] Potential fix for code scanning alert no. 15: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/devnet-test-no-provers.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/devnet-test-no-provers.yml b/.github/workflows/devnet-test-no-provers.yml index a1314dbe..cf03ef2e 100644 --- a/.github/workflows/devnet-test-no-provers.yml +++ b/.github/workflows/devnet-test-no-provers.yml @@ -22,6 +22,9 @@ env: jobs: devnet-provision-check-no-provers: name: Devnet Provision Check (No Provers) + permissions: + contents: read + issues: write runs-on: ubuntu-22.04 timeout-minutes: 45 From 7ebc7770b46c5192af4e288b9271b9b2b96037f7 Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Fri, 31 Oct 2025 08:29:17 +0000 Subject: [PATCH 24/25] Update surge-remover.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- surge-remover.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/surge-remover.sh b/surge-remover.sh index 6cc938ec..962dcf3d 100755 --- a/surge-remover.sh +++ b/surge-remover.sh @@ -55,19 +55,19 @@ remove_db() { echo # Remove DB contents but preserve directory structure with .gitkeep - if [ -d "./execution-data" ] && [ "$(ls -A ./execution-data 2>/dev/null | wc -l)" -gt 0 ]; then + if [ -d "./execution-data" ] && [ -n "$(ls -A ./execution-data 2>/dev/null)" ]; then rm -rf ./execution-data/* || echo "Warning: Could not remove some execution-data files" fi - if [ -d "./blockscout-postgres-data" ] && [ "$(ls -A ./blockscout-postgres-data 2>/dev/null | wc -l)" -gt 0 ]; then + if [ -d "./blockscout-postgres-data" ] && [ -n "$(ls -A ./blockscout-postgres-data 2>/dev/null)" ]; then rm -rf ./blockscout-postgres-data/* || echo "Warning: Could not remove some blockscout-postgres-data files" fi - if [ -d "./mysql-data" ] && [ "$(ls -A ./mysql-data 2>/dev/null | wc -l)" -gt 0 ]; then + if [ -d "./mysql-data" ] && [ -n "$(ls -A ./mysql-data 2>/dev/null)" ]; then rm -rf ./mysql-data/* || echo "Warning: Could not remove some mysql-data files" fi - if [ -d "./rabbitmq" ] && [ "$(ls -A ./rabbitmq 2>/dev/null | wc -l)" -gt 0 ]; then + if [ -d "./rabbitmq" ] && [ -n "$(ls -A ./rabbitmq 2>/dev/null)" ]; then rm -rf ./rabbitmq/* || echo "Warning: Could not remove some rabbitmq files" fi From a2db3bf90bf47c1fdf0d4c037a8d85ddf5a0eeda Mon Sep 17 00:00:00 2001 From: Michael Vasylenko Date: Fri, 31 Oct 2025 08:29:52 +0000 Subject: [PATCH 25/25] Update surge-remover.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- surge-remover.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/surge-remover.sh b/surge-remover.sh index 962dcf3d..dce63052 100755 --- a/surge-remover.sh +++ b/surge-remover.sh @@ -72,9 +72,13 @@ remove_db() { fi # Recreate .gitkeep files + mkdir -p ./execution-data touch ./execution-data/.gitkeep + mkdir -p ./blockscout-postgres-data touch ./blockscout-postgres-data/.gitkeep + mkdir -p ./mysql-data touch ./mysql-data/.gitkeep + mkdir -p ./rabbitmq touch ./rabbitmq/.gitkeep echo