---
phase: 14-ducklake-integration-test-refresh-and-ci-job
plan: "03"
type: execute
wave: 2
depends_on: ["14-01"]
files_modified:
  - .github/workflows/PullRequestCI.yml
  - .github/workflows/DuckDBVersionMonitor.yml
  - Justfile
autonomous: true
requirements: [DUCKLAKE-CI, DUCKLAKE-MONITOR]

must_haves:
  truths:
    - "PullRequestCI.yml has a second job ducklake-ci-check that runs in parallel with linux-fast-check (no needs: dependency)"
    - "ducklake-ci-check job installs Rust, builds with cargo build --features extension, installs uv, runs test_ducklake_ci.py"
    - "DuckDBVersionMonitor.yml runs the DuckLake CI test after the existing build+test step with continue-on-error: true"
    - "Version monitor PR bodies include DuckLake pass/fail result"
    - "Justfile has test-ducklake-ci target that runs test_ducklake_ci.py"
  artifacts:
    - path: ".github/workflows/PullRequestCI.yml"
      provides: "Parallel ducklake-ci-check job"
      contains: "ducklake-ci-check"
    - path: ".github/workflows/DuckDBVersionMonitor.yml"
      provides: "DuckLake compatibility step in version monitor"
      contains: "ducklake_test"
    - path: "Justfile"
      provides: "test-ducklake-ci target"
      contains: "test-ducklake-ci"
  key_links:
    - from: ".github/workflows/PullRequestCI.yml"
      to: "test/integration/test_ducklake_ci.py"
      via: "uv run test/integration/test_ducklake_ci.py"
      pattern: "test_ducklake_ci"
    - from: ".github/workflows/DuckDBVersionMonitor.yml"
      to: "test/integration/test_ducklake_ci.py"
      via: "uv run test/integration/test_ducklake_ci.py"
      pattern: "test_ducklake_ci"
---

<objective>
Wire the CI job into PullRequestCI.yml, add the DuckLake step to DuckDBVersionMonitor.yml, and add the Justfile target.

Purpose: The CI test exists after Plan 01 — this plan connects it to the CI system so it runs automatically on PRs and during DuckDB version monitoring.
Output: Parallel CI job in PullRequestCI.yml, DuckLake step in DuckDBVersionMonitor.yml, test-ducklake-ci Justfile target.
</objective>

<execution_context>
@/Users/paul/.claude/get-shit-done/workflows/execute-plan.md
@/Users/paul/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/phases/14-ducklake-integration-test-refresh-and-ci-job/14-CONTEXT.md
@.planning/phases/14-ducklake-integration-test-refresh-and-ci-job/14-RESEARCH.md
@.github/workflows/PullRequestCI.yml
@.github/workflows/DuckDBVersionMonitor.yml
@Justfile
</context>

<tasks>

<task type="auto">
  <name>Task 1: Add ducklake-ci-check parallel job to PullRequestCI.yml</name>
  <files>.github/workflows/PullRequestCI.yml</files>
  <action>
Read `.github/workflows/PullRequestCI.yml`. Add a second job `ducklake-ci-check` after the existing `linux-fast-check` job.

The new job must:
- Have NO `needs:` field — it runs in parallel with `linux-fast-check`
- Run on `ubuntu-latest`
- Build the extension with `cargo build --features extension` (not CMake)
- Install Python's uv via `pip install uv`
- Run `uv run test/integration/test_ducklake_ci.py`
- Set `SEMANTIC_VIEWS_EXTENSION_PATH` env var to `target/debug/semantic_views.duckdb_extension`

Add this job to the `jobs:` section:

```yaml
  ducklake-ci-check:
    name: DuckLake integration test (Linux x86_64)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust stable
        uses: dtolnay/rust-toolchain@stable

      - name: Build extension
        run: cargo build --features extension

      - name: Install uv
        run: pip install uv

      - name: Run DuckLake CI integration test
        run: uv run test/integration/test_ducklake_ci.py
        env:
          SEMANTIC_VIEWS_EXTENSION_PATH: target/debug/semantic_views.duckdb_extension
```

Important: The indentation must match the YAML structure. The job is a peer of `linux-fast-check` under `jobs:`.
  </action>
  <verify>
    <automated>python3 -c "import yaml; d = yaml.safe_load(open('.github/workflows/PullRequestCI.yml')); assert 'ducklake-ci-check' in d['jobs'], 'job missing'; j = d['jobs']['ducklake-ci-check']; assert 'needs' not in j, 'needs should not be present'; print('PullRequestCI.yml OK')" 2>/dev/null || python3 -c "import sys; content = open('.github/workflows/PullRequestCI.yml').read(); assert 'ducklake-ci-check' in content; assert 'SEMANTIC_VIEWS_EXTENSION_PATH' in content; assert 'test_ducklake_ci' in content; print('PullRequestCI.yml OK')"</automated>
  </verify>
  <done>PullRequestCI.yml has ducklake-ci-check job with no needs: field, cargo build --features extension step, uv run step with SEMANTIC_VIEWS_EXTENSION_PATH env var.</done>
</task>

<task type="auto">
  <name>Task 2: Add DuckLake step to DuckDBVersionMonitor.yml and update PR body templates</name>
  <files>.github/workflows/DuckDBVersionMonitor.yml</files>
  <action>
Read `.github/workflows/DuckDBVersionMonitor.yml`. Make two changes:

**Change 1: Add DuckLake test step after the build+test step.**

