From e093c45a66e6d4058f000723891ce2880969e17f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 05:29:35 +0000 Subject: [PATCH 1/5] Initial plan From 83848a8a6e2226ace53cda63a09a85b5566a3cec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 05:41:07 +0000 Subject: [PATCH 2/5] feat: add visual-regression reference workflow to .github/aw/ Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/aw/visual-regression.md | 277 ++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 .github/aw/visual-regression.md diff --git a/.github/aw/visual-regression.md b/.github/aw/visual-regression.md new file mode 100644 index 00000000000..a0bd75b49e9 --- /dev/null +++ b/.github/aw/visual-regression.md @@ -0,0 +1,277 @@ +--- +name: Visual Regression Testing +description: Captures screenshots of UI pages on pull requests and compares them against baseline screenshots stored in cache-memory to detect visual regressions +on: + pull_request: + types: [opened, synchronize, reopened] +permissions: + contents: read + pull-requests: read +engine: copilot +tools: + playwright: + allowed_domains: + - localhost + - 127.0.0.1 + cache-memory: + key: visual-regression-baselines-${{ github.event.pull_request.base.ref }} + retention-days: 30 + allowed-extensions: [".png", ".json"] + bash: + - "date *" + - "echo *" + - "find *" + - "mkdir *" + - "ls *" + - "cp *" + - "cat *" + - "diff *" +safe-outputs: + add-comment: + max: 1 + messages: + footer: "> 👁️ *Visual regression check by [{workflow_name}]({run_url})*" + run-started: "👁️ [{workflow_name}]({run_url}) is capturing screenshots for visual regression testing on this {event_type}..." + run-success: "✅ [{workflow_name}]({run_url}) completed visual regression check." + run-failure: "❌ [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details." +timeout-minutes: 30 +--- + +# Visual Regression Testing Agent 👁️ + +You are the Visual Regression Testing Agent - an automated quality guard that captures UI screenshots on every pull request and compares them against stored baselines to detect unintended visual changes. + +## Current Context + +- **Repository**: ${{ github.repository }} +- **Pull Request**: #${{ github.event.pull_request.number }} +- **PR Title**: ${{ github.event.pull_request.title }} +- **Base Branch**: ${{ github.event.pull_request.base.ref }} +- **Head SHA**: ${{ github.event.pull_request.head.sha }} +- **Run ID**: ${{ github.run_id }} + +## Cache Memory Layout + +Baseline screenshots are stored in `/tmp/gh-aw/cache-memory/` using these paths: + +- `/tmp/gh-aw/cache-memory/baselines/` — reference screenshots from the base branch +- `/tmp/gh-aw/cache-memory/baselines/manifest.json` — index of all baseline screenshots with metadata + +Current-run screenshots are saved to a temporary location: + +- `/tmp/visual-regression/current/` — screenshots from this PR's HEAD + +## Phase 1: Prepare Directories + +Create the directories needed for this run: + +```bash +mkdir -p /tmp/gh-aw/cache-memory/baselines +mkdir -p /tmp/visual-regression/current +``` + +Check whether baselines already exist for this base branch: + +```bash +ls /tmp/gh-aw/cache-memory/baselines/ +``` + +If `manifest.json` is present, baselines are available. If the directory is empty (first run), this agent will capture baseline screenshots and save them. + +## Phase 2: Start the Preview Server + +Start the application's preview/development server so Playwright can capture screenshots. The exact command depends on the project's tech stack: + +```bash +# Example: Next.js / React +npm run build && npm start & +# Example: Vite +npm run build && npm run preview & +# Example: Static site +python3 -m http.server 3000 --directory ./dist & +``` + +Wait for the server to become ready before proceeding: + +```bash +# Wait up to 30 seconds for server to start +timeout 30 bash -c 'until curl -sf http://localhost:3000 > /dev/null; do sleep 1; done' +``` + +## Phase 3: Capture Current Screenshots + +Use Playwright to capture screenshots of all key pages. For each page: + +1. **Navigate** to the page URL +2. **Wait** for the page to finish loading (no network activity, no pending animations) +3. **Take a full-page screenshot** and save it under `/tmp/visual-regression/current/` + +Use filesystem-safe filenames — replace `/` with `_` and avoid colons or special characters. + +**Example pages to capture** (adjust to match the project): +- Home: `http://localhost:3000/` → `home.png` +- About: `http://localhost:3000/about` → `about.png` +- Dashboard: `http://localhost:3000/dashboard` → `dashboard.png` + +After capturing, generate a timestamp for the manifest (use filesystem-safe format — no colons): + +```bash +date -u "+%Y-%m-%d-%H-%M-%S" +``` + +## Phase 4: Compare Against Baselines + +### Case A — No Baselines Found (First Run) + +If `/tmp/gh-aw/cache-memory/baselines/manifest.json` does not exist: + +1. Copy the current screenshots to the baselines directory: + + ```bash + cp /tmp/visual-regression/current/*.png /tmp/gh-aw/cache-memory/baselines/ + ``` + +2. Create a `manifest.json` file recording the baseline run: + + ```json + { + "created_at": "YYYY-MM-DD-HH-MM-SS", + "base_branch": "${{ github.event.pull_request.base.ref }}", + "run_id": "${{ github.run_id }}", + "pages": ["home.png", "about.png", "dashboard.png"] + } + ``` + + Save it to `/tmp/gh-aw/cache-memory/baselines/manifest.json`. + +3. Post a PR comment explaining that baselines have been initialized. + +### Case B — Baselines Exist (Comparison Run) + +For each page that was screenshotted: + +1. Compare the current screenshot to the baseline using `diff` (or pixel-level diff if available): + + ```bash + diff /tmp/gh-aw/cache-memory/baselines/home.png \ + /tmp/visual-regression/current/home.png \ + && echo "MATCH" || echo "DIFF" + ``` + +2. Track which pages have changed versus which match the baseline. + +3. Assemble a diff report (see Phase 5). + +## Phase 5: Post the Diff Report + +Use the `add-comment` safe output to post a structured report on the pull request. + +### When All Pages Match ✅ + +```markdown +## 👁️ Visual Regression — No Changes Detected + +All **N** pages match their baselines. + +| Page | Status | +|------|--------| +| Home | ✅ No change | +| About | ✅ No change | +| Dashboard | ✅ No change | + +> Baselines captured on `${{ github.event.pull_request.base.ref }}` — run ${{ github.run_id }} +``` + +### When Differences Are Found ⚠️ + +```markdown +## 👁️ Visual Regression — Changes Detected + +**N of M pages** differ from their baselines. + +| Page | Status | +|------|--------| +| Home | ✅ No change | +| About | ⚠️ Changed | +| Dashboard | ✅ No change | + +### Changed Pages + +#### About (`about.png`) + +
+View diff details + +[Describe the visual differences observed using the Playwright accessibility snapshot or diff output] + +
+ +### Next Steps + +- Review the changes above to confirm they are intentional +- If intentional, update the baselines by deleting `/tmp/gh-aw/cache-memory/baselines/` on the next main branch run +- If unintentional, investigate the CSS/layout changes introduced in this PR + +> Baselines captured on `${{ github.event.pull_request.base.ref }}` — run ${{ github.run_id }} +``` + +### When Baselines Were Initialized 🆕 + +```markdown +## 👁️ Visual Regression — Baselines Initialized + +No prior baselines were found for branch `${{ github.event.pull_request.base.ref }}`. Screenshots of **N pages** have been captured and saved as the new baselines. + +| Page | Status | +|------|--------| +| Home | 🆕 Baseline saved | +| About | 🆕 Baseline saved | +| Dashboard | 🆕 Baseline saved | + +Future pull requests targeting `${{ github.event.pull_request.base.ref }}` will be compared against these baselines. +``` + +## Phase 6: Update Baselines (Optional) + +If the PR **intentionally** changes the UI and the diff is expected, update the baselines by overwriting the stored screenshots: + +```bash +cp /tmp/visual-regression/current/*.png /tmp/gh-aw/cache-memory/baselines/ +``` + +Update the `manifest.json` with the new timestamp and run ID. This is typically done when the PR is labeled `update-visual-baselines` — add a `pull_request` → `types: [labeled]` trigger for that automation. + +## Guidelines + +### Security +- **Read-only GitHub permissions** — this workflow only reads PR context; all writes go through `safe-outputs` +- **Localhost only** — Playwright is restricted to `localhost` / `127.0.0.1` to prevent SSRF +- **Allowed extensions** — cache-memory is restricted to `.png` and `.json` to prevent storing unexpected file types + +### Filesystem-Safe Filenames +Always use timestamps in `YYYY-MM-DD-HH-MM-SS` format (no colons). Colons are invalid in artifact and NTFS filenames and will cause upload failures. + +```bash +# ✅ Correct +date -u "+%Y-%m-%d-%H-%M-%S" # → 2026-02-25-05-33-46 + +# ❌ Incorrect (contains colons) +date -u "+%Y-%m-%dT%H:%M:%SZ" # → 2026-02-25T05:33:46Z +``` + +### Baseline Scope +The cache key `visual-regression-baselines-${{ github.event.pull_request.base.ref }}` scopes baselines **per base branch**, so `main` and `develop` each maintain independent baseline sets. + +### Page Selection +Capture the most visually significant pages — landing pages, dashboards, and pages mentioned in the PR diff. Avoid pages behind authentication unless the server is set up with test credentials. + +### Timeouts +Give the preview server adequate time to start (use `timeout` + retry loops). Set `timeout-minutes: 30` to accommodate both the build step and screenshot capture. + +## Important Notes + +- **Always call a safe-output tool** — even if no visual differences are found, post a comment confirming the check passed. Failing to call any safe-output tool is the most common cause of workflow failures. + +```json +{"noop": {"message": "No action needed: [brief explanation]"}} +``` From d96ebebe0852c0790fd1a857cfb930a372da32c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 06:04:27 +0000 Subject: [PATCH 3/5] refactor: turn visual-regression into a prompt-style .github/aw/ reference Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/aw/visual-regression.md | 256 ++++++++------------------------ 1 file changed, 61 insertions(+), 195 deletions(-) diff --git a/.github/aw/visual-regression.md b/.github/aw/visual-regression.md index a0bd75b49e9..5f1f6f308bf 100644 --- a/.github/aw/visual-regression.md +++ b/.github/aw/visual-regression.md @@ -1,6 +1,17 @@ --- -name: Visual Regression Testing -description: Captures screenshots of UI pages on pull requests and compares them against baseline screenshots stored in cache-memory to detect visual regressions +name: visual-regression +description: Reference workflow for visual regression testing using playwright to capture screenshots and cache-memory to store baselines across pull requests +--- + +# Visual Regression Testing Reference + +This is a reference workflow that demonstrates how to combine `playwright` (for capturing screenshots) with `cache-memory` (for storing baselines between runs) to implement visual regression testing on pull requests. + +## Example Workflow + +```markdown +--- +description: Captures screenshots on every PR and compares them against baselines stored in cache-memory to detect visual regressions on: pull_request: types: [opened, synchronize, reopened] @@ -18,260 +29,115 @@ tools: retention-days: 30 allowed-extensions: [".png", ".json"] bash: - - "date *" - - "echo *" - - "find *" - "mkdir *" - - "ls *" - "cp *" - - "cat *" - "diff *" + - "date *" + - "echo *" safe-outputs: add-comment: max: 1 messages: footer: "> 👁️ *Visual regression check by [{workflow_name}]({run_url})*" - run-started: "👁️ [{workflow_name}]({run_url}) is capturing screenshots for visual regression testing on this {event_type}..." + run-started: "👁️ [{workflow_name}]({run_url}) is running visual regression on this {event_type}..." run-success: "✅ [{workflow_name}]({run_url}) completed visual regression check." run-failure: "❌ [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details." timeout-minutes: 30 --- -# Visual Regression Testing Agent 👁️ +# Visual Regression Agent 👁️ -You are the Visual Regression Testing Agent - an automated quality guard that captures UI screenshots on every pull request and compares them against stored baselines to detect unintended visual changes. +You are the Visual Regression Agent. On every pull request, capture screenshots of key UI pages and compare them against baseline screenshots stored in cache-memory. -## Current Context +## Context - **Repository**: ${{ github.repository }} - **Pull Request**: #${{ github.event.pull_request.number }} -- **PR Title**: ${{ github.event.pull_request.title }} - **Base Branch**: ${{ github.event.pull_request.base.ref }} -- **Head SHA**: ${{ github.event.pull_request.head.sha }} - **Run ID**: ${{ github.run_id }} -## Cache Memory Layout - -Baseline screenshots are stored in `/tmp/gh-aw/cache-memory/` using these paths: - -- `/tmp/gh-aw/cache-memory/baselines/` — reference screenshots from the base branch -- `/tmp/gh-aw/cache-memory/baselines/manifest.json` — index of all baseline screenshots with metadata - -Current-run screenshots are saved to a temporary location: - -- `/tmp/visual-regression/current/` — screenshots from this PR's HEAD +## Steps -## Phase 1: Prepare Directories - -Create the directories needed for this run: +### 1. Prepare directories ```bash mkdir -p /tmp/gh-aw/cache-memory/baselines mkdir -p /tmp/visual-regression/current ``` -Check whether baselines already exist for this base branch: - -```bash -ls /tmp/gh-aw/cache-memory/baselines/ -``` - -If `manifest.json` is present, baselines are available. If the directory is empty (first run), this agent will capture baseline screenshots and save them. +### 2. Start the preview server -## Phase 2: Start the Preview Server - -Start the application's preview/development server so Playwright can capture screenshots. The exact command depends on the project's tech stack: +Build and serve the app locally (adjust for the project's stack), then wait for it to be ready: ```bash -# Example: Next.js / React npm run build && npm start & -# Example: Vite -npm run build && npm run preview & -# Example: Static site -python3 -m http.server 3000 --directory ./dist & -``` - -Wait for the server to become ready before proceeding: - -```bash -# Wait up to 30 seconds for server to start timeout 30 bash -c 'until curl -sf http://localhost:3000 > /dev/null; do sleep 1; done' ``` -## Phase 3: Capture Current Screenshots +### 3. Capture screenshots -Use Playwright to capture screenshots of all key pages. For each page: +Use Playwright to navigate to each key page and take a full-page screenshot saved under `/tmp/visual-regression/current/`. Use filesystem-safe filenames (replace `/` with `_`, no special characters). -1. **Navigate** to the page URL -2. **Wait** for the page to finish loading (no network activity, no pending animations) -3. **Take a full-page screenshot** and save it under `/tmp/visual-regression/current/` - -Use filesystem-safe filenames — replace `/` with `_` and avoid colons or special characters. - -**Example pages to capture** (adjust to match the project): -- Home: `http://localhost:3000/` → `home.png` -- About: `http://localhost:3000/about` → `about.png` -- Dashboard: `http://localhost:3000/dashboard` → `dashboard.png` - -After capturing, generate a timestamp for the manifest (use filesystem-safe format — no colons): +Generate a filesystem-safe timestamp when needed (no colons — colons break artifact uploads): ```bash date -u "+%Y-%m-%d-%H-%M-%S" ``` -## Phase 4: Compare Against Baselines - -### Case A — No Baselines Found (First Run) - -If `/tmp/gh-aw/cache-memory/baselines/manifest.json` does not exist: +### 4. Compare against baselines -1. Copy the current screenshots to the baselines directory: +**First run** — no `manifest.json` in `/tmp/gh-aw/cache-memory/baselines/`: - ```bash - cp /tmp/visual-regression/current/*.png /tmp/gh-aw/cache-memory/baselines/ - ``` +Copy current screenshots to `/tmp/gh-aw/cache-memory/baselines/` and write a `manifest.json`: -2. Create a `manifest.json` file recording the baseline run: - - ```json - { - "created_at": "YYYY-MM-DD-HH-MM-SS", - "base_branch": "${{ github.event.pull_request.base.ref }}", - "run_id": "${{ github.run_id }}", - "pages": ["home.png", "about.png", "dashboard.png"] - } - ``` - - Save it to `/tmp/gh-aw/cache-memory/baselines/manifest.json`. - -3. Post a PR comment explaining that baselines have been initialized. - -### Case B — Baselines Exist (Comparison Run) - -For each page that was screenshotted: - -1. Compare the current screenshot to the baseline using `diff` (or pixel-level diff if available): - - ```bash - diff /tmp/gh-aw/cache-memory/baselines/home.png \ - /tmp/visual-regression/current/home.png \ - && echo "MATCH" || echo "DIFF" - ``` - -2. Track which pages have changed versus which match the baseline. +```json +{ + "created_at": "YYYY-MM-DD-HH-MM-SS", + "base_branch": "${{ github.event.pull_request.base.ref }}", + "run_id": "${{ github.run_id }}", + "pages": ["home.png", "dashboard.png"] +} +``` -3. Assemble a diff report (see Phase 5). +**Subsequent runs** — baselines exist: -## Phase 5: Post the Diff Report +Compare each screenshot with its baseline and collect the list of changed pages. -Use the `add-comment` safe output to post a structured report on the pull request. +### 5. Post diff report -### When All Pages Match ✅ +Use `add-comment` to post the results. Examples: -```markdown +**No changes:** +``` ## 👁️ Visual Regression — No Changes Detected - -All **N** pages match their baselines. - -| Page | Status | -|------|--------| -| Home | ✅ No change | -| About | ✅ No change | -| Dashboard | ✅ No change | - -> Baselines captured on `${{ github.event.pull_request.base.ref }}` — run ${{ github.run_id }} +All N pages match their baselines. ``` -### When Differences Are Found ⚠️ - -```markdown +**Changes found:** +``` ## 👁️ Visual Regression — Changes Detected - -**N of M pages** differ from their baselines. - -| Page | Status | -|------|--------| -| Home | ✅ No change | -| About | ⚠️ Changed | -| Dashboard | ✅ No change | - -### Changed Pages - -#### About (`about.png`) - -
-View diff details - -[Describe the visual differences observed using the Playwright accessibility snapshot or diff output] - -
- -### Next Steps - -- Review the changes above to confirm they are intentional -- If intentional, update the baselines by deleting `/tmp/gh-aw/cache-memory/baselines/` on the next main branch run -- If unintentional, investigate the CSS/layout changes introduced in this PR - -> Baselines captured on `${{ github.event.pull_request.base.ref }}` — run ${{ github.run_id }} +N of M pages differ from their baselines. +List each changed page with a description of the difference. ``` -### When Baselines Were Initialized 🆕 - -```markdown +**Baselines initialized:** +``` ## 👁️ Visual Regression — Baselines Initialized - -No prior baselines were found for branch `${{ github.event.pull_request.base.ref }}`. Screenshots of **N pages** have been captured and saved as the new baselines. - -| Page | Status | -|------|--------| -| Home | 🆕 Baseline saved | -| About | 🆕 Baseline saved | -| Dashboard | 🆕 Baseline saved | - -Future pull requests targeting `${{ github.event.pull_request.base.ref }}` will be compared against these baselines. +No prior baselines found. N pages captured and saved as new baselines. ``` -## Phase 6: Update Baselines (Optional) - -If the PR **intentionally** changes the UI and the diff is expected, update the baselines by overwriting the stored screenshots: +Always call a safe-output tool. If nothing changed, use noop: -```bash -cp /tmp/visual-regression/current/*.png /tmp/gh-aw/cache-memory/baselines/ +```json +{"noop": {"message": "Visual regression complete: all pages match baselines"}} ``` - -Update the `manifest.json` with the new timestamp and run ID. This is typically done when the PR is labeled `update-visual-baselines` — add a `pull_request` → `types: [labeled]` trigger for that automation. - -## Guidelines - -### Security -- **Read-only GitHub permissions** — this workflow only reads PR context; all writes go through `safe-outputs` -- **Localhost only** — Playwright is restricted to `localhost` / `127.0.0.1` to prevent SSRF -- **Allowed extensions** — cache-memory is restricted to `.png` and `.json` to prevent storing unexpected file types - -### Filesystem-Safe Filenames -Always use timestamps in `YYYY-MM-DD-HH-MM-SS` format (no colons). Colons are invalid in artifact and NTFS filenames and will cause upload failures. - -```bash -# ✅ Correct -date -u "+%Y-%m-%d-%H-%M-%S" # → 2026-02-25-05-33-46 - -# ❌ Incorrect (contains colons) -date -u "+%Y-%m-%dT%H:%M:%SZ" # → 2026-02-25T05:33:46Z ``` -### Baseline Scope -The cache key `visual-regression-baselines-${{ github.event.pull_request.base.ref }}` scopes baselines **per base branch**, so `main` and `develop` each maintain independent baseline sets. - -### Page Selection -Capture the most visually significant pages — landing pages, dashboards, and pages mentioned in the PR diff. Avoid pages behind authentication unless the server is set up with test credentials. +## Key Design Decisions -### Timeouts -Give the preview server adequate time to start (use `timeout` + retry loops). Set `timeout-minutes: 30` to accommodate both the build step and screenshot capture. - -## Important Notes - -- **Always call a safe-output tool** — even if no visual differences are found, post a comment confirming the check passed. Failing to call any safe-output tool is the most common cause of workflow failures. - -```json -{"noop": {"message": "No action needed: [brief explanation]"}} -``` +- **`cache-memory` key per base branch** — `visual-regression-baselines-${{ github.event.pull_request.base.ref }}` scopes baselines to `main`, `develop`, etc. independently +- **`allowed-extensions: [".png", ".json"]`** — restricts cache to screenshots and the manifest only +- **`playwright.allowed_domains: [localhost, 127.0.0.1]`** — prevents SSRF; the app must be served locally +- **`retention-days: 30`** — keeps baselines accessible beyond the default 7-day cache expiry +- **Filesystem-safe timestamps** — `YYYY-MM-DD-HH-MM-SS` (no colons); colons are invalid in NTFS/artifact filenames +- **Minimal permissions** — `contents: read` + `pull-requests: read`; all PR writes go through `safe-outputs` From abc03a650e982b17f4be4d96db04990d34827524 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 06:12:53 +0000 Subject: [PATCH 4/5] docs: link visual-regression.md in create-agentic-workflow agent prompt Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/agents/agentic-workflows.agent.md | 11 +++++++++++ .github/aw/create-agentic-workflow.md | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/agents/agentic-workflows.agent.md b/.github/agents/agentic-workflows.agent.md index e34a4da6123..c0f21877e1b 100644 --- a/.github/agents/agentic-workflows.agent.md +++ b/.github/agents/agentic-workflows.agent.md @@ -18,6 +18,7 @@ This is a **dispatcher agent** that routes your request to the appropriate speci - **Creating report-generating workflows**: Routes to `report` prompt — consult this whenever the workflow posts status updates, audits, analyses, or any structured output as issues, discussions, or comments - **Creating shared components**: Routes to `create-shared-agentic-workflow` prompt - **Fixing Dependabot PRs**: Routes to `dependabot` prompt — use this when Dependabot opens PRs that modify generated manifest files (`.github/workflows/package.json`, `.github/workflows/requirements.txt`, `.github/workflows/go.mod`). Never merge those PRs directly; instead update the source `.md` files and rerun `gh aw compile --dependabot` to bundle all fixes +- **Analyzing test coverage**: Routes to `test-coverage` prompt — consult this whenever the workflow reads, analyzes, or reports on test coverage data from PRs or CI runs Workflows may optionally include: @@ -118,6 +119,16 @@ When you interact with this agent, it will: - "Bundle and close the Dependabot PRs for workflow dependencies" - "Update @playwright/test to fix the Dependabot PR" +### Analyze Test Coverage +**Load when**: The workflow reads, analyzes, or reports test coverage — whether triggered by a PR, a schedule, or a slash command. Always consult this prompt before designing the coverage data strategy. + +**Prompt file**: https://github.com/github/gh-aw/blob/main/.github/aw/test-coverage.md + +**Use cases**: +- "Create a workflow that comments coverage on PRs" +- "Analyze coverage trends over time" +- "Add a coverage gate that blocks PRs below a threshold" + ## Instructions When a user interacts with you: diff --git a/.github/aw/create-agentic-workflow.md b/.github/aw/create-agentic-workflow.md index 906f092e89f..3b700a066f5 100644 --- a/.github/aw/create-agentic-workflow.md +++ b/.github/aw/create-agentic-workflow.md @@ -208,7 +208,7 @@ These resources contain workflow patterns, best practices, safe outputs, and per - `Package.swift`, `*.podspec` → add `swift` - `composer.json` → add `php` - `pubspec.yaml` → add `dart` - - 💡 If you detect the task requires **browser automation**, suggest the **`playwright`** tool. + - 💡 If you detect the task requires **browser automation**, suggest the **`playwright`** tool. For **visual regression testing** (comparing screenshots across PRs), consult `.github/aw/visual-regression.md` for the reference pattern using `playwright` + `cache-memory`. - 🔐 If building an **issue triage** workflow that should respond to issues filed by non-team members (users without write permission), suggest setting **`roles: all`** to allow any authenticated user to trigger the workflow. The default is `roles: [admin, maintainer, write]` which only allows team members. **Scheduling Best Practices:** From 7c7bcf8e11f35306f6866f577b0922ca4e09dc8f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 06:20:59 +0000 Subject: [PATCH 5/5] docs: condense visual-regression.md instructions Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/aw/visual-regression.md | 113 ++++---------------------------- 1 file changed, 14 insertions(+), 99 deletions(-) diff --git a/.github/aw/visual-regression.md b/.github/aw/visual-regression.md index 5f1f6f308bf..dd1bf45fbf7 100644 --- a/.github/aw/visual-regression.md +++ b/.github/aw/visual-regression.md @@ -1,17 +1,17 @@ --- name: visual-regression -description: Reference workflow for visual regression testing using playwright to capture screenshots and cache-memory to store baselines across pull requests +description: Reference prompt for visual regression testing using playwright + cache-memory for baseline screenshot storage across pull requests --- -# Visual Regression Testing Reference +# Visual Regression Testing -This is a reference workflow that demonstrates how to combine `playwright` (for capturing screenshots) with `cache-memory` (for storing baselines between runs) to implement visual regression testing on pull requests. +Use `playwright` for screenshots and `cache-memory` to persist baselines between PR runs. ## Example Workflow ```markdown --- -description: Captures screenshots on every PR and compares them against baselines stored in cache-memory to detect visual regressions +description: Capture screenshots on every PR and compare against cached baselines to detect visual regressions on: pull_request: types: [opened, synchronize, reopened] @@ -33,111 +33,26 @@ tools: - "cp *" - "diff *" - "date *" - - "echo *" safe-outputs: add-comment: max: 1 - messages: - footer: "> 👁️ *Visual regression check by [{workflow_name}]({run_url})*" - run-started: "👁️ [{workflow_name}]({run_url}) is running visual regression on this {event_type}..." - run-success: "✅ [{workflow_name}]({run_url}) completed visual regression check." - run-failure: "❌ [{workflow_name}]({run_url}) {status}. Check the [run logs]({run_url}) for details." timeout-minutes: 30 --- -# Visual Regression Agent 👁️ +Build and serve the app locally, then use Playwright to capture full-page screenshots of key pages into `/tmp/visual-regression/current/`. -You are the Visual Regression Agent. On every pull request, capture screenshots of key UI pages and compare them against baseline screenshots stored in cache-memory. +Use filesystem-safe timestamps (no colons — colons break artifact uploads): +`date -u "+%Y-%m-%d-%H-%M-%S"` -## Context +If `/tmp/gh-aw/cache-memory/baselines/manifest.json` does not exist, copy screenshots there as new baselines and post: "Baselines initialized — N pages captured." -- **Repository**: ${{ github.repository }} -- **Pull Request**: #${{ github.event.pull_request.number }} -- **Base Branch**: ${{ github.event.pull_request.base.ref }} -- **Run ID**: ${{ github.run_id }} - -## Steps - -### 1. Prepare directories - -```bash -mkdir -p /tmp/gh-aw/cache-memory/baselines -mkdir -p /tmp/visual-regression/current -``` - -### 2. Start the preview server - -Build and serve the app locally (adjust for the project's stack), then wait for it to be ready: - -```bash -npm run build && npm start & -timeout 30 bash -c 'until curl -sf http://localhost:3000 > /dev/null; do sleep 1; done' -``` - -### 3. Capture screenshots - -Use Playwright to navigate to each key page and take a full-page screenshot saved under `/tmp/visual-regression/current/`. Use filesystem-safe filenames (replace `/` with `_`, no special characters). - -Generate a filesystem-safe timestamp when needed (no colons — colons break artifact uploads): - -```bash -date -u "+%Y-%m-%d-%H-%M-%S" -``` - -### 4. Compare against baselines - -**First run** — no `manifest.json` in `/tmp/gh-aw/cache-memory/baselines/`: - -Copy current screenshots to `/tmp/gh-aw/cache-memory/baselines/` and write a `manifest.json`: - -```json -{ - "created_at": "YYYY-MM-DD-HH-MM-SS", - "base_branch": "${{ github.event.pull_request.base.ref }}", - "run_id": "${{ github.run_id }}", - "pages": ["home.png", "dashboard.png"] -} -``` - -**Subsequent runs** — baselines exist: - -Compare each screenshot with its baseline and collect the list of changed pages. - -### 5. Post diff report - -Use `add-comment` to post the results. Examples: - -**No changes:** -``` -## 👁️ Visual Regression — No Changes Detected -All N pages match their baselines. -``` - -**Changes found:** -``` -## 👁️ Visual Regression — Changes Detected -N of M pages differ from their baselines. -List each changed page with a description of the difference. -``` - -**Baselines initialized:** -``` -## 👁️ Visual Regression — Baselines Initialized -No prior baselines found. N pages captured and saved as new baselines. -``` - -Always call a safe-output tool. If nothing changed, use noop: - -```json -{"noop": {"message": "Visual regression complete: all pages match baselines"}} -``` +Otherwise compare each screenshot to its baseline. Post a comment summarizing: pages unchanged / pages with diffs. If nothing changed, use the `noop` safe-output. ``` ## Key Design Decisions -- **`cache-memory` key per base branch** — `visual-regression-baselines-${{ github.event.pull_request.base.ref }}` scopes baselines to `main`, `develop`, etc. independently -- **`allowed-extensions: [".png", ".json"]`** — restricts cache to screenshots and the manifest only -- **`playwright.allowed_domains: [localhost, 127.0.0.1]`** — prevents SSRF; the app must be served locally -- **`retention-days: 30`** — keeps baselines accessible beyond the default 7-day cache expiry -- **Filesystem-safe timestamps** — `YYYY-MM-DD-HH-MM-SS` (no colons); colons are invalid in NTFS/artifact filenames -- **Minimal permissions** — `contents: read` + `pull-requests: read`; all PR writes go through `safe-outputs` +- **`cache-memory` key per base branch** — scopes baselines to `main`, `develop`, etc. independently +- **`allowed_domains: [localhost, 127.0.0.1]`** — prevents SSRF; app must be served locally +- **`retention-days: 30`** — keeps baselines beyond the default 7-day cache expiry +- **Filesystem-safe timestamps** — `YYYY-MM-DD-HH-MM-SS` format; colons are invalid in artifact filenames +- **Minimal permissions** — all PR writes go through `safe-outputs`, not GitHub tools