mirror of
https://github.com/stablyai/orca.git
synced 2026-10-17 16:02:55 +00:00
377 lines
17 KiB
YAML
377 lines
17 KiB
YAML
name: SSH Relay Runtime Artifacts
|
|
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- '.github/workflows/ssh-relay-runtime-artifacts.yml'
|
|
- 'config/patches/node-pty@1.1.0.patch'
|
|
- 'config/scripts/build-relay.mjs'
|
|
- 'config/scripts/*ssh-relay*'
|
|
- 'config/ssh-relay-node-release-keys/**'
|
|
- 'config/ssh-relay-node-release-v24.18.0.json'
|
|
- 'package.json'
|
|
- 'pnpm-lock.yaml'
|
|
- 'src/main/ipc/parcel-watcher-process-entry.ts'
|
|
- 'src/relay/**'
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: ssh-relay-runtime-artifacts-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
build-posix-runtime:
|
|
name: Build ${{ matrix.tuple }} runtime
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: ubuntu-24.04
|
|
tuple: linux-x64-glibc
|
|
node_archive: node-v24.18.0-linux-x64.tar.xz
|
|
- runner: ubuntu-24.04-arm
|
|
tuple: linux-arm64-glibc
|
|
node_archive: node-v24.18.0-linux-arm64.tar.xz
|
|
- runner: macos-15-intel
|
|
tuple: darwin-x64
|
|
node_archive: node-v24.18.0-darwin-x64.tar.xz
|
|
- runner: macos-15
|
|
tuple: darwin-arm64
|
|
node_archive: node-v24.18.0-darwin-arm64.tar.xz
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 20
|
|
|
|
steps:
|
|
- name: Checkout exact source revision
|
|
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
with:
|
|
# Why: artifact evidence must name the exact reviewed source, not GitHub's synthetic merge.
|
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6
|
|
with:
|
|
run_install: false
|
|
|
|
- name: Setup Node 24.18.0
|
|
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
|
|
with:
|
|
node-version: 24.18.0
|
|
cache: pnpm
|
|
|
|
- name: Record native runner identity
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
printf 'requested_runner=%s\n' '${{ matrix.runner }}'
|
|
printf 'resolved_image_os=%s\n' "${ImageOS:-unknown}"
|
|
printf 'resolved_image_version=%s\n' "${ImageVersion:-unknown}"
|
|
printf 'runner_arch=%s\n' "$RUNNER_ARCH"
|
|
printf 'runner_environment=%s\n' "$RUNNER_ENVIRONMENT"
|
|
uname -a
|
|
node --version
|
|
printf 'source_commit=%s\n' "$(git rev-parse HEAD)"
|
|
|
|
- name: Install Linux build and verification tools
|
|
if: runner.os == 'Linux'
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y -qq build-essential ca-certificates curl gnupg gpgv python3 xz-utils
|
|
|
|
- name: Install macOS signature verifier
|
|
if: runner.os == 'macOS'
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
brew list gnupg >/dev/null 2>&1 || brew install gnupg
|
|
command -v xz
|
|
xcodebuild -version
|
|
|
|
- name: Install source dependencies without native postinstall
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
pnpm install --frozen-lockfile --ignore-scripts
|
|
git diff --exit-code package.json pnpm-lock.yaml
|
|
|
|
- name: Run runtime artifact contract tests
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
node --check config/scripts/ssh-relay-runtime-reproducibility.mjs
|
|
node --check config/scripts/ssh-relay-runtime-reproducibility.test.mjs
|
|
node --check config/scripts/build-ssh-relay-runtime.mjs
|
|
node --check config/scripts/ssh-relay-runtime-build.test.mjs
|
|
pnpm exec vitest run --config config/vitest.config.ts \
|
|
config/scripts/ssh-relay-node-release-verification.test.mjs \
|
|
config/scripts/ssh-relay-node-tar-inspection.test.mjs \
|
|
config/scripts/ssh-relay-node-pty-build.test.mjs \
|
|
config/scripts/ssh-relay-node-pty-windows-build-determinism.test.mjs \
|
|
config/scripts/ssh-relay-node-pty-windows-settlement.test.mjs \
|
|
config/scripts/ssh-relay-node-zip-inspection.test.mjs \
|
|
config/scripts/ssh-relay-runtime-artifact.test.mjs \
|
|
config/scripts/ssh-relay-runtime-build.test.mjs \
|
|
config/scripts/ssh-relay-runtime-pty-smoke.test.mjs \
|
|
config/scripts/ssh-relay-runtime-reproducibility.test.mjs \
|
|
config/scripts/ssh-relay-runtime-resource-diagnostics.test.mjs \
|
|
config/scripts/ssh-relay-runtime-windows-tree.test.mjs \
|
|
config/scripts/ssh-relay-runtime-zip.test.mjs \
|
|
config/scripts/ssh-relay-runtime-workflow.test.mjs
|
|
|
|
- name: Download exact Node release inputs
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
inputs="$RUNNER_TEMP/node-release-inputs"
|
|
mkdir -p "$inputs"
|
|
base='https://nodejs.org/dist/v24.18.0'
|
|
for asset in SHASUMS256.txt SHASUMS256.txt.sig '${{ matrix.node_archive }}'; do
|
|
curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 \
|
|
--connect-timeout 20 --max-time 300 --retry 2 --retry-delay 2 --retry-all-errors \
|
|
"$base/$asset" --output "$inputs/$asset"
|
|
done
|
|
printf 'NODE_INPUTS=%s\n' "$inputs" >> "$GITHUB_ENV"
|
|
|
|
- name: Build twice, inspect, smoke, and compare exact runtime
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
output_root="$RUNNER_TEMP/ssh-relay-runtime/${{ matrix.tuple }}"
|
|
mkdir -p "$output_root"
|
|
first_output="$output_root/first"
|
|
second_output="$output_root/second"
|
|
work_directory="$RUNNER_TEMP/orca-ssh-relay-runtime-build-work"
|
|
source_commit=$(git rev-parse HEAD)
|
|
source_date_epoch=$(git show -s --format=%ct "$source_commit")
|
|
for output in "$first_output" "$second_output"; do
|
|
printf 'clean_build_output=%s\n' "$output"
|
|
/usr/bin/time -p node config/scripts/build-ssh-relay-runtime.mjs \
|
|
--tuple '${{ matrix.tuple }}' \
|
|
--inputs-directory "$NODE_INPUTS" \
|
|
--output-directory "$output" \
|
|
--work-directory "$work_directory" \
|
|
--source-date-epoch "$source_date_epoch" \
|
|
--git-commit "$source_commit"
|
|
identity="$output/orca-ssh-relay-runtime-${{ matrix.tuple }}.identity.json"
|
|
archive=$(find "$output" -maxdepth 1 -name '*.tar.xz' -print -quit)
|
|
test -n "$archive"
|
|
/usr/bin/time -p node config/scripts/verify-ssh-relay-runtime.mjs \
|
|
--runtime-directory "$output/runtime" \
|
|
--identity "$identity" \
|
|
--archive "$archive"
|
|
if find "$output/runtime" -type f \( -name npm -o -name npx -o -name corepack -o -name '*.map' \) -print -quit | grep -q .; then
|
|
echo 'Runtime contains a prohibited package manager or source map.' >&2
|
|
exit 1
|
|
fi
|
|
parcel_packages=$(find "$output/runtime/node_modules/@parcel" -mindepth 1 -maxdepth 1 -type d | wc -l | tr -d ' ')
|
|
test "$parcel_packages" = 2
|
|
done
|
|
node config/scripts/ssh-relay-runtime-reproducibility.mjs \
|
|
--tuple '${{ matrix.tuple }}' \
|
|
--first-output-directory "$first_output" \
|
|
--second-output-directory "$second_output"
|
|
mkdir -p "$GITHUB_WORKSPACE/runtime-evidence/${{ matrix.tuple }}"
|
|
cp "$first_output"/*.tar.xz "$first_output"/*.spdx.json "$first_output"/*.provenance.json "$first_output"/*.identity.json \
|
|
"$GITHUB_WORKSPACE/runtime-evidence/${{ matrix.tuple }}/"
|
|
|
|
- name: Upload unpublished artifact evidence
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: ssh-relay-runtime-${{ matrix.tuple }}
|
|
path: runtime-evidence/${{ matrix.tuple }}/
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
build-windows-runtime:
|
|
name: Build ${{ matrix.tuple }} runtime
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: windows-2022
|
|
tuple: win32-x64
|
|
node_archive: node-v24.18.0-win-x64.zip
|
|
node_library: win-x64/node.lib
|
|
msvc_arch: x64
|
|
- runner: windows-11-arm
|
|
tuple: win32-arm64
|
|
node_archive: node-v24.18.0-win-arm64.zip
|
|
node_library: win-arm64/node.lib
|
|
msvc_arch: arm64
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 30
|
|
|
|
steps:
|
|
- name: Checkout exact source revision
|
|
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
with:
|
|
# Why: artifact evidence must name the exact reviewed source, not GitHub's synthetic merge.
|
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
|
|
- name: Configure target-native MSVC
|
|
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1
|
|
with:
|
|
arch: ${{ matrix.msvc_arch }}
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6
|
|
with:
|
|
run_install: false
|
|
|
|
- name: Setup Node 24.18.0
|
|
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
|
|
with:
|
|
node-version: 24.18.0
|
|
cache: pnpm
|
|
|
|
- name: Record native runner identity
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
"requested_runner=${{ matrix.runner }}"
|
|
"resolved_image_os=$env:ImageOS"
|
|
"resolved_image_version=$env:ImageVersion"
|
|
"runner_arch=$env:RUNNER_ARCH"
|
|
"runner_environment=$env:RUNNER_ENVIRONMENT"
|
|
Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, OsBuildNumber
|
|
node --version
|
|
"source_commit=$(git rev-parse HEAD)"
|
|
|
|
- name: Select bundled Git signature tools
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
$gitUsrBin = Join-Path $env:ProgramFiles 'Git/usr/bin'
|
|
foreach ($tool in @('gpg.exe', 'gpgv.exe')) {
|
|
if (-not (Test-Path -LiteralPath (Join-Path $gitUsrBin $tool) -PathType Leaf)) {
|
|
throw "Git for Windows does not provide required signature tool: $tool"
|
|
}
|
|
}
|
|
$gitUsrBin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
|
|
|
- name: Install source dependencies without native postinstall
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
pnpm install --frozen-lockfile --ignore-scripts
|
|
if ($LASTEXITCODE -ne 0) { throw 'pnpm install failed' }
|
|
git diff --exit-code package.json pnpm-lock.yaml
|
|
if ($LASTEXITCODE -ne 0) { throw 'frozen install changed dependency files' }
|
|
|
|
- name: Run runtime artifact contract tests
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
node --check config/scripts/ssh-relay-runtime-reproducibility.mjs
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime reproducibility script syntax check failed' }
|
|
node --check config/scripts/ssh-relay-runtime-reproducibility.test.mjs
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime reproducibility test syntax check failed' }
|
|
node --check config/scripts/build-ssh-relay-runtime.mjs
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime build script syntax check failed' }
|
|
node --check config/scripts/ssh-relay-runtime-build.test.mjs
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime build test syntax check failed' }
|
|
pnpm exec vitest run --config config/vitest.config.ts `
|
|
config/scripts/ssh-relay-node-release-verification.test.mjs `
|
|
config/scripts/ssh-relay-node-tar-inspection.test.mjs `
|
|
config/scripts/ssh-relay-node-pty-build.test.mjs `
|
|
config/scripts/ssh-relay-node-pty-windows-build-determinism.test.mjs `
|
|
config/scripts/ssh-relay-node-pty-windows-settlement.test.mjs `
|
|
config/scripts/ssh-relay-node-zip-inspection.test.mjs `
|
|
config/scripts/ssh-relay-runtime-artifact.test.mjs `
|
|
config/scripts/ssh-relay-runtime-build.test.mjs `
|
|
config/scripts/ssh-relay-runtime-pty-smoke.test.mjs `
|
|
config/scripts/ssh-relay-runtime-reproducibility.test.mjs `
|
|
config/scripts/ssh-relay-runtime-resource-diagnostics.test.mjs `
|
|
config/scripts/ssh-relay-runtime-windows-tree.test.mjs `
|
|
config/scripts/ssh-relay-runtime-zip.test.mjs `
|
|
config/scripts/ssh-relay-runtime-workflow.test.mjs
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime artifact contract tests failed' }
|
|
|
|
- name: Download exact Node release inputs
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
$inputs = Join-Path $env:RUNNER_TEMP 'node-release-inputs'
|
|
New-Item -ItemType Directory -Path $inputs | Out-Null
|
|
$base = 'https://nodejs.org/dist/v24.18.0'
|
|
$assets = @(
|
|
'SHASUMS256.txt',
|
|
'SHASUMS256.txt.sig',
|
|
'${{ matrix.node_archive }}',
|
|
'node-v24.18.0-headers.tar.gz',
|
|
'${{ matrix.node_library }}'
|
|
)
|
|
foreach ($asset in $assets) {
|
|
$destination = Join-Path $inputs $asset
|
|
New-Item -ItemType Directory -Path (Split-Path -Parent $destination) -Force | Out-Null
|
|
& curl.exe --fail --silent --show-error --location --proto '=https' --tlsv1.2 `
|
|
--connect-timeout 20 --max-time 300 --retry 2 --retry-delay 2 --retry-all-errors `
|
|
"$base/$asset" --output $destination
|
|
if ($LASTEXITCODE -ne 0) { throw "Node input download failed: $asset" }
|
|
}
|
|
"NODE_INPUTS=$inputs" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
|
|
|
- name: Build twice, inspect, smoke, and compare exact runtime
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
$outputRoot = Join-Path $env:RUNNER_TEMP 'ssh-relay-runtime/${{ matrix.tuple }}'
|
|
New-Item -ItemType Directory -Path $outputRoot -Force | Out-Null
|
|
$firstOutput = Join-Path $outputRoot 'first'
|
|
$secondOutput = Join-Path $outputRoot 'second'
|
|
$workDirectory = Join-Path $env:RUNNER_TEMP 'orca-ssh-relay-runtime-build-work'
|
|
$sourceCommit = git rev-parse HEAD
|
|
$sourceDateEpoch = git show -s --format=%ct $sourceCommit
|
|
foreach ($output in @($firstOutput, $secondOutput)) {
|
|
"clean_build_output=$output"
|
|
node config/scripts/build-ssh-relay-runtime.mjs `
|
|
--tuple '${{ matrix.tuple }}' `
|
|
--inputs-directory $env:NODE_INPUTS `
|
|
--output-directory $output `
|
|
--work-directory $workDirectory `
|
|
--source-date-epoch $sourceDateEpoch `
|
|
--git-commit $sourceCommit
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime build failed' }
|
|
$identity = Join-Path $output 'orca-ssh-relay-runtime-${{ matrix.tuple }}.identity.json'
|
|
$archive = Get-ChildItem -LiteralPath $output -Filter '*.zip' -File | Select-Object -First 1
|
|
if (-not $archive) { throw 'runtime ZIP is missing' }
|
|
node config/scripts/verify-ssh-relay-runtime.mjs `
|
|
--runtime-directory (Join-Path $output 'runtime') `
|
|
--identity $identity `
|
|
--archive $archive.FullName
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime verification failed' }
|
|
$prohibited = Get-ChildItem -LiteralPath (Join-Path $output 'runtime') -Recurse -File |
|
|
Where-Object { $_.Name -in @('npm', 'npm.cmd', 'npx', 'npx.cmd', 'corepack', 'corepack.cmd') -or $_.Name.EndsWith('.map') } |
|
|
Select-Object -First 1
|
|
if ($prohibited) { throw "Runtime contains a prohibited file: $($prohibited.FullName)" }
|
|
$parcelRoot = Join-Path $output 'runtime/node_modules/@parcel'
|
|
if (@(Get-ChildItem -LiteralPath $parcelRoot -Directory).Count -ne 2) {
|
|
throw 'Runtime must contain exactly the watcher wrapper and one native package'
|
|
}
|
|
}
|
|
node config/scripts/ssh-relay-runtime-reproducibility.mjs `
|
|
--tuple '${{ matrix.tuple }}' `
|
|
--first-output-directory $firstOutput `
|
|
--second-output-directory $secondOutput
|
|
if ($LASTEXITCODE -ne 0) { throw 'runtime reproducibility verification failed' }
|
|
$evidence = Join-Path $env:GITHUB_WORKSPACE 'runtime-evidence/${{ matrix.tuple }}'
|
|
New-Item -ItemType Directory -Path $evidence -Force | Out-Null
|
|
$firstArchive = Get-ChildItem -LiteralPath $firstOutput -Filter '*.zip' -File | Select-Object -First 1
|
|
Copy-Item -LiteralPath $firstArchive.FullName -Destination $evidence
|
|
Get-ChildItem -LiteralPath $firstOutput -File |
|
|
Where-Object { $_.Name -match '\.(?:spdx|provenance|identity)\.json$' } |
|
|
Copy-Item -Destination $evidence
|
|
|
|
- name: Upload unpublished artifact evidence
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: ssh-relay-runtime-${{ matrix.tuple }}
|
|
path: runtime-evidence/${{ matrix.tuple }}/
|
|
if-no-files-found: error
|
|
retention-days: 7
|