diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 00000000..c37cf24d --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,80 @@ +# GitHub Actions Workflows + +This directory contains CI/CD workflows for the DeepWork project. We use GitHub's merge queue for efficient testing. + +## Workflow Overview + +| Workflow | File | Purpose | +|----------|------|---------| +| **Validate** | `validate.yml` | Linting (ruff) and unit tests | +| **Integration Tests** | `claude-code-test.yml` | Command generation and e2e tests | +| **CLA Assistant** | `cla.yml` | Contributor License Agreement verification | +| **Release** | `release.yml` | PyPI publishing on tags | + +## Merge Queue Strategy + +We use a skip pattern so the same required checks pass in both PR and merge queue contexts: + +| Workflow | On PRs | In Merge Queue | +|----------|--------|----------------| +| **Validate** | Runs | Runs | +| **Integration Tests** | Skipped (passes) | Runs | +| **E2E Tests** | Skipped (passes) | Runs | +| **CLA Check** | Runs | Skipped (passes) | + +### How It Works + +Jobs/steps use `if: github.event_name == 'merge_group'` conditions to control execution: + +```yaml +# Job that only runs in merge queue (skipped on PRs) +jobs: + expensive-tests: + if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' + ... + +# Step that skips in merge queue (runs on PRs only) +steps: + - name: CLA Check + if: github.event_name != 'merge_group' + ... +``` + +When a job/step is skipped due to an `if` condition, GitHub treats it as a successful check. This allows: + +- **Fast PR feedback**: Only lint + unit tests run on every push +- **Thorough merge validation**: Expensive integration/e2e tests run in merge queue before merging +- **No duplicate CLA checks**: CLA is verified on PRs; no need to re-check in merge queue + +### Required Checks Configuration + +In GitHub branch protection rules, require these checks: +- `Validate / tests` +- `Claude Code Integration Test / validate-generation` +- `Claude Code Integration Test / claude-code-e2e` +- `CLA Assistant / cla-check` + +All checks will pass in both PR and merge queue contexts (either by running or by being skipped). + +## Workflow Details + +### validate.yml +- **Triggers**: `pull_request`, `merge_group` +- **Jobs**: `tests` - runs ruff format/lint checks and pytest unit tests +- Runs on every PR and in merge queue + +### claude-code-test.yml +- **Triggers**: `pull_request`, `merge_group`, `workflow_dispatch` +- **Jobs**: + - `validate-generation`: Tests command generation from fixtures (no API key needed) + - `claude-code-e2e`: Full end-to-end test with Claude Code CLI (requires `ANTHROPIC_API_KEY`) +- Both jobs skip on PRs, run in merge queue and manual dispatch + +### cla.yml +- **Triggers**: `pull_request_target`, `issue_comment`, `merge_group` +- **Jobs**: `cla-check` - verifies contributors have signed the CLA +- Runs on PRs, skips in merge queue (CLA already verified) + +### release.yml +- **Triggers**: Tags matching `v*` +- **Jobs**: Builds and publishes to PyPI diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index ba8f9e48..118f7e8b 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -5,6 +5,8 @@ on: types: [created] pull_request_target: types: [opened, synchronize] + # Run in merge queue but skip the step (shows as passing check) + merge_group: # Explicitly set permissions for the workflow permissions: @@ -18,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "CLA Assistant" - if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' + if: github.event_name != 'merge_group' && ((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target') uses: contributor-assistant/github-action@v2.6.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/claude-code-test.yml b/.github/workflows/claude-code-test.yml index 502d4338..84e888d0 100644 --- a/.github/workflows/claude-code-test.yml +++ b/.github/workflows/claude-code-test.yml @@ -9,6 +9,8 @@ on: required: false default: 'false' type: boolean + # Run on all PRs (shows as check, but steps skip unless in merge queue) + pull_request: # Run in the merge queue to validate before merging merge_group: @@ -18,9 +20,11 @@ concurrency: cancel-in-progress: true jobs: - # Job 1: Validate command generation from fixtures (always runs, no API key needed) + # Job 1: Validate command generation from fixtures (no API key needed) + # Runs on merge_group and workflow_dispatch, skipped on PRs (shows as passing check) validate-generation: runs-on: ubuntu-latest + if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' steps: - uses: actions/checkout@v4 @@ -80,10 +84,11 @@ jobs: # Job 2: Full end-to-end test with Claude Code # Tests the COMPLETE workflow: define job -> implement -> execute + # Runs on merge_group and workflow_dispatch, skipped on PRs (shows as passing check) claude-code-e2e: runs-on: ubuntu-latest needs: validate-generation - if: github.event_name == 'workflow_dispatch' || github.event_name == 'merge_group' + if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} steps: