feat: add ws-plugin and cron-plugin to official Motia plugins #1145
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: E2E Tests (PR) | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, labeled] | |
| branches: [main] | |
| paths: | |
| - 'packages/**' | |
| - 'playground/**' | |
| - '!packages/docs/**' | |
| - '.github/workflows/e2e-tests-pr.yml' | |
| workflow_dispatch: | |
| inputs: | |
| branch: | |
| description: 'Branch to run E2E tests against' | |
| required: true | |
| default: 'main' | |
| type: string | |
| permissions: | |
| contents: read | |
| checks: write | |
| pull-requests: write | |
| jobs: | |
| e2e-pr-tests: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| template: [motia-tutorial-typescript, motia-tutorial-python] | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 30 | |
| env: | |
| CI: true | |
| NODE_ENV: test | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha || github.event.inputs.branch || github.sha }} | |
| fetch-depth: 0 | |
| - name: Verify checkout branch | |
| run: | | |
| echo "Current branch: $(git branch --show-current || echo 'detached HEAD')" | |
| echo "Current commit: $(git rev-parse HEAD)" | |
| echo "Event name: ${{ github.event_name }}" | |
| if [ "${{ github.event_name }}" == "pull_request" ]; then | |
| echo "PR head SHA: ${{ github.event.pull_request.head.sha }}" | |
| echo "PR head ref: ${{ github.event.pull_request.head.ref }}" | |
| echo "PR base ref: ${{ github.event.pull_request.base.ref }}" | |
| echo "Expected commit SHA: ${{ github.event.pull_request.head.sha }}" | |
| echo "Actual commit SHA: $(git rev-parse HEAD)" | |
| if [ "$(git rev-parse HEAD)" != "${{ github.event.pull_request.head.sha }}" ]; then | |
| echo "⚠️ WARNING: Checkout SHA mismatch!" | |
| exit 1 | |
| fi | |
| fi | |
| - uses: pnpm/action-setup@v4 | |
| - name: Setup | |
| uses: ./.github/actions/setup | |
| - name: Install Redis | |
| run: | | |
| if [ "${{ runner.os }}" == "Linux" ]; then | |
| sudo apt-get update | |
| sudo apt-get install -y redis-server | |
| redis-server --daemonize yes | |
| elif [ "${{ runner.os }}" == "macOS" ]; then | |
| brew install redis | |
| brew services start redis | |
| fi | |
| sleep 2 | |
| redis-cli ping || echo "Redis not responding to ping" | |
| - name: Get Playwright version | |
| id: playwright-version | |
| run: | | |
| cd packages/e2e | |
| PLAYWRIGHT_VERSION=$(node -p "require('./package.json').dependencies['@playwright/test'] || require('./package.json').devDependencies['@playwright/test']") | |
| echo "version=$PLAYWRIGHT_VERSION" >> $GITHUB_OUTPUT | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v4 | |
| id: playwright-cache | |
| with: | |
| path: | | |
| ~/.cache/ms-playwright | |
| ~/AppData/Local/ms-playwright | |
| ~/Library/Caches/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: | | |
| playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}- | |
| playwright-${{ runner.os }}- | |
| - name: Install E2E dependencies and browsers | |
| run: | | |
| cd packages/e2e | |
| pnpm install | |
| pnpm exec playwright install | |
| pnpm exec playwright install-deps | |
| - name: Clean previous test artifacts | |
| run: | | |
| cd packages/e2e | |
| pnpm clean | |
| - name: Verify built CLI | |
| run: | | |
| # Verify the built CLI exists | |
| if [ ! -f "packages/snap/dist/cli.mjs" ]; then | |
| echo "❌ Built CLI not found at packages/snap/dist/cli.mjs" | |
| echo "Available files in dist:" | |
| ls -la packages/snap/dist/ || echo "dist directory not found" | |
| exit 1 | |
| fi | |
| # Make CLI executable through node | |
| echo "✅ Built CLI found at packages/snap/dist/cli.mjs" | |
| node packages/snap/dist/cli.mjs --version || echo "CLI version check failed" | |
| - name: Record test start time | |
| run: echo "START_TIME=$(date +%s)" >> $GITHUB_ENV | |
| - name: Run PR E2E tests with built CLI | |
| id: run_tests | |
| uses: nick-fields/retry@v3 | |
| with: | |
| timeout_minutes: 10 | |
| max_attempts: 2 | |
| retry_on: error | |
| shell: bash | |
| command: | | |
| cd packages/e2e | |
| echo "🧪 Starting PR E2E tests - Template: ${{ matrix.template }}, OS: ${{ matrix.os }}" | |
| # Export the built CLI path for tests to use | |
| export MOTIA_CLI_PATH="$GITHUB_WORKSPACE/packages/snap/dist/cli.mjs" | |
| export MOTIA_ANALYTICS_DISABLED=true | |
| export MOTIA_API_URL=http://localhost:3000 | |
| export MOTIA_TEST_TEMPLATE=${{ matrix.template }} | |
| export REDISMS_SYSTEM_BINARY=$(which redis-server) | |
| # Run tests based on template (no sharding) | |
| if [ "${{ matrix.template }}" == "motia-tutorial-python" ]; then | |
| pnpm test:pr:python --reporter=line,html,github | |
| else | |
| pnpm test:pr --reporter=line,html,github | |
| fi | |
| - name: Record test metrics | |
| if: always() | |
| run: | | |
| TEST_DURATION=$(($(date +%s) - $START_TIME)) | |
| echo "TEST_DURATION=$TEST_DURATION" >> $GITHUB_ENV | |
| echo "::notice title=Test Duration::${{ matrix.template }} on ${{ matrix.os }} completed in $TEST_DURATION seconds" | |
| # Output performance metrics | |
| echo "### Performance Metrics - ${{ matrix.os }} - ${{ matrix.template }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Duration: ${TEST_DURATION}s" >> $GITHUB_STEP_SUMMARY | |
| echo "- Status: ${{ steps.run_tests.outcome }}" >> $GITHUB_STEP_SUMMARY | |
| - name: Process test results | |
| id: test_result | |
| if: always() | |
| run: | | |
| echo "📊 Test Results Summary:" | |
| echo "- Template: ${{ matrix.template }}" | |
| echo "- OS: ${{ matrix.os }}" | |
| echo "- Test outcome: ${{ steps.run_tests.outcome }}" | |
| echo "- Duration: ${{ env.TEST_DURATION }} seconds" | |
| if [ "${{ steps.run_tests.outcome }}" == "success" ]; then | |
| echo "result=success" >> $GITHUB_OUTPUT | |
| echo "✅ PR E2E tests passed for ${{ matrix.template }} on ${{ matrix.os }}" | |
| else | |
| echo "result=failure" >> $GITHUB_OUTPUT | |
| echo "::error title=Test Failed::E2E tests failed for ${{ matrix.template }} on ${{ matrix.os }}" | |
| # Extract and display error summary if available | |
| if [ -f "packages/e2e/test-results/results.json" ]; then | |
| echo "### Failed Tests Summary" >> $GITHUB_STEP_SUMMARY | |
| jq -r '.failures[]' packages/e2e/test-results/results.json >> $GITHUB_STEP_SUMMARY 2>/dev/null || true | |
| fi | |
| exit 1 | |
| fi | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-pr-test-results-${{ github.event.number }}-${{ matrix.os }}-${{ matrix.template }} | |
| path: | | |
| packages/e2e/playwright-report/ | |
| packages/e2e/test-results/ | |
| packages/e2e/test-results.xml | |
| retention-days: 7 | |
| - name: Clean up test artifacts | |
| if: always() | |
| run: | | |
| echo "🧹 Cleaning up test artifacts..." | |
| # Kill any processes on port 3000 | |
| if command -v lsof &> /dev/null; then | |
| PORT_PIDS=$(lsof -ti:3000 2>/dev/null || true) | |
| if [ ! -z "$PORT_PIDS" ]; then | |
| echo "$PORT_PIDS" | xargs -r kill -9 2>/dev/null || true | |
| fi | |
| fi | |
| # Clean up any test project directories created during tests | |
| rm -rf packages/e2e/motia-e2e-test-project* 2>/dev/null || true | |
| echo "✅ Cleanup complete" | |
| # Windows-specific job that only runs when e2e-windows label is present | |
| e2e-pr-tests-windows: | |
| if: contains(github.event.pull_request.labels.*.name, 'e2e-windows') | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| template: [motia-tutorial-typescript, motia-tutorial-python] | |
| runs-on: windows-latest | |
| timeout-minutes: 30 | |
| env: | |
| CI: true | |
| NODE_ENV: test | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha || github.event.inputs.branch || github.sha }} | |
| fetch-depth: 0 | |
| - name: Verify checkout branch | |
| shell: bash | |
| run: | | |
| echo "Current branch: $(git branch --show-current || echo 'detached HEAD')" | |
| echo "Current commit: $(git rev-parse HEAD)" | |
| echo "Event name: ${{ github.event_name }}" | |
| if [ "${{ github.event_name }}" == "pull_request" ]; then | |
| echo "PR head SHA: ${{ github.event.pull_request.head.sha }}" | |
| echo "PR head ref: ${{ github.event.pull_request.head.ref }}" | |
| echo "PR base ref: ${{ github.event.pull_request.base.ref }}" | |
| echo "Expected commit SHA: ${{ github.event.pull_request.head.sha }}" | |
| echo "Actual commit SHA: $(git rev-parse HEAD)" | |
| if [ "$(git rev-parse HEAD)" != "${{ github.event.pull_request.head.sha }}" ]; then | |
| echo "WARNING: Checkout SHA mismatch!" | |
| exit 1 | |
| fi | |
| fi | |
| - uses: pnpm/action-setup@v4 | |
| - name: Setup | |
| uses: ./.github/actions/setup | |
| - name: Get Playwright version | |
| id: playwright-version | |
| shell: bash | |
| run: | | |
| cd packages/e2e | |
| PLAYWRIGHT_VERSION=$(node -p "require('./package.json').dependencies['@playwright/test'] || require('./package.json').devDependencies['@playwright/test']") | |
| echo "version=$PLAYWRIGHT_VERSION" >> $GITHUB_OUTPUT | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v4 | |
| id: playwright-cache | |
| with: | |
| path: | | |
| ~/.cache/ms-playwright | |
| ~/AppData/Local/ms-playwright | |
| ~/Library/Caches/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: | | |
| playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}- | |
| playwright-${{ runner.os }}- | |
| - name: Install E2E dependencies and browsers | |
| shell: bash | |
| run: | | |
| cd packages/e2e | |
| pnpm install | |
| pnpm exec playwright install | |
| pnpm exec playwright install-deps | |
| - name: Clean previous test artifacts | |
| shell: bash | |
| run: | | |
| cd packages/e2e | |
| pnpm clean | |
| - name: Verify built CLI (Windows) | |
| shell: cmd | |
| run: | | |
| if not exist "packages\snap\dist\cli.mjs" ( | |
| echo Built CLI not found at packages\snap\dist\cli.mjs | |
| dir packages\snap\dist\ 2>nul || echo dist directory not found | |
| exit /b 1 | |
| ) | |
| echo Built CLI found at packages\snap\dist\cli.mjs | |
| node packages\snap\dist\cli.mjs --version || echo CLI version check failed | |
| - name: Record test start time | |
| shell: bash | |
| run: echo "START_TIME=$(date +%s)" >> $GITHUB_ENV | |
| - name: Set test environment variables (Windows) | |
| shell: pwsh | |
| run: | | |
| echo "MOTIA_CLI_PATH=$env:GITHUB_WORKSPACE\packages\snap\dist\cli.mjs" >> $env:GITHUB_ENV | |
| echo "MOTIA_ANALYTICS_DISABLED=true" >> $env:GITHUB_ENV | |
| echo "MOTIA_API_URL=http://localhost:3000" >> $env:GITHUB_ENV | |
| echo "MOTIA_TEST_TEMPLATE=${{ matrix.template }}" >> $env:GITHUB_ENV | |
| echo "MOTIA_WINDOWS_FAST_MODE=true" >> $env:GITHUB_ENV | |
| - name: Run PR E2E tests with built CLI (Windows) | |
| id: run_tests | |
| uses: nick-fields/retry@v3 | |
| with: | |
| timeout_minutes: 10 | |
| max_attempts: 2 | |
| retry_on: error | |
| shell: bash | |
| command: | | |
| cd packages/e2e | |
| echo "Starting PR E2E tests - Template: ${{ matrix.template }}, OS: windows-latest" | |
| # Run tests based on template (no sharding) | |
| if [ "${{ matrix.template }}" == "motia-tutorial-python" ]; then | |
| pnpm test:pr:python --reporter=line,html,github | |
| else | |
| pnpm test:pr --reporter=line,html,github | |
| fi | |
| - name: Record test metrics | |
| if: always() | |
| shell: bash | |
| run: | | |
| TEST_DURATION=$(($(date +%s) - $START_TIME)) | |
| echo "TEST_DURATION=$TEST_DURATION" >> $GITHUB_ENV | |
| echo "::notice title=Test Duration::${{ matrix.template }} on windows-latest completed in $TEST_DURATION seconds" | |
| # Output performance metrics | |
| echo "### Performance Metrics - windows-latest - ${{ matrix.template }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Duration: ${TEST_DURATION}s" >> $GITHUB_STEP_SUMMARY | |
| echo "- Status: ${{ steps.run_tests.outcome }}" >> $GITHUB_STEP_SUMMARY | |
| - name: Process test results | |
| id: test_result | |
| if: always() | |
| shell: bash | |
| run: | | |
| echo "Test Results Summary:" | |
| echo "- Template: ${{ matrix.template }}" | |
| echo "- OS: windows-latest" | |
| echo "- Test outcome: ${{ steps.run_tests.outcome }}" | |
| echo "- Duration: ${{ env.TEST_DURATION }} seconds" | |
| if [ "${{ steps.run_tests.outcome }}" == "success" ]; then | |
| echo "result=success" >> $GITHUB_OUTPUT | |
| echo "PR E2E tests passed for ${{ matrix.template }} on windows-latest" | |
| else | |
| echo "result=failure" >> $GITHUB_OUTPUT | |
| echo "::error title=Test Failed::E2E tests failed for ${{ matrix.template }} on windows-latest" | |
| # Extract and display error summary if available | |
| if [ -f "packages/e2e/test-results/results.json" ]; then | |
| echo "### Failed Tests Summary" >> $GITHUB_STEP_SUMMARY | |
| jq -r '.failures[]' packages/e2e/test-results/results.json >> $GITHUB_STEP_SUMMARY 2>/dev/null || true | |
| fi | |
| exit 1 | |
| fi | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-pr-test-results-${{ github.event.number }}-windows-latest-${{ matrix.template }} | |
| path: | | |
| packages/e2e/playwright-report/ | |
| packages/e2e/test-results/ | |
| packages/e2e/test-results.xml | |
| retention-days: 7 | |
| - name: Clean up test artifacts (Windows) | |
| if: always() | |
| shell: pwsh | |
| run: | | |
| Write-Host "Cleaning up test artifacts..." | |
| # Kill any processes on port 3000 | |
| $processes = Get-NetTCPConnection -LocalPort 3000 -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess -Unique | |
| foreach ($proc in $processes) { | |
| Stop-Process -Id $proc -Force -ErrorAction SilentlyContinue | |
| } | |
| # Clean up any test project directories created during tests | |
| Remove-Item -Path "packages\e2e\motia-e2e-test-project*" -Recurse -Force -ErrorAction SilentlyContinue | |
| Write-Host "Cleanup complete" | |
| # Aggregate results from all matrix jobs | |
| check-results: | |
| needs: [e2e-pr-tests, e2e-pr-tests-windows] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| outputs: | |
| result: ${{ steps.check_result.outputs.result }} | |
| run_id: ${{ github.run_id }} | |
| pr_number: ${{ github.event.pull_request.number }} | |
| steps: | |
| - name: Check all test results | |
| id: check_result | |
| run: | | |
| echo "📊 Checking results from all test jobs..." | |
| MAIN_RESULT='${{ needs.e2e-pr-tests.result }}' | |
| WINDOWS_RESULT='${{ needs.e2e-pr-tests-windows.result }}' | |
| echo "Main tests (Ubuntu/macOS) result: $MAIN_RESULT" | |
| echo "Windows tests result: $WINDOWS_RESULT" | |
| # Main tests must pass | |
| if [ "$MAIN_RESULT" != "success" ]; then | |
| echo "result=failure" >> $GITHUB_OUTPUT | |
| echo "❌ Main PR E2E tests failed" | |
| echo "### PR E2E Tests: FAILED ❌" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| # Windows tests must pass if they ran (not skipped) | |
| if [ "$WINDOWS_RESULT" == "failure" ]; then | |
| echo "result=failure" >> $GITHUB_OUTPUT | |
| echo "❌ Windows PR E2E tests failed" | |
| echo "### PR E2E Tests: FAILED ❌ (Windows)" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| echo "result=success" >> $GITHUB_OUTPUT | |
| if [ "$WINDOWS_RESULT" == "skipped" ]; then | |
| echo "✅ All PR E2E tests passed (Windows tests skipped - no e2e-windows label)" | |
| echo "### PR E2E Tests: PASSED ✅ (Windows skipped)" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "✅ All PR E2E tests passed (including Windows)" | |
| echo "### PR E2E Tests: PASSED ✅ (including Windows)" >> $GITHUB_STEP_SUMMARY | |
| fi |