Merge remote-tracking branch 'origin/main' into OrcaWin/node-rt-phase3

This commit is contained in:
m4air
2026-10-02 11:41:34 -07:00
203 changed files with 10653 additions and 5075 deletions
+2 -1
View File
@@ -51,7 +51,8 @@ permissions:
concurrency:
group: ci-cache-warmup-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
# Hourly retries must let an active warmer finish publishing its caches.
cancel-in-progress: ${{ github.event_name != 'schedule' }}
jobs:
warm:
+2 -2
View File
@@ -49,7 +49,7 @@ jobs:
# v5 avoids the v6 bootstrap/shim regression when pinning pnpm 10.
uses: pnpm/action-setup@v5
with:
version: 10.24.0
version: 10.34.6
package_json_file: docs/site/package.json
run_install: false
@@ -224,7 +224,7 @@ jobs:
# v5 avoids the v6 bootstrap/shim regression when pinning pnpm 10.
uses: pnpm/action-setup@v5
with:
version: 10.24.0
version: 10.34.6
package_json_file: docs/site/package.json
run_install: false
+29 -8
View File
@@ -119,7 +119,22 @@ jobs:
ref: ${{ inputs.ref || github.ref }}
- name: Install native build tools
run: sudo apt-get update && sudo apt-get install -y build-essential python3
env:
ORCA_E2E_APT_PACKAGES: build-essential python3
run: &install_e2e_tools |
read -r -a packages <<< "$ORCA_E2E_APT_PACKAGES"
for source in /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources; do
if [ -f "$source" ]; then
sudo sed -i 's|https*://azure\.archive\.ubuntu\.com/ubuntu|https://archive.ubuntu.com/ubuntu|g' "$source"
fi
done
sudo tee /etc/apt/apt.conf.d/99-orca-e2e >/dev/null <<'APTCONF'
Acquire::http::Timeout "15";
Acquire::https::Timeout "15";
Acquire::Retries "1";
APTCONF
timeout 120 sudo apt-get update
timeout 300 sudo apt-get install -y "${packages[@]}"
- uses: ./.github/actions/install-node-dependencies
with:
@@ -176,7 +191,11 @@ jobs:
# Native cache misses need the compiler, Electron needs Xvfb, and paired
# Quick Open needs ripgrep. Install them in one apt transaction per shard.
- name: Install native build and headless UI tools
run: sudo apt-get update && sudo apt-get install -y build-essential fonts-noto-cjk python3 ripgrep xvfb zsh openbox x11-utils
# The Azure archive took 16 minutes for one font package; bound setup
# separately so a slow mirror cannot consume the shard's test budget.
env: &e2e_tool_packages
ORCA_E2E_APT_PACKAGES: build-essential fonts-noto-cjk openssh-client python3 ripgrep xvfb zsh openbox x11-utils
run: *install_e2e_tools
- uses: ./.github/actions/install-node-dependencies
with:
@@ -241,7 +260,7 @@ jobs:
# them as an artifact makes post-mortem debugging on CI possible without
# re-running locally.
- name: Upload Playwright traces
if: failure()
if: failure() || cancelled()
uses: actions/upload-artifact@v7
with:
name: playwright-traces-${{ matrix.shard_name }}
@@ -267,7 +286,8 @@ jobs:
# unbounded inventory fallback; the paired fixture exercises that real boundary.
# Why openssh-client: the Docker-SSH fixture shells out to ssh/ssh-keygen, and this
# lane now receives those specs from pr.yml's SSH source mapping.
run: sudo apt-get update && sudo apt-get install -y build-essential fonts-noto-cjk openssh-client python3 ripgrep xvfb zsh openbox x11-utils
env: *e2e_tool_packages
run: *install_e2e_tools
- uses: ./.github/actions/install-node-dependencies
with:
@@ -345,7 +365,7 @@ jobs:
pnpm run test:e2e "${TEST_FILES[@]}" --workers=1 "${E2E_PROJECT_ARGS[@]}"
- name: Upload Playwright traces
if: failure()
if: failure() || cancelled()
uses: actions/upload-artifact@v7
with:
name: playwright-traces-changed
@@ -404,7 +424,8 @@ jobs:
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 fonts-noto-cjk openssh-client python3 ripgrep xvfb zsh openbox x11-utils
env: *e2e_tool_packages
run: *install_e2e_tools
- uses: ./.github/actions/install-node-dependencies
with:
@@ -460,7 +481,7 @@ jobs:
fi
- name: Upload watcher isolation traces
if: failure()
if: failure() || cancelled()
uses: actions/upload-artifact@v7
with:
name: playwright-traces-ssh-docker-watcher-isolation-${{ matrix.shard }}
@@ -587,7 +608,7 @@ jobs:
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()
if: failure() || cancelled()
with:
name: localhost-ssh-traces
path: test-results/
+57 -53
View File
@@ -17,9 +17,9 @@ on:
- '.pnpmfile.cjs'
- '.github/actions/install-node-dependencies/**'
- '.github/actions/prepare-native-runtime/**'
- '.github/actions/prepare-orcad-prebuilds/**'
- '.github/workflows/node-server-tests.yml'
# The pull request qualifies one platform for an unflavoured change; this is where all six
# are re-qualified, so a platform break surfaces minutes after merge instead of next cron.
# Relevant main pushes qualify every platform after the dependency check.
push:
branches: [main]
paths:
@@ -36,6 +36,7 @@ on:
- '.pnpmfile.cjs'
- '.github/actions/install-node-dependencies/**'
- '.github/actions/prepare-native-runtime/**'
- '.github/actions/prepare-orcad-prebuilds/**'
- '.github/workflows/node-server-tests.yml'
workflow_dispatch:
inputs:
@@ -60,15 +61,16 @@ on:
permissions:
contents: read
# Why a run-scoped group for template builds: a release call shares github.ref with main's push
# runs, and cancelling either would drop a release's template or a main qualification.
# Main pushes must finish detection before they can supersede relevant qualification.
concurrency:
group: node-server-${{ inputs.build_template && format('template-{0}', github.run_id) || github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ !inputs.build_template }}
group: node-server-${{ (inputs.build_template || github.event_name == 'push') && format('run-{0}', github.run_id) || github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ !inputs.build_template && github.event_name != 'push' }}
jobs:
changes:
if: github.event_name == 'pull_request'
if: >-
github.event_name == 'push' ||
(github.event_name == 'pull_request' && github.event.pull_request.draft != true)
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
@@ -84,7 +86,20 @@ jobs:
- name: Detect headless-server build and test inputs
id: scope
shell: bash
env:
PUSH_BASE: ${{ github.event.before }}
EVENT_NAME: ${{ github.event_name }}
run: |
if [ "$EVENT_NAME" = push ]; then
# Compare the entire push, including multi-commit pushes and removed files.
if git fetch --no-tags --depth=1 origin "$PUSH_BASE" &&
git diff --name-only --no-renames -z "$PUSH_BASE" HEAD > "$RUNNER_TEMP/node-server-changes"; then
node config/scripts/node-server-change-scope.mjs "$RUNNER_TEMP/node-server-changes" --full-qualification
else
echo 'should_run=true' >> "$GITHUB_OUTPUT"
fi
exit 0
fi
# Compare the tested merge with its base, retaining both sides of renames.
if git diff --name-only --no-renames -z HEAD^1 HEAD > "$RUNNER_TEMP/node-server-changes"; then
node config/scripts/node-server-change-scope.mjs "$RUNNER_TEMP/node-server-changes"
@@ -94,6 +109,9 @@ jobs:
persistence:
needs: changes
concurrency:
group: node-server-persistence-${{ matrix.os }}-${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' }}
# Missing/failed detection runs the full matrix; manual runs remain unconditional.
# A draft carries no platform verdict; readiness re-triggers this workflow. Spelled against
# the event name so the push and schedule paths do not rest on a null property comparison.
@@ -116,48 +134,15 @@ jobs:
- uses: ./.github/actions/install-node-dependencies
with:
native-runtime: ${{ runner.os == 'Windows' && 'node' || 'none' }}
- name: Resolve this Windows server prebuild cache
id: orcad-prebuild-cache-identity
if: >-
runner.os == 'Windows' && (runner.arch == 'X64' || runner.arch == 'ARM64') &&
!inputs.build_template && inputs.ref == '' &&
(github.event_name == 'pull_request' ||
(github.ref == 'refs/heads/main' && contains(fromJSON('["push","schedule","workflow_dispatch"]'), github.event_name)))
continue-on-error: true
shell: bash
run: node config/scripts/orcad-windows-prebuild-cache.mjs --fingerprint
- name: Restore the exact Windows server prebuild for this pull request
id: orcad-prebuild-cache-restore
if: >-
github.event_name == 'pull_request' &&
steps.orcad-prebuild-cache-identity.outcome == 'success' &&
steps.orcad-prebuild-cache-identity.outputs.key != ''
continue-on-error: true
uses: actions/cache/restore@v5
# Linux release slots come from the floor and Alpine lanes; this slot serves local tests.
- uses: ./.github/actions/prepare-orcad-prebuilds
id: orcad-prebuild
with:
path: ${{ steps.orcad-prebuild-cache-identity.outputs.path }}
key: ${{ steps.orcad-prebuild-cache-identity.outputs.key }}
# Before setup-node 18: the scripts import the TypeScript runtime pin.
# Linux release slots come from the Ubuntu 20.04 and Alpine lanes below, where their libc
# floors live; this runner's slot only packages orcad for its own tests.
- name: Build and smoke this runner's node-pty prebuild slot under the pinned Node
shell: bash
env:
WINDOWS_PREBUILD_CACHE_HIT: ${{ steps.orcad-prebuild-cache-restore.outputs.cache-hit }}
WINDOWS_PREBUILD_CACHE_RESTORE_OUTCOME: ${{ steps.orcad-prebuild-cache-restore.outcome }}
run: |
if [ "$RUNNER_OS" = Windows ] && [ "$WINDOWS_PREBUILD_CACHE_HIT" = true ] &&
[ "$WINDOWS_PREBUILD_CACHE_RESTORE_OUTCOME" = success ] &&
node config/scripts/orcad-windows-prebuild-cache.mjs --validate; then
echo 'Using the validated Windows server prebuild'
else
if [ "$RUNNER_OS" = Windows ]; then
rm -rf -- out/orcad-prebuilds
fi
pnpm build:orcad-prebuilds
fi
pnpm build:orcad-prebuilds --require-slots "$(node config/scripts/build-orcad-prebuilds.mjs --print-slot)"
pnpm build:orcad-prebuilds --smoke
resolve-windows-cache: >-
${{ !inputs.build_template && inputs.ref == '' &&
(github.event_name == 'pull_request' ||
(github.ref == 'refs/heads/main' && contains(fromJSON('["push","schedule","workflow_dispatch"]'), github.event_name))) }}
restore-windows-cache: ${{ github.event_name == 'pull_request' || github.event_name == 'push' }}
- run: pnpm build:orcad
# Design D7 upgrade and rollback: the last Bun orcad, built from a main commit that shipped
# it, beside this checkout's Node slot; the live-terminal hand-over skips once PROTOCOL_VERSION
@@ -213,13 +198,13 @@ jobs:
success() && runner.os == 'Windows' && (runner.arch == 'X64' || runner.arch == 'ARM64') &&
!inputs.build_template && inputs.ref == '' && github.ref == 'refs/heads/main' &&
contains(fromJSON('["push","schedule","workflow_dispatch"]'), github.event_name) &&
steps.orcad-prebuild-cache-identity.outcome == 'success' &&
steps.orcad-prebuild-cache-identity.outputs.key != ''
steps.orcad-prebuild.outputs.cache-identity-outcome == 'success' &&
steps.orcad-prebuild.outputs.cache-key != ''
continue-on-error: true
uses: actions/cache/save@v5
with:
path: ${{ steps.orcad-prebuild-cache-identity.outputs.path }}
key: ${{ steps.orcad-prebuild-cache-identity.outputs.key }}
path: ${{ steps.orcad-prebuild.outputs.cache-path }}
key: ${{ steps.orcad-prebuild.outputs.cache-key }}
# Linux release slots come from the floor and Alpine lanes; these runners own the rest.
- name: Keep this runner's qualified slot for the desktop template
if: inputs.build_template && runner.os != 'Linux'
@@ -234,6 +219,9 @@ jobs:
linux_glibc_floor:
needs: [changes, persistence]
concurrency:
group: node-server-linux_glibc_floor-${{ matrix.os }}-${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' }}
# A failed smoke already blocks qualification; missing scope still selects every platform.
if: >-
${{ !cancelled() && needs.persistence.result == 'success' &&
@@ -262,7 +250,17 @@ jobs:
PYTHON: /opt/python/cp312-cp312/bin/python3
steps:
- name: Install glibc 2.28 prerequisites
run: dnf install -y git procps-ng unzip which xz
run: |
missing_tool=false
for tool in git ps unzip which xz; do
if ! command -v "$tool" >/dev/null 2>&1; then
missing_tool=true
fi
done
if [ "$missing_tool" = true ]; then
# The image's source-built Git needs no RPM; missing tools come from AlmaLinux.
dnf --disablerepo='epel*' install -y git procps-ng unzip which xz
fi
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}
@@ -289,6 +287,9 @@ jobs:
linux_glibc217_compat:
needs: [changes, persistence]
concurrency:
group: node-server-linux_glibc217_compat-${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' }}
# A failed smoke already blocks qualification; missing scope still selects every platform.
if: >-
${{ !cancelled() && needs.persistence.result == 'success' &&
@@ -341,6 +342,9 @@ jobs:
linux_musl:
needs: [changes, persistence]
concurrency:
group: node-server-linux_musl-${{ matrix.os }}-${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' }}
# A failed smoke already blocks qualification; missing scope still selects every platform.
if: >-
${{ !cancelled() && needs.persistence.result == 'success' &&
+11 -1
View File
@@ -56,7 +56,17 @@ jobs:
PYTHON: /opt/python/cp312-cp312/bin/python3
steps:
- name: Install glibc 2.28 prerequisites
run: dnf install -y git procps-ng unzip which xz
run: |
missing_tool=false
for tool in git ps unzip which xz; do
if ! command -v "$tool" >/dev/null 2>&1; then
missing_tool=true
fi
done
if [ "$missing_tool" = true ]; then
# The image's source-built Git needs no RPM; missing tools come from AlmaLinux.
dnf --disablerepo='epel*' install -y git procps-ng unzip which xz
fi
- uses: actions/checkout@v6
with:
persist-credentials: false
+19 -4
View File
@@ -28,6 +28,7 @@ on:
- 'config/patches/@vscode__windows-process-tree*'
- 'config/scripts/build-windows-process-tree-relay-addon.mjs'
- 'config/scripts/relay-windows-process-tree-staging.mjs'
- 'config/scripts/relay-windows-process-tree-prepared-addon*.mjs'
- 'config/scripts/windows-process-tree-gyp-rebuild.mjs'
- 'src/shared/relay-windows-breakaway-launch.ts'
- 'src/shared/windows-breakaway-launch*.ts'
@@ -36,6 +37,8 @@ on:
- 'src/main/ssh/orcad-windows-host-lane.test.ts'
- 'config/ci/windows-ssh-provider/**'
- '.github/workflows/ssh-windows-hosts.yml'
- '.github/actions/prepare-orcad-prebuilds/**'
- 'config/scripts/orcad-windows-prebuild-cache.mjs'
workflow_dispatch:
inputs:
cells:
@@ -83,6 +86,7 @@ jobs:
with:
persist-credentials: false
- uses: ./.github/actions/install-node-dependencies
id: dependencies
with:
native-runtime: node
- name: Self-test the provisioning scripts before touching the machine
@@ -97,15 +101,26 @@ jobs:
# The deploy materializes rung A from this template; only this runner's slot exists here.
# The process-tree addon carries the launcher that starts the relay outside sshd's job; the
# orcad slot and the relay both stage it, and a standard-user host has no other launch route.
- name: Build this runner's orcad slot, the win32 template and the relay
- name: Build this runner's Windows process-table addon
shell: bash
env:
REUSE_PREPARED_RUNTIME: ${{ github.event_name == 'pull_request' && steps.dependencies.outputs.native-cache-hit == 'true' }}
run: |
reuse_args=()
if [ "$REUSE_PREPARED_RUNTIME" = true ]; then
reuse_args+=(--reuse-prepared-runtime)
fi
node config/scripts/build-windows-process-tree-relay-addon.mjs --arch=${{ matrix.arch }} "${reuse_args[@]}"
- uses: ./.github/actions/prepare-orcad-prebuilds
with:
resolve-windows-cache: ${{ github.event_name == 'pull_request' }}
restore-windows-cache: ${{ github.event_name == 'pull_request' }}
- name: Build the win32 template and the relay
shell: bash
env:
ORCA_REQUIRE_RELAY_NATIVE_ADDONS: ${{ matrix.arch }}
run: |
node config/scripts/build-windows-process-tree-relay-addon.mjs --arch=${{ matrix.arch }}
pnpm build:orcad-prebuilds
pnpm build:orcad-prebuilds --require-slots "win32-${{ matrix.arch }}"
pnpm build:orcad-prebuilds --smoke
node config/scripts/build-orcad-template.mjs --targets "win32-${{ matrix.arch }}"
pnpm run build:relay
- name: Run the Windows host cells against a private ${{ matrix.server }} sshd
+4 -2
View File
@@ -26,6 +26,7 @@ jobs:
test:
name: tests node ${{ matrix.node }} ${{ matrix.shard.index }}/${{ matrix.shard.count }}
runs-on: ${{ inputs.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
@@ -82,6 +83,7 @@ jobs:
matrix:
node: ${{ fromJSON(inputs.node_versions) }}
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
@@ -103,8 +105,8 @@ jobs:
- name: Install relay integration dependencies
working-directory: cloud
run: |
npx --yes pnpm@10.24.0 --filter '@orca-cloud/relay...' install --frozen-lockfile --ignore-scripts
npx --yes pnpm@10.24.0 --filter '@orca-cloud/relay^...' build
npx --yes pnpm@10.34.6 --filter '@orca-cloud/relay...' install --frozen-lockfile --ignore-scripts
npx --yes pnpm@10.34.6 --filter '@orca-cloud/relay^...' build
- name: Test relay integration contracts
env: