mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
* Track the rule registry as a generated artifact `cargo xtask bundle` already wrote the registry to `dist/antipatterns.json` and into `extension/detector/`, but neither is tracked, so a consumer reading this repo from a source checkout or a tarball had no way to get the rule list without a Rust toolchain. The Rust swap made that concrete: impeccable.style imported `cli/engine/registry/antipatterns.mjs` for its rule count and its Slop catalog, and that file is gone. Write the same JSON to `crates/live/assets/antipatterns.json`, next to the in-page bundle and tracked like it, and extend `cargo xtask bundle --check` to fail when either asset is stale. The build's rule-count check now reads the tracked copy first and falls back to the extension copy, so a fresh checkout validates counts instead of skipping the check. Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY * Registry: wire the staleness gate into CI, harden the count read Two review findings on the tracked-registry change. `cargo xtask bundle --check` was never run by CI, so a rule whose name, category, or description changed without changing the rule count could ship a stale `crates/live/assets/antipatterns.json`. The extension job already runs `bun run build:extension` (and so `cargo xtask bundle`) and then asserts a clean tree; adding that file to the path list covers it with the gate that is already there. The bundle beside it stays out: its bytes carry a wasm module built by whatever wasm-pack and wasm-opt the runner installed, so diffing it would fail on toolchain drift rather than on a real change. `readDetectionRuleCount` counted `new Set(rules.map(r => r.id))`, so a shape change would collapse to a set of one `undefined` and read as a one-rule registry, flagging every count claim as stale. Count only non-empty string ids, and say "no readable antipatterns.json" when the file is present but unparseable. Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY * Registry gate: make the trigger honest, name the real count condition The tracked-registry diff check ran on every PR, but the step that regenerates the registry (`bun run build:extension`, which is `cargo xtask bundle`) only runs when the detector trigger fires, and that trigger did not list `crates/bundle`. A PR that changed how the registry is serialized therefore never rebuilt it, and the check compared the committed file against an untouched tree and passed on stale bytes. Two changes. The detector trigger now covers every input the bundle reads: `crates/(bundle|core|foundation|wasm|xtask)/` plus `crates/live/assets/` so a hand-edit of a tracked artifact is regenerated over. And the registry check moved into its own step carrying the same condition as the build it validates, so it no longer claims to check something that was never regenerated; the provider-output check stays unconditional, because `bun run build` runs on every PR. Separately, `readDetectionRuleCount` returns the reason it found no count. "no antipatterns.json" covered three different conditions, and a registry that is present but unparseable sends anyone debugging a count failure to the wrong place. It now reports the paths it looked at, or names the file that is not readable as JSON, or names the file that carries no rule ids. Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY --------- Co-authored-by: Claude Code <noreply@anthropic.com>
649 lines
22 KiB
YAML
649 lines
22 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
# Nightly full live-e2e matrix. The smoke groups already gate every PR; the
|
|
# full sweep is too slow for that, so it runs once a day against main.
|
|
schedule:
|
|
- cron: '0 7 * * *'
|
|
|
|
concurrency:
|
|
# Scheduled runs get their own group: the 07:00 UTC nightly and a push to
|
|
# main share github.ref, and cancel-in-progress would let them kill each
|
|
# other mid-run.
|
|
group: ${{ github.workflow }}-${{ github.event_name == 'schedule' && 'nightly' || github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
changes:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
core: ${{ steps.plan.outputs.core }}
|
|
rust: ${{ steps.plan.outputs.rust }}
|
|
detector: ${{ steps.plan.outputs.detector }}
|
|
live: ${{ steps.plan.outputs.live }}
|
|
framework: ${{ steps.plan.outputs.framework }}
|
|
cli_remote_e2e: ${{ steps.plan.outputs.cli_remote_e2e }}
|
|
live_e2e: ${{ steps.plan.outputs.live_e2e }}
|
|
live_e2e_accept_cleanup: ${{ steps.plan.outputs.live_e2e_accept_cleanup }}
|
|
skill_behavior: ${{ steps.plan.outputs.skill_behavior }}
|
|
live_svelte_adapter_deepseek: ${{ steps.plan.outputs.live_svelte_adapter_deepseek }}
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Detect test plan
|
|
id: plan
|
|
env:
|
|
GITHUB_EVENT_BEFORE: ${{ github.event.before }}
|
|
run: node scripts/ci-test-plan.mjs
|
|
|
|
test-matrix:
|
|
name: test (Node ${{ matrix.node-version }})
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
node-version: [22.18.0, 24]
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: ${{ matrix.node-version }}
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Install dependencies
|
|
run: bun install
|
|
|
|
- name: Run core tests
|
|
run: bun run test:core
|
|
|
|
- name: Install Puppeteer browser
|
|
if: needs.changes.outputs.detector == 'true'
|
|
run: bunx puppeteer browsers install chrome
|
|
|
|
- name: Run detector tests
|
|
if: needs.changes.outputs.detector == 'true'
|
|
run: bun run test:detector
|
|
|
|
- name: Run live unit tests
|
|
if: needs.changes.outputs.live == 'true'
|
|
run: bun run test:live
|
|
|
|
- name: Run framework fixture tests
|
|
if: needs.changes.outputs.framework == 'true'
|
|
run: bun run test:framework
|
|
|
|
- name: Build
|
|
run: bun run build
|
|
|
|
# `bun run build:extension` runs `cargo xtask bundle`: the rule core
|
|
# compiled to wasm plus the page JS in browser-bundle/.
|
|
- name: Install the pinned toolchain
|
|
if: needs.changes.outputs.detector == 'true'
|
|
run: rustup show && rustup target add wasm32-unknown-unknown
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
if: needs.changes.outputs.detector == 'true'
|
|
|
|
- name: Install wasm-pack
|
|
if: needs.changes.outputs.detector == 'true'
|
|
run: cargo install wasm-pack --locked
|
|
|
|
- name: Build extension
|
|
if: needs.changes.outputs.detector == 'true'
|
|
run: bun run build:extension
|
|
|
|
- name: Lint Firefox extension (web-ext)
|
|
if: needs.changes.outputs.detector == 'true'
|
|
# Pinned for reproducible CI. Fails on AMO errors; innerHTML style
|
|
# warnings in the panel renderer are non-blocking and not promoted to
|
|
# errors here.
|
|
run: npx --yes web-ext@10 lint --source-dir dist/extension-firefox
|
|
|
|
# Only meaningful right after the bundle was rebuilt, so it carries the
|
|
# same condition as that step rather than running unconditionally and
|
|
# comparing a committed artifact against an untouched tree. Every input
|
|
# `cargo xtask bundle` reads is in the detector trigger
|
|
# (scripts/test-suites.mjs), so a change to the registry rows or to how
|
|
# they are serialized lands here. The in-page bundle beside it is
|
|
# deliberately not checked: its bytes carry a wasm module built by
|
|
# whatever wasm-pack and wasm-opt the runner installed, so diffing it
|
|
# would fail on toolchain drift rather than on a real change.
|
|
- name: Verify the tracked rule registry is current
|
|
if: needs.changes.outputs.detector == 'true'
|
|
run: git diff --exit-code -- crates/live/assets/antipatterns.json
|
|
|
|
- name: Verify generated tracked outputs
|
|
# What `bun run build` writes, which runs on every PR.
|
|
# extension/detector/ is gitignored (built by `cargo xtask bundle`);
|
|
# it stays listed so a stray tracked copy shows up here.
|
|
run: git diff --exit-code -- .agents .claude .cursor .gemini .github/skills plugin extension/detector
|
|
|
|
- name: Upload build artifacts
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: impeccable-build-node-${{ matrix.node-version }}
|
|
# Ship the packaged zips, not the unpacked Firefox staging tree.
|
|
path: |
|
|
dist/
|
|
!dist/extension-firefox/
|
|
retention-days: 7
|
|
|
|
# The Rust workspace: the engine binary, the rule core, and every crate
|
|
# behind them. Everything builds from source with no downloads.
|
|
rust:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.rust == 'true'
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
# rust-toolchain.toml names the channel; `rustup show` installs it.
|
|
# Never override the toolchain here.
|
|
- name: Install the pinned toolchain
|
|
run: rustup show
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Build
|
|
run: cargo build --workspace --all-targets
|
|
|
|
- name: Test
|
|
run: cargo test --workspace
|
|
|
|
# The engine ships a windows-x64 binary (release-engine.yml), so the
|
|
# workspace has to build and pass its own tests there. Tests that need a
|
|
# browser or the oracle skip when those are absent.
|
|
rust-windows:
|
|
runs-on: windows-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.rust == 'true'
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
- name: Install the pinned toolchain
|
|
run: rustup show
|
|
- uses: Swatinem/rust-cache@v2
|
|
- run: cargo build --workspace --all-targets
|
|
- run: cargo test --workspace --no-fail-fast
|
|
|
|
# Behavior gate: replays the tests/oracle/ goldens against a release build
|
|
# of the engine from THIS checkout (so a PR is judged on its own source,
|
|
# not on the last published binary). Without this job the oracle only ever
|
|
# runs on developer laptops: tests/oracle.test.mjs skips cleanly when no
|
|
# binary is present, so the default suite is silent about it on CI.
|
|
oracle:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.oracle == 'true' || needs.changes.outputs.rust == 'true'
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Install dependencies
|
|
run: bun install
|
|
|
|
- name: Install the pinned toolchain
|
|
run: rustup show
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Build the engine from source
|
|
run: cargo build --release -p impeccable
|
|
|
|
- name: Replay oracle goldens
|
|
env:
|
|
IMPECCABLE_BIN: ${{ github.workspace }}/target/release/impeccable
|
|
run: node tests/oracle/run.mjs
|
|
|
|
# Release-order guard (triage decision D4). Verifies that the engine release for
|
|
# the pinned ENGINE_VERSION is fully published — the five dist binaries + .sha256
|
|
# AND the five @impeccable/cli-<os>-<arch> npm platform packages — before a skill
|
|
# release/merge that depends on them. The launcher, npm shim, and
|
|
# `impeccable install` all dead-end without those assets.
|
|
#
|
|
# A hard gate since engine-v0.1.0 shipped: the assets for the pinned
|
|
# ENGINE_VERSION must exist before a skill/CLI release or a merge that bumps the
|
|
# pin, or the launcher, the npm shim and `impeccable install` dead-end.
|
|
# release.mjs hard-fails `release:skill`/`release:cli` on the same check.
|
|
engine-release-ready:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Check engine release assets for pinned ENGINE_VERSION
|
|
id: check
|
|
run: node scripts/check-engine-release.mjs
|
|
|
|
- name: Annotate missing engine release
|
|
# Only when the check itself failed, so a checkout or setup failure keeps its own error.
|
|
if: failure() && steps.check.outcome == 'failure'
|
|
run: |
|
|
echo "::error title=Engine release not ready::The engine release for v$(cat ENGINE_VERSION) is not fully published (engine-v$(cat ENGINE_VERSION) release assets and/or the @impeccable/cli-<os>-<arch> npm platform packages). Publish the engine (bun run release:engine) and the platform packages (bun run release:platform-packages) before bumping ENGINE_VERSION on main or releasing the skill/CLI."
|
|
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
needs: test-matrix
|
|
if: always()
|
|
steps:
|
|
- name: Verify Node test matrix
|
|
run: |
|
|
if [ "${{ needs.test-matrix.result }}" != "success" ]; then
|
|
echo "test-matrix result: ${{ needs.test-matrix.result }}"
|
|
exit 1
|
|
fi
|
|
echo "test matrix passed"
|
|
|
|
cli-remote-e2e:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.cli_remote_e2e == 'true'
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Install dependencies
|
|
run: bun install
|
|
|
|
# The live verbs are the engine binary; build it from this checkout so the
|
|
# suite tests the branch, not the last published release.
|
|
- name: Install the pinned toolchain
|
|
run: rustup show
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Build the engine
|
|
run: cargo build --release -p impeccable
|
|
|
|
- name: Run remote CLI E2E smoke
|
|
run: bun run test:cli-remote-e2e
|
|
|
|
live-e2e-smoke:
|
|
name: live-e2e smoke (${{ matrix.group }})
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.live_e2e == 'true' && github.event_name != 'workflow_dispatch' && github.event_name != 'schedule'
|
|
timeout-minutes: 15
|
|
strategy:
|
|
fail-fast: true
|
|
matrix:
|
|
include:
|
|
- group: platform
|
|
fixtures: astro-vite7,monorepo-nested-vite,nextjs-app-router,vite8-sveltekit
|
|
- group: svelte
|
|
fixtures: vite8-sveltekit-stateful
|
|
- group: react
|
|
fixtures: vite8-react-css-modules,vite8-react-insert,vite8-react-plain
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Cache fixture npm downloads
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-fixture-npm-${{ hashFiles('tests/framework-fixtures/**/files/package.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-fixture-npm-
|
|
|
|
- name: Cache Playwright Chromium
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: ${{ runner.os }}-playwright-chromium-${{ hashFiles('package.json', 'bun.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-playwright-chromium-
|
|
|
|
- name: Install dependencies
|
|
run: bun install
|
|
|
|
- name: Install Playwright Chromium
|
|
run: npx playwright install chromium
|
|
|
|
# The live verbs are the engine binary; build it from this checkout so the
|
|
# suite tests the branch, not the last published release.
|
|
- name: Install the pinned toolchain
|
|
run: rustup show
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Build the engine
|
|
run: cargo build --release -p impeccable
|
|
|
|
- name: Run live E2E tests
|
|
run: bun run test:live-e2e
|
|
env:
|
|
IMPECCABLE_E2E_ONLY: ${{ matrix.fixtures }}
|
|
IMPECCABLE_E2E_SCENARIOS: core
|
|
IMPECCABLE_E2E_TEST_TIMEOUT_MS: 180000
|
|
IMPECCABLE_E2E_INSTALL_TIMEOUT_MS: 120000
|
|
IMPECCABLE_E2E_DEV_READY_TIMEOUT_MS: 60000
|
|
IMPECCABLE_E2E_ARTIFACT_DIR: test-results/live-e2e/${{ matrix.group }}
|
|
|
|
- name: Upload live E2E failure artifacts
|
|
if: failure()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: live-e2e-smoke-${{ matrix.group }}-artifacts
|
|
path: test-results/live-e2e
|
|
if-no-files-found: ignore
|
|
|
|
live-e2e-full:
|
|
name: live-e2e full (${{ matrix.group }})
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.live_e2e == 'true' && (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
|
|
timeout-minutes: 25
|
|
strategy:
|
|
fail-fast: true
|
|
matrix:
|
|
include:
|
|
- group: platform
|
|
fixtures: astro-vite7,monorepo-nested-vite,nextjs-app-router
|
|
- group: svelte
|
|
fixtures: vite8-sveltekit,vite8-sveltekit-stateful
|
|
- group: react-a
|
|
fixtures: vite8-https,vite8-react-base-path,vite8-react-csp-meta,vite8-react-css-modules,vite8-react-emotion
|
|
- group: react-b
|
|
fixtures: vite8-react-insert,vite8-react-mapped-list,vite8-react-modal,vite8-react-plain
|
|
- group: stateful
|
|
fixtures: vite8-react-radix-dialog,vite8-react-router-spa,vite8-react-styled-components,vite8-react-tabs
|
|
- group: styling
|
|
fixtures: vite8-react-tailwindv3,vite8-react-tailwindv4,vite8-react-ts,vite8-react-tsx-repeated-aside,vite8-react-unocss,vite8-react-vanilla-extract
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Cache fixture npm downloads
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-fixture-npm-${{ hashFiles('tests/framework-fixtures/**/files/package.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-fixture-npm-
|
|
|
|
- name: Cache Playwright Chromium
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: ${{ runner.os }}-playwright-chromium-${{ hashFiles('package.json', 'bun.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-playwright-chromium-
|
|
|
|
- name: Install dependencies
|
|
run: bun install
|
|
|
|
- name: Install Playwright Chromium
|
|
run: npx playwright install chromium
|
|
|
|
# The live verbs are the engine binary; build it from this checkout so the
|
|
# suite tests the branch, not the last published release.
|
|
- name: Install the pinned toolchain
|
|
run: rustup show
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Build the engine
|
|
run: cargo build --release -p impeccable
|
|
|
|
- name: Run live E2E tests
|
|
run: bun run test:live-e2e
|
|
env:
|
|
IMPECCABLE_E2E_ONLY: ${{ matrix.fixtures }}
|
|
IMPECCABLE_E2E_TEST_TIMEOUT_MS: 300000
|
|
IMPECCABLE_E2E_INSTALL_TIMEOUT_MS: 180000
|
|
IMPECCABLE_E2E_DEV_READY_TIMEOUT_MS: 120000
|
|
IMPECCABLE_E2E_ARTIFACT_DIR: test-results/live-e2e/${{ matrix.group }}
|
|
|
|
- name: Upload live E2E failure artifacts
|
|
if: failure()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: live-e2e-full-${{ matrix.group }}-artifacts
|
|
path: test-results/live-e2e
|
|
if-no-files-found: ignore
|
|
|
|
live-e2e-accept-cleanup:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.live_e2e_accept_cleanup == 'true'
|
|
timeout-minutes: 15
|
|
env:
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
steps:
|
|
- name: Skip without provider key
|
|
if: ${{ env.ANTHROPIC_API_KEY == '' && env.DEEPSEEK_API_KEY == '' }}
|
|
run: echo "Skipping provider-backed accept-cleanup regression because no provider API key is configured."
|
|
|
|
- name: Checkout repository
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Setup Bun
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Cache fixture npm downloads
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-fixture-npm-${{ hashFiles('tests/framework-fixtures/**/files/package.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-fixture-npm-
|
|
|
|
- name: Cache Playwright Chromium
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: ${{ runner.os }}-playwright-chromium-${{ hashFiles('package.json', 'bun.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-playwright-chromium-
|
|
|
|
- name: Install dependencies
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
run: bun install
|
|
|
|
- name: Install Playwright Chromium
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
run: npx playwright install chromium
|
|
|
|
# The live verbs are the engine binary; build it from this checkout so the
|
|
# suite tests the branch, not the last published release.
|
|
- name: Install the pinned toolchain
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
run: rustup show
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
|
|
- name: Build the engine
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
run: cargo build --release -p impeccable
|
|
|
|
- name: Run accept cleanup regression
|
|
if: ${{ env.ANTHROPIC_API_KEY != '' || env.DEEPSEEK_API_KEY != '' }}
|
|
run: |
|
|
if [ -n "$DEEPSEEK_API_KEY" ]; then
|
|
export IMPECCABLE_E2E_LLM_PROVIDER=deepseek
|
|
else
|
|
export IMPECCABLE_E2E_LLM_PROVIDER=anthropic
|
|
fi
|
|
bun run test:live-e2e-accept-cleanup
|
|
|
|
live-svelte-adapter-deepseek:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.live_svelte_adapter_deepseek == 'true'
|
|
timeout-minutes: 25
|
|
env:
|
|
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
steps:
|
|
- name: Skip without DeepSeek key
|
|
if: ${{ env.DEEPSEEK_API_KEY == '' }}
|
|
run: echo "Skipping Svelte adapter DeepSeek sweep because DEEPSEEK_API_KEY is not configured."
|
|
|
|
- name: Checkout repository
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Setup Bun
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Cache fixture npm downloads
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-fixture-npm-${{ hashFiles('tests/framework-fixtures/**/files/package.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-fixture-npm-
|
|
|
|
- name: Cache Playwright Chromium
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: ${{ runner.os }}-playwright-chromium-${{ hashFiles('package.json', 'bun.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-playwright-chromium-
|
|
|
|
- name: Install dependencies
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
run: bun install
|
|
|
|
- name: Install Playwright Chromium
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
run: npx playwright install chromium
|
|
|
|
# The live verbs are the engine binary; build it from this checkout so the
|
|
# suite tests the branch, not the last published release.
|
|
- name: Install the pinned toolchain
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
run: rustup show
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
|
|
- name: Build the engine
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
run: cargo build --release -p impeccable
|
|
|
|
- name: Run Svelte adapter DeepSeek sweep
|
|
if: ${{ env.DEEPSEEK_API_KEY != '' }}
|
|
run: bun run test:live-svelte-adapter-deepseek
|
|
|
|
skill-behavior:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: needs.changes.outputs.skill_behavior == 'true' && github.event_name != 'pull_request'
|
|
env:
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
GOOGLE_CLOUD_API_KEY: ${{ secrets.GOOGLE_CLOUD_API_KEY }}
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Install dependencies
|
|
run: bun install
|
|
|
|
- name: Run skill behavior tests
|
|
run: bun run test:skill-behavior
|