Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8306d42
test(ssh): prove connect-time conversion to managed orcad on real Lin…
Oct 3, 2026
1859334
fix(e2e): read the SSH host's session partition, provision the conver…
Oct 3, 2026
6095e4c
test(e2e): report the full relay state when the convert poll times out
Oct 3, 2026
da319e6
test(e2e): require the relay to list no terminals before the converti…
Oct 3, 2026
9b42048
test(e2e): require no running-terminal lease before the converting co…
Oct 3, 2026
4abde34
test(e2e): report the host's terminal leases when the converting conn…
Oct 3, 2026
cd8f181
test(e2e): end the relay era with no relay shell left to respawn
Oct 3, 2026
65e5956
test(e2e): settle before the converting connect and name the tabs a b…
Oct 3, 2026
83a28b7
test(e2e): use the exited relay tab as the session tab, since any mou…
Oct 3, 2026
83fe28d
test(e2e): carry an editor tab through the conversion instead of a te…
Oct 3, 2026
41f16bd
test(e2e): log the conversion census inputs before the converting con…
Oct 3, 2026
b2056b4
fix(orcad): log which state blocked a refused conversion
Oct 3, 2026
f647fb1
test(e2e): log both session partitions before the converting connect
Oct 3, 2026
8e1d9a0
fix(orcad): a source partition's copy of focus on another host no lon…
Oct 3, 2026
cdbee1d
fix(ssh): an ssh2 forward on port 0 reports the port it bound, so man…
Oct 3, 2026
1b08cba
test(e2e): give the conversion its full budget again
Oct 3, 2026
c0df428
test(e2e): report the migration journal phase when the conversion stalls
Oct 3, 2026
f56901c
test(e2e): report the connect's own result and main's state when the …
Oct 3, 2026
b2e9191
fix(ssh): a converted host's managed state reaches the renderer inste…
Oct 3, 2026
a8b4060
test(e2e): print a failed server call's response
Oct 3, 2026
8d012bd
test(e2e): give server calls the budget a fresh server's first invent…
Oct 3, 2026
58fc63f
test(e2e): read the converted worktree's tabs with a scoped session.t…
Oct 3, 2026
430e40d
test(e2e): log the converted worktree's tabs instead of asserting the…
Oct 3, 2026
ae45b7d
test(e2e): prove retirement by the dropped source rows; the journal c…
Oct 3, 2026
301cefd
test(e2e): drop the conversion diagnostics now the cell passes
Oct 3, 2026
8e93409
test(e2e): fail a hung disconnect or connect with main's state instea…
Oct 3, 2026
6a89f19
test(e2e): convert an upgraded relay-era profile's host on its first …
Oct 3, 2026
09bca7c
test(e2e): seed the relay-era target the way addTarget registers it
Oct 3, 2026
5a049b6
fix(ssh): a stale ssh2 forward drops a late connection instead of cra…
Oct 3, 2026
5be7450
fix(orcad): the active-slot readiness probe reads Windows hosts throu…
Oct 3, 2026
e2bc760
ci(ssh-windows): let only the convert cell's account open the SSH loc…
Oct 3, 2026
3c59a25
test(e2e): match server paths in their JSON-escaped form, for Windows…
Oct 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,8 @@ jobs:
. != "tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts" and
. != "tests/e2e/ssh-localhost.spec.ts" and
. != "tests/e2e/terminal-ibus-hangul-native.spec.ts" and
. != "tests/e2e/orcad-serve-mode-switch.spec.ts"
. != "tests/e2e/orcad-serve-mode-switch.spec.ts" and
. != "tests/e2e/ssh-orcad-auto-convert.spec.ts"
)' <<<"$TEST_FILES_JSON" > "$RUNNER_TEMP/general-e2e-specs"
fi
mapfile -t TEST_FILES < "$RUNNER_TEMP/general-e2e-specs"
Expand Down Expand Up @@ -551,6 +552,56 @@ jobs:
retention-days: 7
if-no-files-found: ignore

# #24979 on a real host: a relay-era Docker host converts to managed orcad on connect. Needs the
# orcad template for the fixture's target (Debian, linux-x64-glibc), which only this job builds.
orcad-auto-convert-docker:
name: ssh host auto-converts to managed orcad (Docker)
needs: [build, prepare-native-cache]
if: inputs.test_files == '' || inputs.ssh_source_changed == 'true' || contains(inputs.test_files, 'tests/e2e/ssh-orcad-auto-convert.spec.ts')
runs-on: ubuntu-latest
timeout-minutes: 45
env:
ORCA_BACKGROUND_LAUNCH: '1'
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
persist-credentials: false
- name: Install headless tools
run: sudo apt-get update && sudo apt-get install -y build-essential ripgrep xvfb 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/
# Built to a path the app does not look at by default, so the relay phase has no template.
- name: Build the linux-x64-glibc orcad template
run: |
pnpm build:orcad-prebuilds
pnpm build:orcad-prebuilds --require-slots linux-x64-glibc
pnpm build:orcad
node config/scripts/build-orcad-template.mjs --targets linux-x64-glibc
mv out/orcad-template "$RUNNER_TEMP/orcad-convert-template"
- name: Convert a relay-era Docker host
env:
SKIP_BUILD: '1'
ORCA_E2E_SSH_DOCKER: '1'
ORCA_E2E_ORCAD_CONVERT_HOST: docker
ORCA_E2E_FORWARD_APP_LOGS: '1'
ORCA_RELAY_PATH: ${{ github.workspace }}/out/relay
run: |
export ORCA_E2E_ORCAD_CONVERT_TEMPLATE="$RUNNER_TEMP/orcad-convert-template"
xvfb-run --auto-servernum bash .github/scripts/e2e-with-window-manager.sh pnpm exec playwright test --config tests/playwright.config.ts tests/e2e/ssh-orcad-auto-convert.spec.ts --project=electron-headless --workers=1
- uses: actions/upload-artifact@v7
if: failure()
with:
name: orcad-auto-convert-docker-traces
path: test-results/
retention-days: 7
if-no-files-found: ignore

