ci: run only changed e2e specs on pull requests (#11834)

This commit is contained in:
Neil
2026-07-31 16:25:13 -07:00
committed by GitHub
parent f56e6ade80
commit 676964b099
13 changed files with 133 additions and 247 deletions
-10
View File
@@ -140,16 +140,6 @@ jobs:
- name: Windows daemon workspace-close repro
if: runner.os == 'Windows'
run: node config/scripts/windows-daemon-workspace-close-repro.mjs
- if: runner.os == 'Linux'
env:
ORCA_COMPUTER_E2E: '1'
ACCESSIBILITY_ENABLED: '1'
run: xvfb-run --auto-servernum dbus-run-session -- pnpm test:e2e:computer --reporter=verbose tests/e2e/computer-linux.e2e.ts
- if: runner.os == 'Windows'
env:
ORCA_COMPUTER_E2E: '1'
run: pnpm test:e2e:computer --reporter=verbose tests/e2e/computer-windows.e2e.ts
mac-native-owner-smoke:
if: github.event_name == 'pull_request'
runs-on: macos-15
+63
View File
@@ -13,6 +13,10 @@ on:
description: Ref to check out (defaults to the calling workflow's ref)
required: false
type: string
test_files:
description: JSON array of changed specs; empty runs the full suite
required: false
type: string
workflow_dispatch:
inputs:
ref:
@@ -84,6 +88,7 @@ jobs:
e2e:
name: e2e ${{ matrix.shard_name }}
needs: build
if: inputs.test_files == ''
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
@@ -183,9 +188,67 @@ jobs:
retention-days: 7
if-no-files-found: ignore
changed-e2e:
name: changed e2e specs
needs: build
if: inputs.test_files != ''
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- name: Install native build and headless UI tools
run: sudo apt-get update && sudo apt-get install -y build-essential python3 xvfb
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: package.json
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
run_install: false
- name: Use external node-gyp to avoid pnpm's bundled copy
run: |
npm install -g node-gyp@11.5.0
echo "npm_config_node_gyp=$(npm root -g)/node-gyp/bin/node-gyp.js" >> "$GITHUB_ENV"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Download E2E build output
uses: actions/download-artifact@v8
with:
name: e2e-build-out
path: out/
- name: Run changed E2E specs
env:
TEST_FILES_JSON: ${{ inputs.test_files }}
run: |
mapfile -t TEST_FILES < <(jq -r '.[]' <<<"$TEST_FILES_JSON")
xvfb-run --auto-servernum env SKIP_BUILD=1 ORCA_E2E_FORWARD_APP_LOGS=1 \
pnpm run test:e2e "${TEST_FILES[@]}" --workers=1
- name: Upload Playwright traces
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-traces-changed
path: test-results/
retention-days: 7
if-no-files-found: ignore
ssh-docker-watcher-isolation:
name: ssh docker watcher isolation
needs: build
if: inputs.test_files == ''
runs-on: ubuntu-latest
# Why 35: the terminal parking + retention specs below add two more
# docker-rig tests capped at 240s each on top of the watcher isolation pair.
+1 -15
View File
@@ -1,18 +1,6 @@
name: Golden E2E Experiment
on:
pull_request:
paths:
- '.github/workflows/golden-e2e-experiment.yml'
- 'package.json'
- 'tests/e2e/golden-core-flows.spec.ts'
- 'tests/e2e/fixtures/terminal-emoji-table.md'
- 'tests/e2e/helpers/**'
- 'tests/e2e/terminal-raw-emoji-table-scroll-restore.spec.ts'
- 'tests/e2e/terminal-webgl-atlas-budget.spec.ts'
- 'config/patches/@xterm__addon-webgl@0.20.0-beta.286.patch'
- 'src/renderer/src/components/sidebar/SidebarHeader.tsx'
- 'src/renderer/src/lib/pane-manager/**'
workflow_dispatch:
inputs:
ref:
@@ -44,9 +32,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
# Why: pull_request merge refs disappear after merge, but experiment
# reruns still need a stable commit to checkout.
ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.ref }}
ref: ${{ inputs.ref || github.ref }}
- name: Install native build tools
if: runner.os == 'Linux'
@@ -1,20 +1,6 @@
name: Linux Wayland GPU Sandbox
on:
pull_request:
paths:
- .github/workflows/linux-wayland-gpu-sandbox.yml
- config/scripts/linux-wayland-renderer-diagnostics.mjs
- config/scripts/linux-wayland-terminal-exercise.mjs
- config/scripts/linux-wayland-validation-watchdog.mjs
- config/scripts/verify-linux-wayland-gpu-sandbox.mjs
- src/main/startup/configure-process.ts
- src/main/startup/configure-process.test.ts
- src/preload/api-types.ts
- src/preload/index.ts
- src/renderer/src/components/terminal-pane/pty-connection.ts
- src/renderer/src/lib/pane-manager/terminal-webgl-auto-policy.ts
- src/renderer/src/web/web-preload-api.ts
workflow_dispatch:
jobs:
@@ -85,34 +71,6 @@ jobs:
done
test -S "$XDG_RUNTIME_DIR/wayland-1"
- name: Reproduce terminal input freeze without the workaround
id: reproduce_base
if: github.event_name == 'pull_request'
# Why: still collect fixed-path Wayland evidence when the base repro
# stops reproducing; the final gate below fails the job in that case.
continue-on-error: true
timeout-minutes: 10
run: |
set -euo pipefail
git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.base.sha }}"
# Why: once the PR base includes this workaround, the partial
# checkout cannot reconstruct an unfixed Wayland negative control.
if git show "${{ github.event.pull_request.base.sha }}:src/main/startup/configure-process.ts" | grep -Eq "appendSwitch\\(['\"]disable-gpu-sandbox['\"]\\)"; then
echo "The base build already contains the Linux Wayland GPU sandbox workaround; skipping unfixed-path reproduction."
exit 0
fi
# Why: keep the new verifier scripts, but run them against the
# unfixed production terminal/GPU path instead of a hybrid checkout.
git checkout "${{ github.event.pull_request.base.sha }}" -- \
src/main/startup/configure-process.ts \
src/preload/api-types.ts \
src/preload/index.ts \
src/renderer/src/components/terminal-pane/pty-connection.ts \
src/renderer/src/lib/pane-manager/terminal-webgl-auto-policy.ts \
src/renderer/src/web/web-preload-api.ts
rm -rf out
node config/scripts/verify-linux-wayland-gpu-sandbox.mjs --mode=expect-repro
- name: Verify terminal input under Wayland GPU sandbox workaround
if: ${{ !cancelled() }}
timeout-minutes: 10
@@ -122,12 +80,6 @@ jobs:
rm -rf out
node config/scripts/verify-linux-wayland-gpu-sandbox.mjs
- name: Require base reproduction
if: ${{ github.event_name == 'pull_request' && steps.reproduce_base.outcome != 'success' }}
run: |
echo "The unfixed base build did not reproduce the Wayland terminal input failure."
exit 1
- name: Upload Weston log
if: always()
uses: actions/upload-artifact@v7
+14 -15
View File
@@ -325,11 +325,10 @@ jobs:
- name: Smoke packaged CLI
run: node config/scripts/smoke-packaged-cli.mjs --app-dir=dist/win-unpacked
# Why: regression specs under tests/e2e/** used to merge green without ever
# running — e2e.yml only fired on schedule/release (#10518). Path-filter so
# ordinary PRs stay light; any E2E suite change still gets a full shard run.
# Why: PR E2E is advisory and only validates changed specs; scheduled and
# release runs retain full-suite coverage.
e2e-paths:
name: detect e2e path changes
name: detect changed e2e specs
runs-on: ubuntu-latest
if: github.event.pull_request.draft != true
# Why: detector only needs to read the checkout; do not inherit repo defaults.
@@ -337,6 +336,7 @@ jobs:
contents: read
outputs:
should_run: ${{ steps.filter.outputs.should_run }}
test_files: ${{ steps.filter.outputs.test_files }}
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -344,25 +344,22 @@ jobs:
fetch-depth: 0
persist-credentials: false
- name: Filter E2E-relevant paths
- name: Filter changed E2E specs
id: filter
run: |
set -euo pipefail
BASE="${{ github.event.pull_request.base.sha }}"
HEAD="${{ github.event.pull_request.head.sha }}"
# Why: capture first so a failed git diff does not look like "no matches"
# (pipeline status in `if` is not aborted by set -e). Merge-base limits the
# list to files this PR introduced, not base-branch drift.
CHANGED="$(git diff --name-only --merge-base "$BASE" "$HEAD")"
# Why: tests/playwright.config.ts sits beside tests/e2e/, not inside it, so
# it needs its own pattern — a bare `playwright.` prefix matches no tracked
# file and would silently skip E2E when the runner config changes.
if printf '%s\n' "$CHANGED" | grep -E '^(tests/e2e/|tests/playwright\.|\.github/workflows/e2e\.yml$)' >/dev/null; then
CHANGED="$(git diff --name-only --diff-filter=AMCR --merge-base "$BASE" "$HEAD")"
TEST_FILES="$(printf '%s\n' "$CHANGED" | grep -E '^tests/e2e/.*\.spec\.ts$' || true)"
TEST_FILES_JSON="$(printf '%s\n' "$TEST_FILES" | jq --raw-input --slurp --compact-output 'split("\n") | map(select(length > 0))')"
echo "test_files=$TEST_FILES_JSON" >> "$GITHUB_OUTPUT"
if [ "$TEST_FILES_JSON" != '[]' ]; then
echo "should_run=true" >> "$GITHUB_OUTPUT"
echo "E2E path changes detected"
echo "Changed E2E specs: $TEST_FILES_JSON"
else
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "No E2E path changes"
echo "No changed E2E specs"
fi
e2e:
@@ -373,6 +370,8 @@ jobs:
permissions:
contents: read
uses: ./.github/workflows/e2e.yml
with:
test_files: ${{ needs.e2e-paths.outputs.test_files }}
verify:
if: always()
-20
View File
@@ -1,26 +1,6 @@
name: Terminal IME E2E
on:
pull_request:
paths:
- '.github/workflows/terminal-ime-e2e.yml'
- 'config/patches/@xterm__xterm@6.1.0-beta.287.patch'
- 'config/scripts/run-terminal-ibus-hangul-e2e.mjs'
- 'config/scripts/terminal-ime-e2e-workflow.test.mjs'
- 'package.json'
- 'pnpm-lock.yaml'
- 'src/renderer/src/components/terminal-pane/keyboard-handlers.ts'
- 'src/renderer/src/components/terminal-pane/keyboard-handlers-ime.test.tsx'
- 'src/renderer/src/components/terminal-pane/pty-connection.ts'
- 'src/renderer/src/components/terminal-pane/pty-connection.test.ts'
- 'src/renderer/src/components/terminal-pane/terminal-ime-*'
- 'src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts'
- 'src/renderer/src/components/terminal-pane/xterm-bypass-policy.ts'
- 'src/renderer/src/components/terminal-pane/xterm-bypass-policy.test.ts'
- 'tests/e2e/chinese-ime-chat-input-repro.spec.ts'
- 'tests/e2e/korean-ime-terminal-shift-enter-commit.spec.ts'
- 'tests/e2e/terminal-ibus-hangul-native.spec.ts'
- 'tests/e2e/terminal-ime-*.ts'
workflow_dispatch:
schedule:
- cron: '30 9 * * *'
+1 -47
View File
@@ -6,56 +6,10 @@ name: Windows Crash-Survival E2E
# silent-installs it, opens a terminal, force-kills ONLY the app main (no
# tree-kill), and asserts the daemon + shell stay alive, a relaunch adopts the
# same daemon and shell, and post-crash input causes no pwsh FailFast. Targeted
# pull requests keep it as a durable regression gate. A CI runner is the only
# manual runs keep it as a durable regression proof. A CI runner is the only
# safe place to install — see the relocation post-mortem.
on:
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review
paths:
- '.github/workflows/win-crash-survival-e2e.yml'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- 'electron.vite.config.ts'
- 'build-plugins/**'
- 'config/electron-builder.config.cjs'
- 'config/patches/**'
- 'config/scripts/ensure-native-runtime.mjs'
- 'config/scripts/rebuild-native-deps.mjs'
- 'config/scripts/verify-packaged-plugin-resources.cjs'
- 'native/**'
# Byte-hashed at package time, and CRLF-sensitive on Windows.
- '.gitattributes'
- 'resources/plugins/**'
- 'resources/win32/**'
- 'src/main/daemon/**'
- 'src/main/index.ts'
- 'src/main/ipc/pty*.ts'
- 'src/main/persistence.ts'
- 'src/main/providers/**'
- 'src/main/pty/**'
- 'src/main/startup/first-window-startup-services.ts'
- 'src/main/window/attach-main-window-services.ts'
- 'src/preload/**'
- 'src/renderer/src/App.tsx'
- 'src/renderer/src/components/terminal-pane/**'
- 'src/renderer/src/hooks/useIpcEvents.ts'
- 'src/renderer/src/lib/pane-manager/**'
- 'src/renderer/src/lib/session-write-subscriber.ts'
- 'src/renderer/src/lib/workspace-session-host-persistence.ts'
- 'src/renderer/src/store/slices/terminals.ts'
- 'src/shared/pty-session-id-format.ts'
- 'tools/win-crash-survival-e2e/**'
- 'tools/win-update-e2e/**'
# Why: source tests and benchmarks do not change the packaged artifact;
# their own verify jobs cover them without spending a Windows build slot.
- '!src/**/*.test.*'
- '!src/**/*.bench.*'
workflow_dispatch:
inputs:
expect:
@@ -1,41 +1,6 @@
name: Windows terminal restart E2E
on:
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review
paths:
- '.github/workflows/windows-terminal-restart-e2e.yml'
- 'package.json'
- 'pnpm-lock.yaml'
- 'electron.vite.config.ts'
- 'config/patches/**'
- 'config/scripts/ensure-native-runtime.mjs'
- 'config/scripts/rebuild-native-deps.mjs'
- 'tests/playwright.config.ts'
- 'tests/e2e/global-setup.ts'
- 'tests/e2e/global-teardown.ts'
- 'tests/e2e/helpers/**'
- 'tests/e2e/restart-restore-terminal-input.spec.ts'
- 'tests/e2e/restored-terminal-input-readiness.unit.test.ts'
- 'tests/e2e/terminal-probe-input-sequence.ts'
- 'tests/e2e/terminal-probe-input-sequence.unit.test.ts'
- 'tests/e2e/terminal-restart-persistence.spec.ts'
- 'src/main/daemon/**'
- 'src/main/ipc/pty*.ts'
- 'src/main/providers/**'
- 'src/main/pty/**'
- 'src/main/pty-descendant-termination.ts'
- 'src/main/windows-process-tree-kill.ts'
- 'src/main/windows-pty-root-identity.ts'
- 'src/preload/**'
- 'src/renderer/src/components/terminal-pane/**'
- 'src/renderer/src/lib/pane-manager/**'
- 'src/shared/process-table-snapshot.ts'
- 'src/shared/pty-session-id-format.ts'
workflow_dispatch:
inputs:
ref:
+5 -11
View File
@@ -225,20 +225,15 @@ describe('computer-use e2e workflow', () => {
)
})
it('runs Linux computer-use e2e in the PR native-smoke job under Xvfb', () => {
it('does not run computer-use e2e in PR smoke jobs', () => {
const workflow = parse(
readFileSync(join(projectDir, '.github/workflows/computer-e2e.yml'), 'utf8')
)
const nativeSmokeRuns = workflow.jobs['native-smoke'].steps
.map((step) => step.run)
.filter((run) => typeof run === 'string')
const installRun = nativeSmokeRuns.find((run) => run.includes('apt-get install'))
expect(installRun).toContain('gedit')
expect(installRun).toContain('xvfb')
expect(nativeSmokeRuns).toContain(
'xvfb-run --auto-servernum dbus-run-session -- pnpm test:e2e:computer --reporter=verbose tests/e2e/computer-linux.e2e.ts'
)
expect(nativeSmokeRuns.join('\n')).not.toContain('test:e2e:computer')
})
it('builds Electron main output before every computer-use e2e run', () => {
@@ -267,7 +262,7 @@ describe('computer-use e2e workflow', () => {
}
})
it('runs core Windows computer-use e2e in the PR native-smoke job', () => {
it('keeps computer-use e2e in scheduled jobs only', () => {
const workflow = parse(
readFileSync(join(projectDir, '.github/workflows/computer-e2e.yml'), 'utf8')
)
@@ -283,9 +278,8 @@ describe('computer-use e2e workflow', () => {
.filter((run) => typeof run === 'string')
]
expect(nativeSmokeRuns).toContain(
'pnpm test:e2e:computer --reporter=verbose tests/e2e/computer-windows.e2e.ts'
)
expect(nativeSmokeRuns.join('\n')).not.toContain('test:e2e:computer')
expect(allRuns.join('\n')).toContain('test:e2e:computer')
expect(allRuns.join('\n')).not.toContain('test:e2e:computer -- --reporter')
})
@@ -487,7 +487,7 @@ describe('Electron runtime package contract', () => {
expect(uploadStep.with.path).toBe('${{ env.ORCA_E2E_TERMINAL_PERF_REPORT_PATH }}')
})
it('keeps terminal rendering regressions in the fast golden E2E gate', () => {
it('keeps terminal rendering regressions in the manual golden E2E workflow', () => {
const packageScripts = packageJson.scripts
const goldenWorkflow = parse(
readFileSync(join(projectDir, '.github/workflows/golden-e2e-experiment.yml'), 'utf8')
@@ -511,7 +511,6 @@ describe('Electron runtime package contract', () => {
return steps.find((step) => step.name === `Run golden E2E tests on ${label}`)
})
const pullRequestPaths = goldenWorkflow.on.pull_request.paths
const releaseGoldenJob = releaseWorkflow.jobs['terminal-rendering-golden']
const releaseEvidenceJob = releaseWorkflow.jobs['terminal-rendering-release-evidence']
const releaseBuildNeeds = releaseWorkflow.jobs.build.needs
@@ -540,11 +539,8 @@ describe('Electron runtime package contract', () => {
for (const runStep of goldenRunSteps) {
expect(runStep?.run).toContain('pnpm run test:e2e:terminal-rendering-golden')
}
expect(pullRequestPaths).toContain('tests/e2e/terminal-raw-emoji-table-scroll-restore.spec.ts')
expect(pullRequestPaths).toContain('tests/e2e/terminal-webgl-atlas-budget.spec.ts')
expect(pullRequestPaths).toContain('config/patches/@xterm__addon-webgl@0.20.0-beta.286.patch')
expect(pullRequestPaths).toContain('tests/e2e/fixtures/terminal-emoji-table.md')
expect(pullRequestPaths).toContain('src/renderer/src/lib/pane-manager/**')
expect(goldenWorkflow.on.pull_request).toBeUndefined()
expect(goldenWorkflow.on.workflow_dispatch).toBeDefined()
expect(releaseBuildNeeds).not.toContain('terminal-rendering-golden')
expect(releaseBuildNeeds).not.toContain('terminal-rendering-release-evidence')
expect(publishReleaseNeeds).toContain('terminal-rendering-golden')
+39 -9
View File
@@ -5,9 +5,10 @@ import { parse } from 'yaml'
const projectDir = resolve(import.meta.dirname, '../..')
const prWorkflow = parse(readFileSync(join(projectDir, '.github/workflows/pr.yml'), 'utf8'))
const e2eWorkflow = parse(readFileSync(join(projectDir, '.github/workflows/e2e.yml'), 'utf8'))
const filterStep = prWorkflow.jobs['e2e-paths'].steps.find(
(step) => step.name === 'Filter E2E-relevant paths'
(step) => step.name === 'Filter changed E2E specs'
)
const verifyStep = prWorkflow.jobs.verify.steps.find(
(step) => step.name === 'Require successful checks'
@@ -25,7 +26,7 @@ describe('PR E2E gate contract', () => {
expect(verifyStep.run).not.toContain('$E2E')
})
it('runs E2E only when the detector says the PR touches E2E paths', () => {
it('passes only changed specs to the reusable E2E workflow', () => {
// Why: without this the job could lose its filter and run on every PR — the
// cost the path filter exists to avoid — while the gate assertions above
// stay green.
@@ -34,6 +35,10 @@ describe('PR E2E gate contract', () => {
expect(prWorkflow.jobs['e2e-paths'].outputs.should_run).toBe(
'${{ steps.filter.outputs.should_run }}'
)
expect(prWorkflow.jobs['e2e-paths'].outputs.test_files).toBe(
'${{ steps.filter.outputs.test_files }}'
)
expect(prWorkflow.jobs.e2e.with.test_files).toBe('${{ needs.e2e-paths.outputs.test_files }}')
})
it('enforces every job verify depends on', () => {
@@ -49,16 +54,41 @@ describe('PR E2E gate contract', () => {
}
})
it('matches the Playwright config where it actually lives', () => {
// Why: the config is tests/playwright.config.ts, beside tests/e2e/ rather
// than inside it. A bare `playwright.` prefix matches no tracked file, so
// editing the runner config would silently skip E2E.
expect(filterStep.run).toContain('tests/playwright\\.')
expect(filterStep.run).not.toMatch(/\(\^?\|\|]tests\/e2e\/\|playwright\\\./)
it('selects modified Playwright specs without running deleted tests', () => {
expect(filterStep.run).toContain('--diff-filter=AMCR')
expect(filterStep.run).toContain("'^tests/e2e/.*\\.spec\\.ts$'")
expect(filterStep.run).not.toContain('tests/playwright\\.')
})
it('uses one runner for changed specs and keeps full runs sharded', () => {
expect(e2eWorkflow.jobs.e2e.if).toBe("inputs.test_files == ''")
expect(e2eWorkflow.jobs['changed-e2e'].if).toBe("inputs.test_files != ''")
expect(e2eWorkflow.jobs['changed-e2e'].strategy).toBeUndefined()
expect(e2eWorkflow.jobs['ssh-docker-watcher-isolation'].if).toBe("inputs.test_files == ''")
const changedRun = e2eWorkflow.jobs['changed-e2e'].steps.find(
(step) => step.name === 'Run changed E2E specs'
)
expect(changedRun.env.TEST_FILES_JSON).toBe('${{ inputs.test_files }}')
expect(changedRun.run).toContain('pnpm run test:e2e "${TEST_FILES[@]}" --workers=1')
})
it('keeps dedicated E2E workflows out of pull request CI', () => {
const dedicatedWorkflows = [
'golden-e2e-experiment.yml',
'linux-wayland-gpu-sandbox.yml',
'terminal-ime-e2e.yml',
'win-crash-survival-e2e.yml',
'windows-terminal-restart-e2e.yml'
]
for (const file of dedicatedWorkflows) {
const workflow = parse(readFileSync(join(projectDir, '.github/workflows', file), 'utf8'))
expect(workflow.on.pull_request, file).toBeUndefined()
}
})
it('scopes detection to the PR range so base drift cannot false-trigger', () => {
expect(filterStep.run).toContain('git diff --name-only --merge-base "$BASE" "$HEAD"')
expect(filterStep.run).toContain('--merge-base "$BASE" "$HEAD"')
expect(filterStep.run).toContain('set -euo pipefail')
})
})
@@ -10,24 +10,10 @@ describe('terminal IME e2e workflow', () => {
readFileSync(join(projectDir, '.github/workflows/terminal-ime-e2e.yml'), 'utf8')
)
it('runs for xterm patch and terminal IME regression changes', () => {
expect(workflow.on.pull_request.paths).toEqual(
expect.arrayContaining([
'config/patches/@xterm__xterm@6.1.0-beta.287.patch',
'config/scripts/run-terminal-ibus-hangul-e2e.mjs',
'src/renderer/src/components/terminal-pane/keyboard-handlers.ts',
'src/renderer/src/components/terminal-pane/keyboard-handlers-ime.test.tsx',
'src/renderer/src/components/terminal-pane/pty-connection.ts',
'src/renderer/src/components/terminal-pane/pty-connection.test.ts',
'src/renderer/src/components/terminal-pane/terminal-ime-*',
'src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts',
'src/renderer/src/components/terminal-pane/xterm-bypass-policy.ts',
'src/renderer/src/components/terminal-pane/xterm-bypass-policy.test.ts',
'tests/e2e/korean-ime-terminal-shift-enter-commit.spec.ts',
'tests/e2e/terminal-ibus-hangul-native.spec.ts',
'tests/e2e/terminal-ime-*.ts'
])
)
it('runs only on schedule or manual dispatch', () => {
expect(workflow.on.pull_request).toBeUndefined()
expect(workflow.on.workflow_dispatch).toBeNull()
expect(workflow.on.schedule).toEqual([{ cron: '30 9 * * *' }])
})
it('installs native IBus Hangul and X11 input tools', () => {
+3 -12
View File
@@ -13,20 +13,11 @@ import { closeApp, resolveElectronMainPid } from '../../tools/win-update-e2e/app
import { isPidAlive } from '../../tools/win-update-e2e/daemon-processes.mjs'
describe('win-crash-survival-e2e proof contracts', () => {
it('keeps the packaged proof wired as a targeted pull-request gate', () => {
it('keeps the packaged proof manually dispatchable without a PR trigger', () => {
const workflow = readFileSync('.github/workflows/win-crash-survival-e2e.yml', 'utf8')
expect(workflow).toMatch(/^ pull_request:/m)
expect(workflow).not.toMatch(/^ pull_request:/m)
expect(workflow).toMatch(/^ workflow_dispatch:/m)
expect(workflow).not.toMatch(/^ push:/m)
expect(workflow).toContain("- 'src/main/daemon/**'")
expect(workflow).toContain("- 'src/main/index.ts'")
expect(workflow).toContain("- 'src/main/ipc/pty*.ts'")
expect(workflow).toContain("- 'src/main/startup/first-window-startup-services.ts'")
expect(workflow).toContain("- 'src/main/window/attach-main-window-services.ts'")
expect(workflow).toContain("- 'src/preload/**'")
expect(workflow).toContain("- 'src/renderer/src/components/terminal-pane/**'")
expect(workflow).toContain("- 'src/renderer/src/store/slices/terminals.ts'")
expect(workflow).toContain("- '!src/**/*.test.*'")
expect(workflow).toContain("- '!src/**/*.bench.*'")
expect(workflow).toContain('--expect "$env:EXPECT"')
expect(workflow).toContain('exit $LASTEXITCODE')
expect(workflow).toContain("'!config/**/*.test.*'")