test: run localhost SSH terminal and hooks in CI

This commit is contained in:
Neil
2026-09-06 09:32:28 -07:00
parent f5960cec00
commit 3ba65b44bf
4 changed files with 100 additions and 2 deletions
+63
View File
@@ -229,6 +229,7 @@ jobs:
. != "tests/e2e/paired-startup-exec-readiness.spec.ts" and
. != "tests/e2e/local-ssh-browser-routing.spec.ts" and
. != "tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts" and
. != "tests/e2e/ssh-localhost.spec.ts" and
. != "tests/e2e/ssh-client-hosted-browser-drop-reconnect.spec.ts" and
. != "tests/e2e/ssh-docker-bulk-open-freeze-repro.spec.ts" and
. != "tests/e2e/terminal-ibus-hangul-native.spec.ts"
@@ -375,3 +376,65 @@ jobs:
ORCA_BACKGROUND_LAUNCH: '1'
ORCA_RUN_DOCKER_SSH_BROWSER_E2E: '1'
run: node_modules/.bin/vitest run --config config/vitest.config.ts tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts
ssh-localhost:
name: localhost SSH terminal and hooks
needs: [build, prepare-native-cache]
if: inputs.test_files == '' || contains(inputs.test_files, 'tests/e2e/ssh-localhost.spec.ts')
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- name: Install SSH server and headless tools
run: sudo apt-get update && sudo apt-get install -y build-essential openssh-client openssh-server python3 ripgrep xvfb zsh openbox x11-utils
- uses: ./.github/actions/install-node-dependencies
with:
native-runtime: electron
- uses: actions/download-artifact@v8
with:
name: e2e-build-out
path: out/
- name: Start isolated localhost SSH server
shell: bash
run: |
# Bare shells install Pi extensions only for an existing agent home.
mkdir -p "$HOME/.pi/agent"
fixture="$RUNNER_TEMP/orca-localhost-sshd"
mkdir -p "$fixture"
ssh-keygen -q -t ed25519 -N '' -f "$fixture/host_key"
ssh-keygen -q -t ed25519 -N '' -f "$fixture/client_key"
cat > "$fixture/sshd_config" <<EOF
Port 22222
ListenAddress 127.0.0.1
HostKey $fixture/host_key
PidFile $fixture/sshd.pid
AuthorizedKeysFile $fixture/client_key.pub
StrictModes no
PasswordAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
AllowUsers $(id -un)
Subsystem sftp internal-sftp
EOF
sudo mkdir -p /run/sshd
sudo /usr/sbin/sshd -f "$fixture/sshd_config" -E "$fixture/sshd.log"
ssh -i "$fixture/client_key" -p 22222 -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 127.0.0.1 true || { sudo cat "$fixture/sshd.log"; exit 1; }
echo "ORCA_E2E_SSH_PORT=22222" >> "$GITHUB_ENV"
echo "ORCA_E2E_SSH_USER=$(id -un)" >> "$GITHUB_ENV"
echo "ORCA_E2E_SSH_IDENTITY_FILE=$fixture/client_key" >> "$GITHUB_ENV"
- name: Run localhost SSH terminal and hook journey
env:
SKIP_BUILD: '1'
ORCA_E2E_SSH_LOCALHOST: '1'
ORCA_FEATURE_REMOTE_AGENT_HOOKS: '1'
ORCA_E2E_FORWARD_APP_LOGS: '1'
run: xvfb-run --auto-servernum bash .github/scripts/e2e-with-window-manager.sh pnpm exec playwright test --config tests/playwright.config.ts tests/e2e/ssh-localhost.spec.ts --project=electron-headless --workers=1
- uses: actions/upload-artifact@v7
if: failure()
with:
name: localhost-ssh-traces
path: test-results/
retention-days: 7
if-no-files-found: ignore
@@ -13,6 +13,7 @@ const EXPECTED_MATRIX = {
'.github/workflows/e2e.yml#e2e': { contents: 'read' },
'.github/workflows/e2e.yml#prepare-native-cache': { contents: 'read' },
'.github/workflows/e2e.yml#ssh-browser-network-route': { contents: 'read' },
'.github/workflows/e2e.yml#ssh-localhost': { contents: 'read' },
'.github/workflows/e2e.yml#ssh-docker-watcher-isolation': { contents: 'read' },
'.github/workflows/homebrew-bump.yml#bump-cask': { contents: 'read' },
'.github/workflows/release-mac-build.yml#build-mac': { contents: 'write' },
+1 -2
View File
@@ -48,10 +48,9 @@ if (runtime.status !== 0) {
// - E2E does not gate merges: `verify.needs` in pr.yml omits `e2e` while the suite is red on
// main. Nothing in this lane blocks a PR yet. pr.yml's Require-successful-checks comment
// has the exact wiring to flip it, and the gate contract asserts the current state.
// - Three specs are gated on env vars no workflow sets, so they run nowhere
// - Two specs are gated on env vars no workflow sets, so they run nowhere
// and are not Docker-gated, which puts them outside this file's contract:
// nested-runtime-ssh-lifecycle, nested-runtime-ssh-routing (ORCA_E2E_NESTED_RUNTIME_SSH)
// ssh-localhost (ORCA_E2E_SSH_LOCALHOST)
// The nested-runtime runner remains unused by CI.
const result = spawnSync(
pnpm,
@@ -0,0 +1,35 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { parse } from 'yaml'
import { expect, it } from 'vitest'
const workflow = parse(
readFileSync(resolve(import.meta.dirname, '../../.github/workflows/e2e.yml'), 'utf8')
)
it('gives the localhost SSH journey its same-filesystem server and agent prerequisite', () => {
const spec = 'tests/e2e/ssh-localhost.spec.ts'
const job = workflow.jobs['ssh-localhost']
expect(job.if).toContain("inputs.test_files == ''")
expect(job.if).toContain(spec)
expect(job['runs-on']).toBe('ubuntu-latest')
expect(job.needs).toEqual(['build', 'prepare-native-cache'])
const setup = job.steps.find((step) => step.name === 'Start isolated localhost SSH server')
expect(setup.run).toContain('ListenAddress 127.0.0.1')
expect(setup.run).toContain('PasswordAuthentication no')
expect(setup.run).toContain('UsePAM yes')
expect(setup.run).toContain('mkdir -p "$HOME/.pi/agent"')
for (const key of ['ORCA_E2E_SSH_PORT', 'ORCA_E2E_SSH_USER', 'ORCA_E2E_SSH_IDENTITY_FILE']) {
expect(setup.run).toContain(key)
}
const run = job.steps.find((step) => step.name === 'Run localhost SSH terminal and hook journey')
expect(run.env.ORCA_E2E_SSH_LOCALHOST).toBe('1')
expect(run.env.ORCA_FEATURE_REMOTE_AGENT_HOOKS).toBe('1')
expect(run.run).toContain(spec)
expect(run.run).toContain('--project=electron-headless')
expect(run.run).not.toContain('--retries')
expect(run['continue-on-error']).toBeUndefined()
expect(
workflow.jobs['changed-e2e'].steps.find((step) => step.name === 'Run changed E2E specs').run
).toContain(`. != "${spec}"`)
})