ssh-localhost:
name: localhost SSH terminal and hooks
needs: [build, prepare-native-cache]
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/ssh-windows-hosts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ on:
- '!src/**/*.test.ts'
- 'src/main/ssh/ssh-relay-windows-host-lane.test.ts'
- 'src/main/ssh/orcad-windows-host-lane.test.ts'
- 'src/main/ipc/ssh-host-server-*'
- 'tests/e2e/ssh-orcad-auto-convert.spec.ts'
- 'tests/e2e/helpers/orcad-convert-host.ts'
- 'tests/e2e/helpers/orcad-convert-flow.ts'
- 'tests/e2e/helpers/orcad-upgrade-profile.ts'
- 'config/ci/windows-ssh-provider/**'
- '.github/workflows/ssh-windows-hosts.yml'
- '.github/actions/prepare-orcad-prebuilds/**'
Expand Down Expand Up @@ -150,6 +155,10 @@ jobs:
New-Item -ItemType Directory -Force -Path $receipts | Out-Null
$cells=@($env:CELLS -split ',' | ForEach-Object {$_.Trim()} | Where-Object {$_})
if(-not $cells.Count){$cells=@('pinned-cmd','pinned-powershell','legacy-opt-out','orcad-cmd','orcad-powershell')}
# One Windows host runs the app-level conversion; it is last because it switches native modules.
if(-not $env:CELLS -and '${{ matrix.arch }}' -eq 'x64' -and '${{ matrix.server }}' -eq 'inbox'){$cells+='orcad-convert'}
Comment thread
pullfrog[bot] marked this conversation as resolved.
Resolved
# The managed server is reached through an SSH local forward, so only the convert cell's account may open one.
$forwarding=if($cells[-1] -eq 'orcad-convert'){1}else{0}
$archive=''
$preparation=''
if('${{ matrix.server }}' -eq 'inbox' -and '${{ matrix.arch }}' -eq 'arm64'){$preparation=Join-Path $receipts 'inbox-capability-preparation.json'}
Expand All @@ -162,7 +171,7 @@ jobs:
$callback={param($context)
& (Join-Path $tools 'invoke-pinned-relay-cells.ps1') -SourceRoot $sourceRoot -Context $context -Target 'win32-${{ matrix.arch }}' -ReceiptRoot $receipts -Cells $cells
}.GetNewClosure()
& (Join-Path $tools 'preview-ssh/prove-preview-openssh.ps1') -Archive $archive -Arch '${{ matrix.arch }}' -Server '${{ matrix.server }}' -Receipt (Join-Path $receipts 'provider-server.json') -InboxPreparationReceipt $preparation -Accounts $cells.Count -HiddenTools @('npm','npx','node-gyp','gcc','g++','cc','c++','make','cl','clang','clang++','msbuild','cmake') -HostCellProbe $callback 2>&1 | Tee-Object (Join-Path $receipts 'provision.log')
& (Join-Path $tools 'preview-ssh/prove-preview-openssh.ps1') -Archive $archive -Arch '${{ matrix.arch }}' -Server '${{ matrix.server }}' -Receipt (Join-Path $receipts 'provider-server.json') -InboxPreparationReceipt $preparation -Accounts $cells.Count -ForwardingAccounts $forwarding -HiddenTools @('npm','npx','node-gyp','gcc','g++','cc','c++','make','cl','clang','clang++','msbuild','cmake') -HostCellProbe $callback 2>&1 | Tee-Object (Join-Path $receipts 'provision.log')
- uses: actions/upload-artifact@v7
if: always()
with:
Expand Down
40 changes: 33 additions & 7 deletions config/ci/windows-ssh-provider/invoke-pinned-relay-cells.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ param(
[Parameter(Mandatory=$true)][hashtable]$Context,
[Parameter(Mandatory=$true)][ValidateSet('win32-arm64','win32-x64')][string]$Target,
[Parameter(Mandatory=$true)][string]$ReceiptRoot,
[ValidateSet('pinned-cmd','pinned-powershell','legacy-opt-out','orcad-cmd','orcad-powershell')][string[]]$Cells=@('pinned-cmd','pinned-powershell','legacy-opt-out','orcad-cmd','orcad-powershell')
[ValidateSet('pinned-cmd','pinned-powershell','legacy-opt-out','orcad-cmd','orcad-powershell','orcad-convert')][string[]]$Cells=@('pinned-cmd','pinned-powershell','legacy-opt-out','orcad-cmd','orcad-powershell')
)
$ErrorActionPreference='Stop'
if($env:GITHUB_ACTIONS -ne 'true' -or $env:ORCA_ISOLATED_SSH_CI -ne '1'){throw 'Disposable CI only'}
$shells=@{'pinned-cmd'='cmd';'pinned-powershell'='powershell';'legacy-opt-out'='cmd';'orcad-cmd'='cmd';'orcad-powershell'='powershell'}
$shells=@{'pinned-cmd'='cmd';'pinned-powershell'='powershell';'legacy-opt-out'='cmd';'orcad-cmd'='cmd';'orcad-powershell'='powershell';'orcad-convert'='cmd'}
if($Context.accounts.Count -lt $Cells.Count){throw 'Each cell needs its own private account'}
if(-not $Context.forbiddenToolLog){throw 'Run the provisioning with -HiddenTools so toolchain calls are logged'}
$openSshKey='HKLM:\SOFTWARE\OpenSSH'
Expand Down Expand Up @@ -53,6 +53,28 @@ function Test-PrivateWmiLaunch([string]$Account) {
if($match.Success){return $match.Groups[1].Value}else{return 'no-output'}
}

