From 4b218e7172251c2247b96b1ea9fcc776edd98622 Mon Sep 17 00:00:00 2001 From: leaf-agent <318509791+leaf-agent@users.noreply.github.com> Date: Sat, 29 Aug 2026 08:00:52 +0000 Subject: [PATCH] Seed the Playwright browser into the tend sandbox so a session can run the suite --- .claude/skills/running-tend/SKILL.md | 10 ++++++++++ .config/tend.yaml | 16 ++++++++++++++++ .github/workflows/tend-ci-fix.yaml | 3 +++ .github/workflows/tend-mention.yaml | 3 +++ .github/workflows/tend-nightly.yaml | 3 +++ .github/workflows/tend-notifications.yaml | 3 +++ .github/workflows/tend-review-runs.yaml | 3 +++ .github/workflows/tend-review.yaml | 3 +++ .github/workflows/tend-triage.yaml | 3 +++ .github/workflows/tend-weekly.yaml | 3 +++ 10 files changed, 50 insertions(+) diff --git a/.claude/skills/running-tend/SKILL.md b/.claude/skills/running-tend/SKILL.md index d4e7dffd7..b1dd254be 100644 --- a/.claude/skills/running-tend/SKILL.md +++ b/.claude/skills/running-tend/SKILL.md @@ -39,6 +39,16 @@ for the rows. Ignore it. A comment can record recovery, but the drain owns the close. This applies by title, not by the `tend-outage` label: `ci-fix` diagnosis trackers have no rows and are closed by `ci-fix` itself. +## The browser the suite needs is already here + +`.config/tend.yaml`'s `sandbox_setup:` installs the Playwright headless shell +into this sandbox's own cache before the session starts, so `uv run pytest tests +--run-nightly` drives a real browser from here. Don't install it again, and +don't read a browser test as unrunnable — if a launch does fail, that is a fact +about the run worth reporting, not a step to work around. `playwright install +--with-deps` is the one that cannot work: it escalates, and the sandbox user has +no sudo. + ## A red `ci` on main is the first signal, not the second Nothing lands here through a pull request, so no CI run ever gates a change diff --git a/.config/tend.yaml b/.config/tend.yaml index 957b88a04..3283f44d0 100644 --- a/.config/tend.yaml +++ b/.config/tend.yaml @@ -11,6 +11,22 @@ setup: - uses: astral-sh/setup-uv@v7 - run: uv sync --frozen +# `setup:` runs as the runner, and Playwright downloads browsers under the +# home of whoever runs it — a home the sandbox does not inherit. So the agent +# meets `BrowserType.launch: Executable doesn't exist` partway through the +# suite, which is most of it: nearly every test here drives a real browser +# (`tests/CLAUDE.md`). Seeding it under the sandbox's own home is what makes +# the repo's gate runnable from a session rather than only in `ci`. +# +# Same browser `ci.yaml` installs, and no `--with-deps`: the sandbox user has +# no sudo, so that flag fails on `sudo: a password is required` — the runner +# image already carries the system libraries. The launch afterwards is the +# assertion the install worked, so a broken one stops the job instead of +# reaching the agent as a suite that cannot start. +sandbox_setup: + - uv run playwright install chromium --only-shell + - 'uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()"' + workflows: ci-fix: watched_workflows: diff --git a/.github/workflows/tend-ci-fix.yaml b/.github/workflows/tend-ci-fix.yaml index 5afa3df40..f3b3f94e8 100644 --- a/.github/workflows/tend-ci-fix.yaml +++ b/.github/workflows/tend-ci-fix.yaml @@ -42,6 +42,9 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: | /tend-ci-runner:ci-fix ${{ github.event.workflow_run.id }} - Run URL: ${{ github.event.workflow_run.html_url }} diff --git a/.github/workflows/tend-mention.yaml b/.github/workflows/tend-mention.yaml index 2f9060b15..b63a00dab 100644 --- a/.github/workflows/tend-mention.yaml +++ b/.github/workflows/tend-mention.yaml @@ -428,6 +428,9 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: >- ${{ steps.delay.outputs.seconds && format('This job started {0}s after the triggering event (over ~40s means it was queued). ', diff --git a/.github/workflows/tend-nightly.yaml b/.github/workflows/tend-nightly.yaml index 130ed6c35..007207915 100644 --- a/.github/workflows/tend-nightly.yaml +++ b/.github/workflows/tend-nightly.yaml @@ -42,5 +42,8 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: | /tend-ci-runner:nightly diff --git a/.github/workflows/tend-notifications.yaml b/.github/workflows/tend-notifications.yaml index a814f0ff2..da76498d0 100644 --- a/.github/workflows/tend-notifications.yaml +++ b/.github/workflows/tend-notifications.yaml @@ -158,5 +158,8 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: | /tend-ci-runner:notifications diff --git a/.github/workflows/tend-review-runs.yaml b/.github/workflows/tend-review-runs.yaml index a30a34b40..da7adb531 100644 --- a/.github/workflows/tend-review-runs.yaml +++ b/.github/workflows/tend-review-runs.yaml @@ -42,5 +42,8 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: | /tend-ci-runner:review-runs diff --git a/.github/workflows/tend-review.yaml b/.github/workflows/tend-review.yaml index 13417a92e..3075e3665 100644 --- a/.github/workflows/tend-review.yaml +++ b/.github/workflows/tend-review.yaml @@ -158,6 +158,9 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: >- ${{ format('/tend-ci-runner:review {0}', github.event.pull_request.number) }} diff --git a/.github/workflows/tend-triage.yaml b/.github/workflows/tend-triage.yaml index 91e8a4f74..136dfc776 100644 --- a/.github/workflows/tend-triage.yaml +++ b/.github/workflows/tend-triage.yaml @@ -54,6 +54,9 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: | /tend-ci-runner:triage ${{ github.event.issue.number }} diff --git a/.github/workflows/tend-weekly.yaml b/.github/workflows/tend-weekly.yaml index d5636429a..425bb263b 100644 --- a/.github/workflows/tend-weekly.yaml +++ b/.github/workflows/tend-weekly.yaml @@ -42,5 +42,8 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} bot_name: leaf-agent model: opus + sandbox_setup: | + uv run playwright install chromium --only-shell + uv run python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch().close(); p.stop()" prompt: | /tend-ci-runner:weekly