diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml new file mode 100644 index 0000000000..0cab6100bc --- /dev/null +++ b/.github/workflows/e2e-tests.yml @@ -0,0 +1,169 @@ +name: E2E Tests + +on: + issue_comment: + types: [created] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + +jobs: + e2e_tests: + runs-on: ubicloud + timeout-minutes: 30 + if: | + github.event_name == 'workflow_dispatch' || + (github.event_name == 'issue_comment' && + github.event.issue.pull_request && + contains(github.event.comment.body, '/run-e2e')) + + steps: + - name: React to comment + if: github.event_name == 'issue_comment' + uses: actions/github-script@v7 + with: + script: | + await github.rest.reactions.createForIssueComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: context.payload.comment.id, + content: 'rocket' + }); + + - name: Get PR branch + if: github.event_name == 'issue_comment' + uses: actions/github-script@v7 + id: get-branch + with: + script: | + const pr = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number + }); + return pr.data.head.ref; + result-encoding: string + + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'issue_comment' && steps.get-branch.outputs.result || github.ref }} + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Start E2E environment with Docker Compose + working-directory: ./e2e-tests + env: + WM_IMAGE: ghcr.io/windmill-labs/windmill-ee:main + DATABASE_URL: postgres://postgres:changeme@db:5432/windmill + LICENSE_KEY: ${{ secrets.WM_LICENSE_KEY_CI }} + run: | + docker compose up -d + echo "Waiting for services to be healthy..." + # Wait for all services to be healthy (up to 5 minutes) + timeout=300 + elapsed=0 + while [ $elapsed -lt $timeout ]; do + if docker compose ps | grep -q "unhealthy\|starting"; then + echo "Services still starting... ($elapsed seconds elapsed)" + sleep 10 + elapsed=$((elapsed + 10)) + else + echo "All services are healthy!" + break + fi + done + + if [ $elapsed -ge $timeout ]; then + echo "Timeout waiting for services to be healthy" + docker compose ps + docker compose logs + exit 1 + fi + + # Additional wait for Windmill server to be fully ready + echo "Waiting for Windmill server to be ready..." + sleep 30 + + # Check if server is responding + curl -f http://localhost:80/api/version || (echo "Windmill server not responding" && docker compose logs windmill_server && exit 1) + + - name: Install Playwright + working-directory: ./frontend + run: | + npm install --no-save @playwright/test + npx playwright install --with-deps chromium + + - name: Run E2E tests + working-directory: ./frontend + env: + BASE_URL: http://localhost:80 + CI: true + run: npm run test:e2e + + - name: Upload Playwright report + uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: frontend/playwright-report/ + retention-days: 30 + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: frontend/test-results/ + retention-days: 30 + + - name: Capture Docker logs on failure + if: failure() + working-directory: ./e2e-tests + run: | + mkdir -p logs + docker compose logs > logs/docker-compose.log + docker compose ps > logs/docker-compose-ps.log + + - name: Upload Docker logs + uses: actions/upload-artifact@v4 + if: failure() + with: + name: docker-logs + path: e2e-tests/logs/ + retention-days: 7 + + - name: Comment on PR with results + if: always() && github.event_name == 'issue_comment' + uses: actions/github-script@v7 + with: + script: | + const conclusion = '${{ job.status }}'; + const emoji = conclusion === 'success' ? '✅' : '❌'; + const message = conclusion === 'success' ? 'passed' : 'failed'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: `${emoji} E2E tests ${message}\n\nView the [workflow run](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) for details.` + }); + + - name: Cleanup + if: always() + working-directory: ./e2e-tests + run: | + docker compose down -v + docker compose rm -f