Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 43 additions & 23 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,47 @@ This directory contains CI/CD workflows for the DeepWork project. We use GitHub'

## Merge Queue Strategy

All workflows explicitly target the `main` branch for both `pull_request` and `merge_group` triggers to ensure proper execution in the merge queue.

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) |
| Workflow | On PRs | In Merge Queue | Manual Trigger |
|----------|--------|----------------|----------------|
| **Validate** | Runs | Runs | Runs |
| **Integration Tests** | Skipped (passes) | Runs | Runs |
| **E2E Tests** | Skipped (passes) | Runs | Runs |
| **CLA Check** | Runs | Skipped (passes) | Skipped (passes) |

### How It Works

All workflows specify explicit branch targeting:

```yaml
on:
pull_request:
branches: [main]
merge_group:
branches: [main]
workflow_dispatch: # Enables manual triggering for testing
```

Jobs/steps use `if: github.event_name == 'merge_group'` conditions to control execution:

```yaml
# Job that only runs in merge queue (skipped on PRs)
# Job that only runs in merge queue and manual dispatch (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'
# Job that skips in merge queue and manual dispatch (runs on PRs only)
jobs:
cla-check:
if: github.event_name != 'merge_group' && github.event_name != 'workflow_dispatch'
...
```

When a job/step is skipped due to an `if` condition, GitHub treats it as a successful check. This allows:
When a job 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
Expand All @@ -50,31 +63,38 @@ When a job/step is skipped due to an `if` condition, GitHub treats it as a succe

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`
- `Claude Code Integration Test / pr-check` (for PRs)
- `Claude Code Integration Test / validate-generation` (for merge queue)
- `Claude Code Integration Test / claude-code-e2e` (for merge queue)
- `CLA Assistant / merge-queue-pass` (for merge queue)
- `CLA Assistant / cla-check` (for PRs)

All checks will pass in both PR and merge queue contexts (either by running or by being skipped).

**Note**: The explicit branch targeting in `merge_group` triggers is critical for workflows to run properly in the merge queue. Without this, GitHub may not trigger the workflows and they will remain in "expected" state.

## Workflow Details

### validate.yml
- **Triggers**: `pull_request`, `merge_group`
- **Triggers**: `pull_request` (main), `merge_group` (main), `workflow_dispatch`
- **Jobs**: `tests` - runs ruff format/lint checks and pytest unit tests
- Runs on every PR and in merge queue
- Runs on every PR, in merge queue, and can be manually triggered

### claude-code-test.yml
- **Triggers**: `pull_request`, `merge_group`, `workflow_dispatch`
- **Triggers**: `pull_request` (main), `merge_group` (main), `workflow_dispatch`
- **Jobs**:
- `pr-check`: Runs on PRs only, always passes (lightweight check)
- `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
- `validate-generation` and `claude-code-e2e` 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)
- **Triggers**: `pull_request_target`, `issue_comment`, `merge_group` (main), `workflow_dispatch`
- **Jobs**:
- `merge-queue-pass`: Runs on merge queue and manual dispatch, always passes
- `cla-check`: Verifies contributors have signed the CLA
- `cla-check` runs on PRs, skips in merge queue and manual dispatch (CLA already verified)

### release.yml
- **Triggers**: Tags matching `v*`
- **Triggers**: `release` (published)
- **Jobs**: Builds and publishes to PyPI
14 changes: 13 additions & 1 deletion .github/workflows/cla.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ on:
types: [created]
pull_request_target:
types: [opened, synchronize]
branches: [main]
# Run in merge queue but skip the step (shows as passing check)
merge_group:
branches: [main]
workflow_dispatch:

# Explicitly set permissions for the workflow
permissions:
Expand All @@ -16,11 +19,20 @@ permissions:
statuses: write

jobs:
# Job for merge queue - always passes since CLA is checked at PR time
merge-queue-pass:
runs-on: ubuntu-latest
if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch'
steps:
- name: CLA already verified at PR time
run: echo "CLA check is performed on PRs, not in merge queue. Passing."

cla-check:
runs-on: ubuntu-latest
if: github.event_name != 'merge_group' && github.event_name != 'workflow_dispatch'
steps:
- name: "CLA Assistant"
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')
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'
uses: contributor-assistant/github-action@v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
16 changes: 15 additions & 1 deletion .github/workflows/claude-code-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,31 @@ on:
type: boolean
# Run on all PRs (shows as check, but steps skip unless in merge queue)
pull_request:
branches: [main]
# Run in the merge queue to validate before merging
merge_group:
branches: [main]

# Ensure only one instance runs at a time per PR/branch
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true

# Minimal permissions for this workflow
permissions:
contents: read

jobs:
# Job for PRs - always passes, actual validation happens in merge queue
pr-check:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: PR Check
run: echo "Claude Code integration tests will run in the merge queue"

# 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)
# Runs on merge_group and workflow_dispatch only
validate-generation:
runs-on: ubuntu-latest
if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch'
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ name: Validate

on:
pull_request:
branches: [main]
merge_group:
branches: [main]
workflow_dispatch:

# Minimal permissions for this workflow
permissions:
contents: read

jobs:
tests:
Expand Down
Loading