# The app converts a relay-era host on connect (tests/e2e/ssh-orcad-auto-convert.spec.ts). Last in
# the run: it switches native modules to Electron's ABI, which the vitest cells cannot load.
function Invoke-ConvertCell($Account,[string]$Descriptor,[string]$Log) {
$ready=Invoke-PrivateSsh $Account.name 'git init -q orca-convert-repo && git -C orca-convert-repo -c user.name=orca -c user.email=orca@example.invalid commit -q --allow-empty -m init && echo ORCA_REPO_READY'
if($ready -notmatch 'ORCA_REPO_READY'){throw 'Could not create the convert cell repository as the account'}
# Out of the app's default lookup, so the relay phase runs without a template.
$template=Join-Path $env:RUNNER_TEMP 'orcad-convert-template'
Copy-Item -LiteralPath 'out\orcad-template' -Destination $template -Recurse -Force
Rename-Item -LiteralPath 'out\orcad-template' -NewName 'orcad-template.convert-hidden'
try {
& node config/scripts/ensure-native-runtime.mjs --runtime=electron 2>&1 | Tee-Object -FilePath $Log | Out-Host
& pnpm exec electron-vite build --mode e2e 2>&1 | Tee-Object -FilePath $Log -Append | Out-Host
$env:ORCA_E2E_ORCAD_CONVERT_HOST=$Descriptor;$env:ORCA_E2E_ORCAD_CONVERT_TEMPLATE=$template;$env:SKIP_BUILD='1'
& pnpm exec playwright test --config tests/playwright.config.ts tests/e2e/ssh-orcad-auto-convert.spec.ts --project=electron-headless --workers=1 2>&1 | Tee-Object -FilePath $Log -Append | Out-Host
# Functions return uncaptured output, so only the exit code may reach the caller.
return $global:LASTEXITCODE
} finally {
Remove-Item Env:ORCA_E2E_ORCAD_CONVERT_HOST,Env:ORCA_E2E_ORCAD_CONVERT_TEMPLATE,Env:SKIP_BUILD -ErrorAction SilentlyContinue
Rename-Item -LiteralPath 'out\orcad-template.convert-hidden' -NewName 'orcad-template'
}
}

New-Item -ItemType Directory -Force -Path $ReceiptRoot | Out-Null
Push-Location $SourceRoot
try {
Expand All @@ -78,11 +100,15 @@ try {
@{cell=$cell;target=$Target;host='127.0.0.1';port=[int]$Context.port;username=$account.name;identityFile=$Context.identityFile;home=$account.home;forbiddenToolLog=$Context.forbiddenToolLog;receipt=(Join-Path $ReceiptRoot "$cell.json")} | ConvertTo-Json | Set-Content -LiteralPath $descriptor -Encoding utf8NoBOM
$env:ORCA_RUN_SSH_WINDOWS_HOST='1';$env:ORCA_SSH_WINDOWS_HOST_CELL=$descriptor
Write-Host "Windows host cell $cell ($Target, DefaultShell $shell, account $($account.name))"
# orcad cells deploy managed orcad instead of the relay; same account and descriptor shape.
$lane=if($cell.StartsWith('orcad-')){'src/main/ssh/orcad-windows-host-lane.test.ts'}else{'src/main/ssh/ssh-relay-windows-host-lane.test.ts'}
& node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts $lane --reporter=verbose 2>&1 | Tee-Object -FilePath (Join-Path $ReceiptRoot "$cell.log")
# Why global: under the workflow's GetNewClosure callback, bare $LASTEXITCODE reads a stale captured copy.
$code=$global:LASTEXITCODE
if($cell -eq 'orcad-convert'){
$code=Invoke-ConvertCell $account $descriptor (Join-Path $ReceiptRoot "$cell.log")
} else {
# orcad cells deploy managed orcad instead of the relay; same account and descriptor shape.
$lane=if($cell.StartsWith('orcad-')){'src/main/ssh/orcad-windows-host-lane.test.ts'}else{'src/main/ssh/ssh-relay-windows-host-lane.test.ts'}
& node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts $lane --reporter=verbose 2>&1 | Tee-Object -FilePath (Join-Path $ReceiptRoot "$cell.log")
# Why global: under the workflow's GetNewClosure callback, bare $LASTEXITCODE reads a stale captured copy.
$code=$global:LASTEXITCODE
}
# The relay's own log is the only record of why it closed a client.
foreach($log in @(Get-ChildItem -Path (Join-Path $account.home '.orca-remote\relay-*\relay*.log'),(Join-Path $account.home '.orca-remote\orcad-*\orcad.log') -File -ErrorAction SilentlyContinue)){Copy-Item -LiteralPath $log.FullName -Destination (Join-Path $ReceiptRoot "$cell.$($log.Directory.Name).$($log.Name)")}
if(Test-Path -LiteralPath $Context.forbiddenToolLog){Copy-Item -LiteralPath $Context.forbiddenToolLog -Destination (Join-Path $ReceiptRoot "$cell.forbidden-tool-calls.log")}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# -HiddenTools: the private accounts are denied every machine PATH directory holding one of these
# executables, and their own PATH carries logging shims for them, so SSH sessions have no host toolchain.
# -HostCellProbe receives a context hashtable (accounts, port, keys, shim log) once provisioning passes.
param([Parameter(Mandatory=$true)][string]$Receipt,[string]$Archive,[Parameter(Mandatory=$true)][ValidateSet('arm64','x64')][string]$Arch,[ValidateSet('preview','inbox')][string]$Server='preview',[scriptblock]$ProductionRouteProbe,[ValidateRange(1,5)][int]$Accounts=1,[string[]]$HiddenTools=@(),[scriptblock]$HostCellProbe,[string]$InboxPreparationReceipt)
param([Parameter(Mandatory=$true)][string]$Receipt,[string]$Archive,[Parameter(Mandatory=$true)][ValidateSet('arm64','x64')][string]$Arch,[ValidateSet('preview','inbox')][string]$Server='preview',[scriptblock]$ProductionRouteProbe,[ValidateRange(1,6)][int]$Accounts=1,[ValidateRange(0,6)][int]$ForwardingAccounts=0,[string[]]$HiddenTools=@(),[scriptblock]$HostCellProbe,[string]$InboxPreparationReceipt)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'windows-ssh-capability.ps1')
$target=@{arm64=@{os='Arm64';folder='OpenSSH-ARM64';machine='0xAA64';archive='698c6aec31c1dd0fb996206e8741f4531a97355686b5431ef347d531b07fcd42'};x64=@{os='X64';folder='OpenSSH-Win64';machine='0x8664';archive='23f50f3458c4c5d0b12217c6a5ddfde0137210a30fa870e98b29827f7b43aba5'}}[$Arch]
Expand Down Expand Up @@ -246,6 +246,7 @@ PermitTunnel no
PermitTTY no
Subsystem sftp "$sftpServerPosix"
LogLevel DEBUG1
$(@($accountNames | Select-Object -Last $ForwardingAccounts | ForEach-Object {"Match User $_`n AllowTcpForwarding local"}) -join "`n")
"@ | Set-Content -LiteralPath $config -Encoding ascii
Write-Stage 'server-config-validate-start'
Invoke-Bounded $sshd @('-t','-f',$config) | Out-Null
Expand Down
5 changes: 4 additions & 1 deletion config/scripts/ci-e2e-job-selection.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@ export const LOCALHOST_SSH_E2E_SPEC = 'tests/e2e/ssh-localhost.spec.ts'
export const NATIVE_IME_E2E_SPEC = 'tests/e2e/terminal-ibus-hangul-native.spec.ts'
// Needs the packaged orcad slot, which only its own job builds.
export const ORCAD_SERVE_MODE_SWITCH_E2E_SPEC = 'tests/e2e/orcad-serve-mode-switch.spec.ts'
// Needs the orcad template for its host's target, which only its own job builds.
export const ORCAD_AUTO_CONVERT_E2E_SPEC = 'tests/e2e/ssh-orcad-auto-convert.spec.ts'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dedicated spec depends on build/prepare-native-cache like ORCAD_SERVE_MODE_SWITCH_E2E_SPEC, but it was not added to classifyE2eJobs's e2e_needs_build specs.some(...) list (lines 85-90). A PR that only edits tests/e2e/ssh-orcad-auto-convert.spec.ts (or orcad-convert-host.ts) yields e2e_needs_build=false, so build/prepare-native-cache skip and the dependent orcad-auto-convert-docker job is skipped despite contains(inputs.test_files, …) being true. Add spec === ORCAD_AUTO_CONVERT_E2E_SPEC there and cover it in ci-e2e-job-selection.test.mjs's build-prerequisite case.

Technical details
# Dedicated Docker job never runs on test-only edits

## Affected sites
- `config/scripts/ci-e2e-job-selection.mjs:85-90` — `e2e_needs_build` list omits the new spec.
- `config/scripts/ci-e2e-job-selection.test.mjs:31-37` — build-prerequisite iteration omits both orcad specs.
- `.github/workflows/e2e.yml:560` — job `if` cannot rescue a skipped `needs`.

## Required outcome
- Editing only the spec or its helper still runs `orcad-auto-convert-docker`.

## Suggested approach
- Add `spec === ORCAD_AUTO_CONVERT_E2E_SPEC` to the OR-list and extend the test iteration.

export const DEDICATED_E2E_SPECS = [
...DOCKER_SSH_E2E_SPECS,
NODE_NETWORK_E2E_SPEC,
LOCALHOST_SSH_E2E_SPEC,
NATIVE_IME_E2E_SPEC,
ORCAD_SERVE_MODE_SWITCH_E2E_SPEC
ORCAD_SERVE_MODE_SWITCH_E2E_SPEC,
ORCAD_AUTO_CONVERT_E2E_SPEC
]
const dedicatedSpecs = new Set(DEDICATED_E2E_SPECS)
const dockerSpecs = new Set(DOCKER_SSH_E2E_SPECS)
Expand Down
9 changes: 9 additions & 0 deletions config/scripts/pr-e2e-source-routing.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ export const PR_E2E_SOURCE_ROUTES = [
file
)
},
{
id: 'ssh.orcad-auto-convert',
specs: ['tests/e2e/ssh-orcad-auto-convert.spec.ts'],
matches: (file) =>
isProductSource(file) &&
/^src\/main\/(?:ipc\/ssh-host-server-|ssh\/(?:ssh-host-server-|orcad-runtime-conversion|orcad-migration-|orcad-retained-source|orcad-runtime-deployment))/.test(
file
)
},
{
id: 'ssh.localhost-agent-hooks',
specs: ['tests/e2e/ssh-localhost.spec.ts'],
Expand Down
1 change: 1 addition & 0 deletions config/scripts/release-cut-token-permissions.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const EXPECTED_MATRIX = {
'.github/workflows/e2e.yml#build': { contents: 'read' },
'.github/workflows/e2e.yml#changed-e2e': { contents: 'read' },
'.github/workflows/e2e.yml#e2e': { contents: 'read' },
'.github/workflows/e2e.yml#orcad-auto-convert-docker': { contents: 'read' },
'.github/workflows/e2e.yml#orcad-serve-mode-switch': { contents: 'read' },
'.github/workflows/e2e.yml#prepare-native-cache': { contents: 'read' },
'.github/workflows/e2e.yml#ssh-browser-network-route': { contents: 'read' },
Expand Down
1 change: 1 addition & 0 deletions config/scripts/ssh-docker-ci-sharding.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ it('gives every removed SSH spec a dedicated owner even for test-only edits', ()
'tests/e2e/orcad-serve-mode-switch.spec.ts',
'tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts',
'tests/e2e/ssh-localhost.spec.ts',
'tests/e2e/ssh-orcad-auto-convert.spec.ts',
'tests/e2e/terminal-ibus-hangul-native.spec.ts'
])
})
Expand Down
18 changes: 18 additions & 0 deletions config/scripts/ssh-windows-hosts-workflow.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { parse } from 'yaml'
import {
WINDOWS_FORBIDDEN_TOOLS,
WINDOWS_HOST_CELL_IDS,
WINDOWS_CONVERT_CELL_ID,
WINDOWS_ORCAD_CELL_IDS
} from '../../src/main/ssh/ssh-windows-host-cells.ts'

Expand Down Expand Up @@ -184,4 +185,21 @@ describe('SSH Windows-host workflow', () => {
}
expect(invoker).toContain('src/main/ssh/orcad-windows-host-lane.test.ts')
})

it('provisions one private account for every cell, convert cell included', () => {
expect(runStep.run).toContain(`$cells+='${WINDOWS_CONVERT_CELL_ID}'`)
// Only the convert cell reaches a managed server, through an SSH local forward.
expect(runStep.run).toContain(
`$forwarding=if($cells[-1] -eq '${WINDOWS_CONVERT_CELL_ID}'){1}else{0}`
)
expect(runStep.run).toContain('-ForwardingAccounts $forwarding')
const provisioner = readFileSync(
join(projectDir, 'config/ci/windows-ssh-provider/preview-ssh/prove-preview-openssh.ps1'),
'utf8'
)
const max = Number(/\[ValidateRange\(1,(\d+)\)\]\[int\]\$Accounts/.exec(provisioner)?.[1])
expect(max).toBeGreaterThanOrEqual(
WINDOWS_HOST_CELL_IDS.length + WINDOWS_ORCAD_CELL_IDS.length + 1
)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@ const MANIFEST: OrcadMigrationManifest = {
}

describe('orcad migration source dependency census', () => {
it('ignores client focus on another host copied into the source host partition', () => {
const state = getDefaultPersistedState('/home/test')
state.sshTargets = [TARGET]
state.repos = [REPO]
state.folderWorkspaces = [FOLDER]
const localWorktreeId = 'local-repo::/home/test/local'
state.workspaceSession = { ...state.workspaceSession, activeWorktreeId: localWorktreeId }
state.workspaceSessionsByHostId = {
[`ssh:${TARGET.id}`]: {
...state.workspaceSession,
activeWorktreeId: localWorktreeId,
activeWorkspaceKey: worktreeWorkspaceKey(localWorktreeId)
}
}

expect(collectOrcadMigrationSourceDependencyCensus(state, MANIFEST)).toMatchObject({
totalCount: 0
})
})

it('allows a static catalog with no unrepresented dependent state', () => {
const state = getDefaultPersistedState('/home/test')
state.sshTargets = [TARGET]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,12 @@ export function countUnsupportedSessionState(
!(sourceHostPartition && scope.repoIds.has(session.activeRepoId))
? 1
: 0
// Why not in the source partition: there focus is a copy of the client-wide focus. An in-scope
// copy is carried; one aimed at another host's workspace is not host state and is never carried.
count +=
session.activeWorktreeId &&
matches(session.activeWorktreeId) &&
!(sourceHostPartition && orcadMigrationOwnerMatchesScope(session.activeWorktreeId, scope))
? 1
: 0
!sourceHostPartition && session.activeWorktreeId && owns(session.activeWorktreeId) ? 1 : 0
count +=
session.activeWorkspaceKey &&
matches(session.activeWorkspaceKey) &&
!(sourceHostPartition && orcadMigrationOwnerMatchesScope(session.activeWorkspaceKey, scope))
? 1
: 0
!sourceHostPartition && session.activeWorkspaceKey && owns(session.activeWorkspaceKey) ? 1 : 0
count += session.activeWorkspaceExecutionHostId === scope.hostId && !sourceHostPartition ? 1 : 0
// activeConnectionIdsAtShutdown is not counted: it is the renderer's live "connected now" hint, and
// the remote work it can stand for (tab PTYs, remote session ids, leases) is counted on its own.
Expand Down
Loading
Loading