The existing step is:
```yaml
      - name: Build and test against new DuckDB version
        if: steps.latest.outputs.is_new == 'true'
        id: build
        run: make configure && make test_release
        continue-on-error: true
```

Add a NEW step immediately after it (before the PR creation steps):
```yaml
      - name: Run DuckLake integration test
        if: steps.latest.outputs.is_new == 'true'
        id: ducklake_test
        run: |
          pip install uv
          SEMANTIC_VIEWS_EXTENSION_PATH=build/release/semantic_views.duckdb_extension \
            uv run test/integration/test_ducklake_ci.py
        continue-on-error: true
```

Note: The version monitor uses `make configure && make test_release` which is a CMake/Makefile build — the release extension ends up in `build/release/`, not `target/release/`. Use `build/release/semantic_views.duckdb_extension` as the path.

**Change 2: Update both PR body templates to include DuckLake result.**

In the "Open version-bump PR (build passed)" step body, add a DuckLake line:
```yaml
            body: |
              Automated version bump to DuckDB ${{ steps.latest.outputs.latest }}.

              Build and tests passed on Linux x86_64. The full platform matrix will run once this PR merges to `main`.

              DuckLake compatibility: ${{ steps.ducklake_test.outcome == 'success' && '✓ passed' || '✗ failed (see run log)' }}

              ---
              *Generated by DuckDB Version Monitor workflow.*
```

In the "Open breakage PR (build failed)" step body, add a DuckLake line:
```yaml
            body: |
              Build against DuckDB ${{ steps.latest.outputs.latest }} failed.

              @copilot please update the DuckDB version pin and fix any compilation errors.

              DuckLake compatibility: ${{ steps.ducklake_test.outcome == 'success' && '✓ passed' || '✗ failed or skipped' }}

              Build log: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

              ---
              *Generated by DuckDB Version Monitor workflow.*
```

Note: `steps.ducklake_test.outcome` will be `'success'`, `'failure'`, or `'skipped'` depending on whether the step ran and passed. The `continue-on-error: true` means the job continues even if ducklake_test fails — the outcome is still `'failure'`.
  </action>
  <verify>
    <automated>python3 -c "content = open('.github/workflows/DuckDBVersionMonitor.yml').read(); assert 'ducklake_test' in content; assert 'continue-on-error' in content; assert 'test_ducklake_ci' in content; assert 'DuckLake compatibility' in content; print('DuckDBVersionMonitor.yml OK')"</automated>
  </verify>
  <done>DuckDBVersionMonitor.yml has ducklake_test step with continue-on-error: true, running after build step. Both PR body templates include DuckLake compatibility result line.</done>
</task>

<task type="auto">
  <name>Task 3: Add test-ducklake-ci target to Justfile</name>
  <files>Justfile</files>
  <action>
Read `Justfile`. Find the existing `test-iceberg` target:
```
test-iceberg: build
    uv run test/integration/test_ducklake.py
```

Add a new `test-ducklake-ci` target immediately after `test-iceberg`:
```
# Run DuckLake CI integration test (uses inline synthetic data, no setup required)
test-ducklake-ci:
    uv run test/integration/test_ducklake_ci.py
```

Note: `test-ducklake-ci` has NO `build` prerequisite because in CI it's triggered after a separate `cargo build` step. Locally, users can call it after building manually. This matches the pattern for the CI job where build is a separate step.

Also, update the `test-all` target comment if it mentions the iceberg setup requirement — optionally add `test-ducklake-ci` to `test-all` if it makes sense. The current `test-all` is:
```
# Run all tests: Rust unit tests + SQL logic tests + DuckLake integration
# Note: DuckLake test requires `just setup-ducklake` to have been run first.
test-all: test-rust test-sql test-iceberg
```

Update to:
```
# Run all tests: Rust unit tests + SQL logic tests + DuckLake integration
# Note: test-iceberg requires `just setup-ducklake` first. test-ducklake-ci uses synthetic data.
test-all: test-rust test-sql test-iceberg test-ducklake-ci
```
  </action>
  <verify>
    <automated>python3 -c "content = open('Justfile').read(); assert 'test-ducklake-ci' in content; assert 'test_ducklake_ci.py' in content; print('Justfile OK')"</automated>
  </verify>
  <done>Justfile has test-ducklake-ci target running test_ducklake_ci.py. test-all updated to include test-ducklake-ci.</done>
</task>

</tasks>

<verification>
- `grep -n "ducklake-ci-check" .github/workflows/PullRequestCI.yml` returns the job name
- `grep -n "needs:" .github/workflows/PullRequestCI.yml` does NOT include ducklake-ci-check
- `grep -n "ducklake_test" .github/workflows/DuckDBVersionMonitor.yml` returns the step id
- `grep -n "continue-on-error" .github/workflows/DuckDBVersionMonitor.yml` returns the ducklake_test step
- `grep -n "DuckLake compatibility" .github/workflows/DuckDBVersionMonitor.yml` returns hits in both PR body templates
- `grep -n "test-ducklake-ci" Justfile` returns the target definition and test-all reference
</verification>

<success_criteria>
Three files updated. PR CI now has a parallel DuckLake check job. Version monitor includes DuckLake pass/fail in PR descriptions. Justfile exposes local test-ducklake-ci target. All changes follow the patterns established in the existing CI files.
</success_criteria>

<output>
After completion, create `.planning/phases/14-ducklake-integration-test-refresh-and-ci-job/14-03-SUMMARY.md`
</output>
