From 53dae5fe841a610b2b23958ceefc9233678acc4a Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Tue, 16 Jul 2024 15:21:14 -0700 Subject: [PATCH] refactor(ci): optimize CI/CD pipeline with parallel testing and enhanced caching - Introduced a `Prepare` job to set up the repository, cache dependencies, count unit tests, and calculate chunks for parallel execution. - Updated `Build-And-Test-Server` job to restore repository and dependencies from cache, run integration tests, and add results to the job summary. - Added `Run-Unit-Tests` job to execute unit tests in parallel chunks, upload test results, and add them to the job summary. - Enhanced `Build-And-Test-Web` job to cache Playwright browsers, run end-to-end tests, and upload E2E test artifacts. - Refined `Release-on-NPM` and `Release-mina-signer-on-NPM` jobs to build and publish the project if the version has changed. --- .github/workflows/build-action.yml | 211 +++++++++++++++++++++++++---- 1 file changed, 188 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 81e670a737..fae2b0939e 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -8,7 +8,53 @@ on: workflow_dispatch: {} jobs: + Prepare: + runs-on: ubuntu-latest + outputs: + test_count: ${{ steps.count_tests.outputs.test_count }} + chunk_count: 8 # This is hardcoded to 8, but it can be changed to any number. + steps: + - name: Checkout repository with submodules + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Cache dependencies and build + uses: actions/cache@v4 + id: cache + with: + path: | + ~/.npm + node_modules + dist + key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.js') }} + + - name: Build o1js + if: steps.cache.outputs.cache-hit != 'true' + run: | + npm ci + npm run build + + - name: Count tests + id: count_tests + run: | + TEST_COUNT=$(find ./dist/node -name "*.unit-test.js" | wc -l) + echo "test_count=${TEST_COUNT}" >> $GITHUB_OUTPUT + echo "Total test count: ${TEST_COUNT}" + + - name: Cache repository + uses: actions/cache@v4 + with: + path: . + key: repo-${{ github.sha }} + Build-And-Test-Server: + needs: Prepare timeout-minutes: 210 runs-on: ubuntu-latest strategy: @@ -21,51 +67,160 @@ jobs: 'DEX integration tests', 'DEX integration test with proofs', 'Voting integration tests', - 'Unit tests', 'Verification Key Regression Check', 'CommonJS test', ] steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Restore repository + uses: actions/cache@v4 + with: + path: . + key: repo-${{ github.sha }} + - name: Setup Node uses: actions/setup-node@v4 with: node-version: '18' - - name: Build o1js and execute tests + + - name: Restore cache + uses: actions/cache@v4 + with: + path: | + ~/.npm + node_modules + dist + key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.js') }} + + - name: Prepare for tests + run: touch profiling.md + + - name: Execute tests env: TEST_TYPE: ${{ matrix.test_type }} + run: sh run-ci-tests.sh + + - name: Add to job summary + if: always() + run: | + echo "### Test Results for ${{ matrix.test_type }}" >> $GITHUB_STEP_SUMMARY + cat profiling.md >> $GITHUB_STEP_SUMMARY + + Run-Unit-Tests: + needs: Prepare + name: Run unit tests parallel + timeout-minutes: 210 + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + chunk: [1, 2, 3, 4, 5, 6, 7, 8] + steps: + - name: Restore repository + uses: actions/cache@v4 + with: + path: . + key: repo-${{ github.sha }} + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Restore cache + uses: actions/cache@v4 + with: + path: | + ~/.npm + node_modules + dist + key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.js') }} + + - name: Prepare for tests + run: touch profiling.md + + - name: Run unit tests + env: + TOTAL_TESTS: ${{ needs.Prepare.outputs.test_count }} + CHUNK: ${{ matrix.chunk }} + CHUNKS: 8 + run: | + echo "Total tests: $TOTAL_TESTS" + echo "Current chunk: $CHUNK" + echo "Total chunks: $CHUNKS" + + if [ -z "$TOTAL_TESTS" ] || [ "$TOTAL_TESTS" -eq 0 ]; then + echo "Error: TOTAL_TESTS is not set or is zero. Exiting." + exit 1 + fi + + start_index=$(( (TOTAL_TESTS * (CHUNK - 1) / CHUNKS) )) + end_index=$(( (TOTAL_TESTS * CHUNK / CHUNKS) )) + + echo "Running tests from index $start_index to $end_index" + + shopt -s globstar + test_files=(./dist/node/**/*.unit-test.js) + + for ((i=start_index; i> $GITHUB_STEP_SUMMARY cat profiling.md >> $GITHUB_STEP_SUMMARY Build-And-Test-Web: + needs: Prepare timeout-minutes: 90 runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Restore repository + uses: actions/cache@v4 + with: + path: . + key: repo-${{ github.sha }} + - name: Setup Node uses: actions/setup-node@v4 with: node-version: '18' - - name: Install Node dependencies - run: | - git submodule update --init --recursive - npm ci + + - name: Restore npm cache + uses: actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} + + - name: Cache Playwright browsers + uses: actions/cache@v4 + id: playwright-cache + with: + path: ~/.cache/ms-playwright + key: ${{ runner.OS }}-playwright-${{ hashFiles('**/package-lock.json') }} + - name: Install Playwright browsers + if: steps.playwright-cache.outputs.cache-hit != 'true' run: npm run e2e:install + - name: Build o1js and prepare the web server run: | npm run build:web npm run e2e:prepare-server + - name: Execute E2E tests run: npm run test:e2e + - name: Upload E2E test artifacts uses: actions/upload-artifact@v4 continue-on-error: true @@ -80,19 +235,24 @@ jobs: if: github.ref == 'refs/heads/main' timeout-minutes: 180 runs-on: ubuntu-latest - needs: [Build-And-Test-Server, Build-And-Test-Web] + needs: [Build-And-Test-Server, Run-Unit-Tests, Build-And-Test-Web] steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Restore repository + uses: actions/cache@v4 + with: + path: . + key: repo-${{ github.sha }} + - name: Setup Node uses: actions/setup-node@v4 with: node-version: '18' + - name: Build o1js run: | - git submodule update --init --recursive npm ci npm run prepublishOnly + - name: Publish to NPM if version has changed uses: JS-DevTools/npm-publish@v3 with: @@ -105,21 +265,26 @@ jobs: if: github.ref == 'refs/heads/main' timeout-minutes: 180 runs-on: ubuntu-latest - needs: [Build-And-Test-Server, Build-And-Test-Web] + needs: [Build-And-Test-Server, Run-Unit-Tests, Build-And-Test-Web] steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Restore repository + uses: actions/cache@v4 + with: + path: . + key: repo-${{ github.sha }} + - name: Setup Node uses: actions/setup-node@v4 with: node-version: '18' + - name: Build mina-signer run: | - git submodule update --init --recursive npm ci cd src/mina-signer npm ci npm run prepublishOnly + - name: Publish to NPM if version has changed uses: JS-DevTools/npm-publish@v3 with: