diff --git a/.github/workflows/ci-e2e-playwright.yml b/.github/workflows/ci-e2e-playwright.yml new file mode 100644 index 0000000..047e265 --- /dev/null +++ b/.github/workflows/ci-e2e-playwright.yml @@ -0,0 +1,93 @@ +# Reusable workflow for running Playwright E2E tests in a containerized +# environment with browsers pre-installed. Eliminates the ~60s browser +# install step by using Microsoft's official Playwright Docker images. +# +# Usage: +# +# jobs: +# e2e: +# uses: codeflash-ai/github-workflows/.github/workflows/ci-e2e-playwright.yml@main +# with: +# test-command: "uv run pytest tests/e2e/ --browser $BROWSER -v" +# +# The $BROWSER placeholder in test-command is replaced with the matrix +# browser value (chromium, firefox, or webkit) at runtime. + +name: E2E (Playwright) + +on: + workflow_call: + inputs: + playwright-version: + description: "Playwright version tag, e.g. v1.59.0 (defaults to latest)" + type: string + default: "v1.59.0" + base-image: + description: "Ubuntu base for the container image" + type: string + default: "noble" + browsers: + description: "JSON array of browsers to test" + type: string + default: '["chromium", "firefox", "webkit"]' + sync-command: + description: "Dependency install command" + type: string + default: "uv sync" + test-command: + description: "Pytest command template — use $BROWSER placeholder for browser name" + type: string + required: true + test-directory: + description: "Working directory for all commands" + type: string + default: "." + artifact-retention-days: + description: "How long to keep trace artifacts" + type: number + default: 7 + fail-fast: + description: "Stop on first browser failure" + type: boolean + default: false + +jobs: + e2e: + strategy: + fail-fast: ${{ inputs.fail-fast }} + matrix: + browser: ${{ fromJSON(inputs.browsers) }} + runs-on: ubuntu-latest + container: + image: mcr.microsoft.com/playwright/python:${{ inputs.playwright-version }}-${{ inputs.base-image }} + options: --user 1001 + permissions: + contents: read + env: + UV_LINK_MODE: copy + defaults: + run: + working-directory: ${{ inputs.test-directory }} + steps: + - uses: actions/checkout@v6 + + - uses: astral-sh/setup-uv@v8.1.0 + with: + enable-cache: true + + - run: ${{ inputs.sync-command }} + + - name: Run Playwright tests (${{ matrix.browser }}) + shell: bash + run: | + BROWSER="${{ matrix.browser }}" && ${TEST_CMD/\$BROWSER/$BROWSER} + env: + TEST_CMD: ${{ inputs.test-command }} + + - name: Upload traces + if: failure() + uses: actions/upload-artifact@v4 + with: + name: playwright-traces-${{ matrix.browser }} + path: ${{ inputs.test-directory }}/test-results/ + retention-days: ${{ inputs.artifact-retention-days }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8e35ac8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,12 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +jobs: + ready: + uses: ./.github/workflows/ready-to-merge.yml + with: + result: success diff --git a/.github/workflows/prek-lint.yml b/.github/workflows/prek-lint.yml index 97f728e..9bf36e0 100644 --- a/.github/workflows/prek-lint.yml +++ b/.github/workflows/prek-lint.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: ${{ inputs.continue-on-error }} permissions: - contents: write + contents: read steps: - uses: actions/checkout@v6 with: diff --git a/.github/workflows/ready-to-merge.yml b/.github/workflows/ready-to-merge.yml index 0ad8646..6fdf256 100644 --- a/.github/workflows/ready-to-merge.yml +++ b/.github/workflows/ready-to-merge.yml @@ -2,9 +2,18 @@ name: Ready to Merge on: workflow_call: + inputs: + result: + description: "Pass 'success' when all upstream jobs passed" + type: string + required: true jobs: ready: runs-on: ubuntu-latest steps: - - run: echo "Branch is up to date" + - run: | + if [ "${{ inputs.result }}" != "success" ]; then + echo "CI failed" + exit 1 + fi diff --git a/README.md b/README.md index 13cc595..a09a51f 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,47 @@ jobs: CI_BOT_PRIVATE_KEY: ${{ secrets.CI_BOT_PRIVATE_KEY }} ``` +### `ci-e2e-playwright.yml` + +Reusable workflow for running [Playwright](https://playwright.dev/) E2E tests inside a Docker container with browsers pre-installed. Uses Microsoft's official `mcr.microsoft.com/playwright/python` images, eliminating the ~60s browser install step per job. + +**Inputs:** + +| Input | Default | Description | +|---|---|---| +| `playwright-version` | *(required)* | Playwright version tag, e.g. `"v1.59.0"` | +| `base-image` | `"noble"` | Ubuntu base for the container image | +| `browsers` | `'["chromium", "firefox", "webkit"]'` | JSON array of browsers to test | +| `sync-command` | `"uv sync"` | Dependency install command | +| `test-command` | *(required)* | Pytest command template -- use `$BROWSER` placeholder | +| `test-directory` | `"."` | Working directory for all commands | +| `artifact-retention-days` | `7` | How long to keep trace artifacts | +| `fail-fast` | `false` | Stop on first browser failure | + +**Example:** + +```yaml +name: E2E + +on: + pull_request: + push: + branches: [main] + +concurrency: + group: e2e-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + e2e: + uses: codeflash-ai/github-workflows/.github/workflows/ci-e2e-playwright.yml@main + with: + playwright-version: "v1.59.0" + test-command: "uv run pytest tests/e2e/ --browser $BROWSER -v --tracing on" + test-directory: "." + fail-fast: false +``` + --- ## Adding a new workflow