mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
6b98d489f8
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
202 lines
8.8 KiB
YAML
202 lines
8.8 KiB
YAML
name: Agent Image Smoke (Playwright)
|
|
|
|
# Builds the two images that carry Playwright + chromium-headless-shell
|
|
# (agent-qa-fe, agent-ux) with a real Docker daemon, verifies a headless
|
|
# chromium launch actually works inside each, verifies the `playwright` MCP
|
|
# server (registered for fe-qa/ux-qa only, see orchestrator.py
|
|
# _generate_mcp_config) is installed and wired to the baked browser, takes a
|
|
# real headless screenshot of a live panel page from inside the ux-qa image,
|
|
# and reports the real before/after image size delta against origin/master.
|
|
# This exists because dev/QA agent sandboxes have no Docker daemon of their
|
|
# own — this workflow is the only place that can produce non-estimated
|
|
# numbers for this change.
|
|
|
|
on:
|
|
push:
|
|
paths:
|
|
- 'docker/agent-base.Dockerfile'
|
|
- 'docker/agent-qa-fe.Dockerfile'
|
|
- 'docker/agent-ux.Dockerfile'
|
|
- 'docker/scripts/playwright-mcp-entrypoint.sh'
|
|
- '.github/workflows/agent-image-smoke.yml'
|
|
pull_request:
|
|
# No `branches:` filter — this repo's task hierarchy opens dev-level
|
|
# PRs against nested parent feature branches (e.g.
|
|
# feature/backend/<root>--<cell>--<subcell>), not directly against
|
|
# master, so a `branches: [master]` filter here would only ever fire
|
|
# once the assembled PR reaches root->master — too late to give QA/PM
|
|
# real evidence at the dev-PR review stage this task exists for.
|
|
paths:
|
|
- 'docker/agent-base.Dockerfile'
|
|
- 'docker/agent-qa-fe.Dockerfile'
|
|
- 'docker/agent-ux.Dockerfile'
|
|
- 'docker/scripts/playwright-mcp-entrypoint.sh'
|
|
- '.github/workflows/agent-image-smoke.yml'
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
playwright-smoke:
|
|
name: Build QA images, verify headless chromium launch + size delta
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
pull-requests: write
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v7
|
|
with:
|
|
# Need origin/master reachable to diff this branch's Dockerfiles
|
|
# against the pre-change baseline for the size-delta report below.
|
|
fetch-depth: 0
|
|
|
|
- name: Build agent-base (shared FROM target for both variants)
|
|
run: docker build -f docker/agent-base.Dockerfile -t roboco-agent-base .
|
|
|
|
- name: Build "after" images (this branch)
|
|
run: |
|
|
docker build -f docker/agent-qa-fe.Dockerfile -t agent-qa-fe:after .
|
|
docker build -f docker/agent-ux.Dockerfile -t agent-ux:after .
|
|
|
|
- name: Build "before" images (origin/master baseline)
|
|
run: |
|
|
mkdir -p /tmp/before
|
|
git show origin/master:docker/agent-qa-fe.Dockerfile > /tmp/before/agent-qa-fe.Dockerfile
|
|
git show origin/master:docker/agent-ux.Dockerfile > /tmp/before/agent-ux.Dockerfile
|
|
docker build -f /tmp/before/agent-qa-fe.Dockerfile -t agent-qa-fe:before .
|
|
docker build -f /tmp/before/agent-ux.Dockerfile -t agent-ux:before .
|
|
|
|
- name: Report real before/after image size delta
|
|
run: |
|
|
{
|
|
echo "### Playwright image size delta (real \`docker inspect\` sizes)"
|
|
echo
|
|
echo "| image | before | after | delta |"
|
|
echo "|---|---|---|---|"
|
|
for name in agent-qa-fe agent-ux; do
|
|
before_bytes=$(docker inspect -f '{{.Size}}' "${name}:before")
|
|
after_bytes=$(docker inspect -f '{{.Size}}' "${name}:after")
|
|
delta_mb=$(( (after_bytes - before_bytes) / 1024 / 1024 ))
|
|
echo "| ${name} | $(( before_bytes / 1024 / 1024 ))MB | $(( after_bytes / 1024 / 1024 ))MB | +${delta_mb}MB |"
|
|
done
|
|
} | tee -a "$GITHUB_STEP_SUMMARY" /tmp/smoke-report.md
|
|
|
|
- name: Headless chromium launch smoke check
|
|
run: |
|
|
{
|
|
echo
|
|
echo "### Headless chromium launch smoke check"
|
|
echo
|
|
} | tee -a /tmp/smoke-report.md
|
|
for name in agent-qa-fe agent-ux; do
|
|
echo "::group::${name} headless launch smoke"
|
|
docker run --rm --entrypoint /app/.venv/bin/python "${name}:after" -c '
|
|
from playwright.sync_api import sync_playwright
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch()
|
|
page = browser.new_page()
|
|
page.goto("about:blank")
|
|
assert page.title() == ""
|
|
browser.close()
|
|
print("PLAYWRIGHT_SMOKE_OK")
|
|
' | tee -a /tmp/smoke-report.md
|
|
echo "::endgroup::"
|
|
done
|
|
|
|
- name: Playwright MCP server smoke check (binary + baked-chromium wiring)
|
|
run: |
|
|
{
|
|
echo
|
|
echo "### Playwright MCP server smoke check"
|
|
echo
|
|
} | tee -a /tmp/smoke-report.md
|
|
for name in agent-qa-fe agent-ux; do
|
|
echo "::group::${name} playwright-mcp binary"
|
|
docker run --rm --entrypoint playwright-mcp "${name}:after" --version | tee -a /tmp/smoke-report.md
|
|
# Confirms the exact chromium-headless-shell path the wrapper
|
|
# entrypoint (docker/scripts/playwright-mcp-entrypoint.sh) will
|
|
# resolve and pass to `playwright-mcp --executable-path` is a
|
|
# real, executable file baked into this image — not a second,
|
|
# separately-downloaded browser.
|
|
docker run --rm --entrypoint /app/.venv/bin/python "${name}:after" -c '
|
|
import os
|
|
from playwright.sync_api import sync_playwright
|
|
with sync_playwright() as p:
|
|
path = p.chromium.executable_path
|
|
assert os.path.isfile(path) and os.access(path, os.X_OK), f"not executable: {path}"
|
|
print("RESOLVED_CHROMIUM_PATH_OK:", path)
|
|
' | tee -a /tmp/smoke-report.md
|
|
echo "::endgroup::"
|
|
done
|
|
|
|
- name: Set up Node (for the panel screenshot step below)
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: '22'
|
|
|
|
- name: Enable corepack (pnpm)
|
|
run: corepack enable
|
|
|
|
- name: Build & start the panel (headless browser verification target)
|
|
working-directory: panel
|
|
env:
|
|
# pnpm 11 prompts for confirmation on modules-purge unless CI=true
|
|
# (matches docker/panel.Dockerfile's build stage).
|
|
CI: 'true'
|
|
run: |
|
|
pnpm install --frozen-lockfile --shamefully-hoist
|
|
pnpm build
|
|
nohup pnpm start -p 3000 > /tmp/panel.log 2>&1 &
|
|
npx --yes wait-on http://localhost:3000/login -t 60000
|
|
|
|
- name: Headless browser verification screenshot (ux-qa image)
|
|
# Demonstrates the ux-qa image's browser actually renders a live
|
|
# panel page end-to-end, not just about:blank. /login needs no
|
|
# backend/auth (proxy.ts excludes it from its matcher) so this has
|
|
# no dependency on the orchestrator/DB being up.
|
|
run: |
|
|
mkdir -p /tmp/pw-artifacts
|
|
chmod 777 /tmp/pw-artifacts
|
|
docker run --rm --add-host=host.docker.internal:host-gateway \
|
|
-v /tmp/pw-artifacts:/tmp/out \
|
|
--entrypoint /app/.venv/bin/python agent-ux:after -c '
|
|
from playwright.sync_api import sync_playwright
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch()
|
|
page = browser.new_page(viewport={"width": 1280, "height": 800})
|
|
page.goto("http://host.docker.internal:3000/login", wait_until="networkidle")
|
|
page.screenshot(path="/tmp/out/ux-qa-panel-login.png")
|
|
browser.close()
|
|
print("PANEL_SCREENSHOT_OK")
|
|
'
|
|
{
|
|
echo
|
|
echo "### Headless browser verification screenshot (ux-qa image)"
|
|
echo
|
|
echo "Screenshot of a live panel page (\`/login\`), taken from inside \`agent-ux:after\`. See the \`ux-qa-panel-screenshot\` build artifact."
|
|
} | tee -a /tmp/smoke-report.md
|
|
|
|
- name: Upload panel screenshot artifact
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: ux-qa-panel-screenshot
|
|
path: /tmp/pw-artifacts/ux-qa-panel-login.png
|
|
|
|
- name: Post results as a PR comment
|
|
# always() so the PR comment (the only evidence-delivery path QA/PM
|
|
# has, since no agent role can read the Checks tab directly) still
|
|
# posts a partial report even if an earlier build/smoke step failed —
|
|
# an `if:` that doesn't call a status function is otherwise
|
|
# implicitly ANDed with success(), silently swallowing the report.
|
|
if: always() && github.event_name == 'pull_request'
|
|
uses: actions/github-script@v9
|
|
with:
|
|
script: |
|
|
const fs = require('fs');
|
|
const body = fs.readFileSync('/tmp/smoke-report.md', 'utf8');
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
body: `## Agent Image Smoke (Playwright) results\n\n${body}`,
|
|
});
|