feat: publish HoloLake model-native living system source
This commit is contained in:
parent
6ad10edde1
commit
c395dd3a99
2467 changed files with 615073 additions and 0 deletions
63
product-source/hololake-platform/.chunk/README.md
Normal file
63
product-source/hololake-platform/.chunk/README.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Chunk Sidecar Validation
|
||||
|
||||
This repo uses Chunk as an experimental inner-loop validation runner for the same gates enforced by the local git hooks.
|
||||
|
||||
## Setup
|
||||
|
||||
Install the CLI:
|
||||
|
||||
```bash
|
||||
brew install CircleCI-Public/circleci/chunk
|
||||
```
|
||||
|
||||
If Homebrew cannot install the formula, use the matching archive from the Chunk CLI GitHub releases and place the `chunk` binary on `PATH`.
|
||||
|
||||
Authenticate before remote sidecar runs:
|
||||
|
||||
```bash
|
||||
chunk auth set circleci
|
||||
```
|
||||
|
||||
`chunk validate` can run locally without CircleCI auth. Remote sidecars require `CIRCLECI_TOKEN` or stored CircleCI auth.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
chunk validate --list
|
||||
chunk validate lint
|
||||
chunk validate typecheck
|
||||
chunk validate frontend-coverage
|
||||
chunk validate --remote lint
|
||||
bash .chunk/run-sidecar-gates-local.sh true
|
||||
```
|
||||
|
||||
Use `chunk sidecar setup --name tolaria-hooks` for the first remote environment setup. Once the environment passes, create a snapshot and launch future sidecars from that snapshot to avoid reinstalling Node, Rust, Tauri Linux dependencies, Playwright Chromium, and `cargo-llvm-cov` every time.
|
||||
|
||||
Keep native macOS Tauri QA outside Chunk. The sidecar is Linux-based and is meant to catch portable lint, build, unit coverage, Rust, and Playwright smoke failures before the full local pre-push hook runs. Browser provisioning uses `.chunk/install-playwright-browsers.mjs` because Playwright's built-in installer can outlive the current Chunk SSH session while extracting large archives.
|
||||
|
||||
## Fast Pre-Push Path
|
||||
|
||||
The local pre-push hook prefers the sidecar fast path when Chunk is available. It targets three independent sidecars by name and always passes `--sidecar-id` after resolution, avoiding races with Chunk's global active-sidecar state:
|
||||
|
||||
- `tolaria-hooks-frontend-2`: lint and build first, then frontend coverage with `FRONTEND_COVERAGE_SHARDS=2` and `VITEST_COVERAGE_MAX_WORKERS=2`.
|
||||
- `tolaria-hooks-rust`: clippy, rustfmt, and `cargo llvm-cov` with `CARGO_BUILD_JOBS=2`.
|
||||
- `tolaria-hooks-playwright`: curated Playwright smoke with one shared Vite server, eight shards, and four concurrent shard workers.
|
||||
|
||||
Set `LAPUTA_PREPUSH_LOCAL=1` to force the old local path. Use `SIDECAR_FRONTEND_ID`, `SIDECAR_RUST_ID`, or `SIDECAR_PLAYWRIGHT_ID` to pin a lane to a specific sidecar when duplicate names exist in CircleCI. Use `SIDECAR_SNAPSHOT_ID=<snapshot-id>` when provisioning missing lane sidecars from a prepared snapshot.
|
||||
|
||||
The lane launcher uses `chunk sidecar exec` only to start detached remote lane processes with `setsid -f`, then polls status files. Long foreground `exec` commands hit CircleCI's sidecar API deadline; plain background jobs are still tracked by `exec` and can time out.
|
||||
|
||||
```bash
|
||||
bash .chunk/run-sidecar-gates-local.sh true
|
||||
```
|
||||
|
||||
Latest measured passing run with two frontend coverage shards: lane runtime 318s including sync, frontend completed in 313s, and Playwright smoke completed in 104s. The previous single-coverage frontend path took 441s with 457s external wall time, so the two-shard experiment reduced the sidecar long pole by about 29%. A previous Playwright run exposed `tests/smoke/h1-title-decoupled.spec.ts` as flaky on sidecar, so it remains in regression coverage but is no longer part of the curated smoke lane.
|
||||
|
||||
To compare the frontend coverage experiment against the old single coverage run, use:
|
||||
|
||||
```bash
|
||||
FRONTEND_COVERAGE_SHARDS=1 bash .chunk/run-sidecar-gates-local.sh false
|
||||
FRONTEND_COVERAGE_SHARDS=2 bash .chunk/run-sidecar-gates-local.sh false
|
||||
```
|
||||
|
||||
The default sidecar fast path uses two frontend coverage shards. Each shard disables per-shard coverage thresholds, then the merged V8/Istanbul coverage map is checked once against the same 70% line/function/branch/statement thresholds.
|
||||
157
product-source/hololake-platform/.chunk/config.json
Normal file
157
product-source/hololake-platform/.chunk/config.json
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
{
|
||||
"commands": [
|
||||
{
|
||||
"name": "lint",
|
||||
"run": "pnpm lint",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx,.js,.jsx,.mjs,.json",
|
||||
"timeout": 120,
|
||||
"limit": 3
|
||||
},
|
||||
{
|
||||
"name": "typecheck",
|
||||
"run": "npx tsc --noEmit",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 180,
|
||||
"limit": 3
|
||||
},
|
||||
{
|
||||
"name": "build",
|
||||
"run": "pnpm build",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx,.css,.html,.json",
|
||||
"timeout": 300,
|
||||
"limit": 2
|
||||
},
|
||||
{
|
||||
"name": "frontend-coverage",
|
||||
"run": "pnpm test:coverage --silent",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 600,
|
||||
"limit": 2
|
||||
},
|
||||
{
|
||||
"name": "rust-lint",
|
||||
"run": "cargo clippy --manifest-path=src-tauri/Cargo.toml -- -D warnings && cargo fmt --manifest-path=src-tauri/Cargo.toml -- --check",
|
||||
"role": "gate",
|
||||
"fileExt": ".rs",
|
||||
"timeout": 300,
|
||||
"limit": 2
|
||||
},
|
||||
{
|
||||
"name": "rust-coverage",
|
||||
"run": "cargo llvm-cov --manifest-path src-tauri/Cargo.toml --no-clean --ignore-filename-regex \"lib\\.rs|main\\.rs|menu\\.rs\" --fail-under-lines 85 -- --test-threads=1",
|
||||
"role": "gate",
|
||||
"fileExt": ".rs",
|
||||
"timeout": 900,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-1",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 1/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-2",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 2/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-3",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 3/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-4",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 4/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-5",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 5/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-6",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 6/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-7",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 7/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
},
|
||||
{
|
||||
"name": "smoke-8",
|
||||
"run": "bash .chunk/run-playwright-smoke.sh 8/8",
|
||||
"role": "gate",
|
||||
"fileExt": ".ts,.tsx",
|
||||
"timeout": 240,
|
||||
"limit": 1
|
||||
}
|
||||
],
|
||||
"stopHookMaxAttempts": 2,
|
||||
"vcs": {
|
||||
"org": "refactoringhq",
|
||||
"repo": "tolaria"
|
||||
},
|
||||
"orgID": "39f93336-5295-4c6c-845f-e692c1d3f968",
|
||||
"environment": {
|
||||
"stack": "javascript-rust-tauri",
|
||||
"setup": [
|
||||
{
|
||||
"name": "system",
|
||||
"command": "sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential curl file git libwebkit2gtk-4.1-dev libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev libsoup-3.0-dev patchelf pkg-config unzip wget xvfb && sudo rm -rf /var/lib/apt/lists/*"
|
||||
},
|
||||
{
|
||||
"name": "rust",
|
||||
"command": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal && . \"$HOME/.cargo/env\" && rustup default stable && rustup component add clippy rustfmt && cargo install cargo-llvm-cov --locked"
|
||||
},
|
||||
{
|
||||
"name": "node",
|
||||
"command": "curl -fsSL https://nodejs.org/dist/v26.3.0/node-v26.3.0-linux-x64.tar.xz | sudo tar -xJ -C /usr/local --strip-components=1 && node --version && npm --version"
|
||||
},
|
||||
{
|
||||
"name": "pnpm",
|
||||
"command": "sudo npm install -g pnpm@10.33.0 && pnpm --version"
|
||||
},
|
||||
{
|
||||
"name": "install",
|
||||
"command": "mkdir -p \"$HOME/Documents\" && pnpm install --frozen-lockfile && . \"$HOME/.cargo/env\" && cargo fetch --manifest-path src-tauri/Cargo.toml"
|
||||
},
|
||||
{
|
||||
"name": "playwright-deps",
|
||||
"command": "pnpm exec playwright install-deps chromium"
|
||||
},
|
||||
{
|
||||
"name": "playwright",
|
||||
"command": "node .chunk/install-playwright-browsers.mjs"
|
||||
}
|
||||
],
|
||||
"image": "cimg/node",
|
||||
"image_version": "26.3.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bin/env node
|
||||
/* global console */
|
||||
import { execFileSync, spawnSync } from 'node:child_process'
|
||||
import {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
readdirSync,
|
||||
renameSync,
|
||||
rmSync,
|
||||
writeFileSync,
|
||||
} from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
|
||||
function run(command, args) {
|
||||
const result = spawnSync(command, args, { stdio: 'inherit' })
|
||||
if (result.error) throw result.error
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`${command} exited with status ${result.status}`)
|
||||
}
|
||||
}
|
||||
|
||||
function parsePlan(planText) {
|
||||
const entries = []
|
||||
const seen = new Set()
|
||||
|
||||
for (const section of planText.split(/\n(?=\S)/)) {
|
||||
const label = section.split('\n')[0]?.trim() ?? ''
|
||||
const location = readField(section, 'Install location')
|
||||
const url = readField(section, 'Download url')
|
||||
rememberEntry(entries, seen, { label, location, url })
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
function readField(text, name) {
|
||||
const match = text.match(new RegExp(`^\\s*${name}:\\s*(.+)$`, 'm'))
|
||||
return match?.[1].trim() ?? ''
|
||||
}
|
||||
|
||||
function rememberEntry(entries, seen, entry) {
|
||||
const key = `${entry.location}\n${entry.url}`
|
||||
if (!entry.location || !entry.url || seen.has(key)) return
|
||||
seen.add(key)
|
||||
entries.push(entry)
|
||||
}
|
||||
|
||||
function installBrowser(entry) {
|
||||
const markerPath = join(entry.location, 'INSTALLATION_COMPLETE')
|
||||
if (existsSync(markerPath)) {
|
||||
console.log(`Already installed: ${entry.label}`)
|
||||
return
|
||||
}
|
||||
|
||||
const workDir = join(tmpdir(), `playwright-${Date.now()}`)
|
||||
const archivePath = join(workDir, 'browser.zip')
|
||||
const extractDir = join(workDir, 'extract')
|
||||
|
||||
rmSync(entry.location, { force: true, recursive: true })
|
||||
mkdirSync(extractDir, { recursive: true })
|
||||
|
||||
console.log(`Downloading ${entry.label}`)
|
||||
run('curl', [
|
||||
'-fL',
|
||||
'--retry',
|
||||
'3',
|
||||
'--connect-timeout',
|
||||
'20',
|
||||
'-o',
|
||||
archivePath,
|
||||
entry.url,
|
||||
])
|
||||
|
||||
console.log(`Extracting ${entry.label}`)
|
||||
run('unzip', ['-q', archivePath, '-d', extractDir])
|
||||
|
||||
mkdirSync(entry.location, { recursive: true })
|
||||
for (const child of readdirSync(extractDir)) {
|
||||
renameSync(join(extractDir, child), join(entry.location, child))
|
||||
}
|
||||
|
||||
writeFileSync(markerPath, '')
|
||||
rmSync(workDir, { force: true, recursive: true })
|
||||
}
|
||||
|
||||
const planText = execFileSync(
|
||||
'npx',
|
||||
['playwright', 'install', '--dry-run', 'chromium'],
|
||||
{ encoding: 'utf8' },
|
||||
)
|
||||
const entries = parsePlan(planText)
|
||||
|
||||
if (entries.length === 0) {
|
||||
throw new Error('Playwright did not report any browser archives to install')
|
||||
}
|
||||
|
||||
for (const entry of entries) {
|
||||
installBrowser(entry)
|
||||
}
|
||||
146
product-source/hololake-platform/.chunk/run-playwright-shards.sh
Normal file
146
product-source/hololake-platform/.chunk/run-playwright-shards.sh
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
total_shards="${1:-${PLAYWRIGHT_SHARDS:-8}}"
|
||||
concurrency="${PLAYWRIGHT_CONCURRENCY:-$total_shards}"
|
||||
log_dir="${TMPDIR:-/tmp}/tolaria-playwright-shards-$$"
|
||||
batch_pids=()
|
||||
shared_server="${PLAYWRIGHT_SHARED_SERVER:-1}"
|
||||
server_port="${PLAYWRIGHT_SMOKE_PORT:-41741}"
|
||||
base_url="${BASE_URL:-http://127.0.0.1:${server_port}}"
|
||||
server_port="$(node -e 'console.log(new URL(process.argv[1]).port || "41741")' "$base_url")"
|
||||
server_pid=""
|
||||
|
||||
if [[ ! "$total_shards" =~ ^[1-9][0-9]*$ ]]; then
|
||||
printf 'Usage: %s [total-shards]\n' "$0" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ ! "$concurrency" =~ ^[1-9][0-9]*$ ]]; then
|
||||
printf 'PLAYWRIGHT_CONCURRENCY must be a positive integer\n' >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
mkdir -p "$log_dir"
|
||||
|
||||
stop_shared_server() {
|
||||
if [[ -z "$server_pid" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
kill -TERM "$server_pid" 2>/dev/null || true
|
||||
sleep 2
|
||||
kill -KILL "$server_pid" 2>/dev/null || true
|
||||
server_pid=""
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
local status=$?
|
||||
trap - EXIT INT TERM
|
||||
|
||||
for pid in "${batch_pids[@]:-}"; do
|
||||
kill -TERM "$pid" 2>/dev/null || true
|
||||
done
|
||||
|
||||
sleep 2
|
||||
|
||||
for pid in "${batch_pids[@]:-}"; do
|
||||
kill -KILL "$pid" 2>/dev/null || true
|
||||
done
|
||||
|
||||
stop_shared_server
|
||||
|
||||
exit "$status"
|
||||
}
|
||||
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
wait_for_shared_server() {
|
||||
local deadline=$((SECONDS + 30))
|
||||
|
||||
until curl -fsS "$base_url" >/dev/null 2>&1; do
|
||||
if [[ -n "$server_pid" ]] && ! kill -0 "$server_pid" 2>/dev/null; then
|
||||
printf '[chunk-playwright] shared server exited before becoming ready\n' >&2
|
||||
sed 's/^/[shared-server] /' "${log_dir}/shared-server.log" >&2 || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$SECONDS" -ge "$deadline" ]]; then
|
||||
printf '[chunk-playwright] shared server did not become ready at %s\n' "$base_url" >&2
|
||||
sed 's/^/[shared-server] /' "${log_dir}/shared-server.log" >&2 || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
start_shared_server() {
|
||||
if [[ "$shared_server" != "1" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
printf '[chunk-playwright] starting shared server at %s\n' "$base_url"
|
||||
TOLARIA_VITE_CACHE_DIR="${TOLARIA_VITE_CACHE_DIR:-${TMPDIR:-/tmp}/tolaria-vite-smoke-shared}" \
|
||||
node scripts/playwright-smoke-server.mjs "$server_port" >"${log_dir}/shared-server.log" 2>&1 &
|
||||
server_pid="$!"
|
||||
wait_for_shared_server
|
||||
}
|
||||
|
||||
run_batch() {
|
||||
local first_shard="$1"
|
||||
local failures=0
|
||||
local names=()
|
||||
local shard="$first_shard"
|
||||
|
||||
batch_pids=()
|
||||
|
||||
while [[ "$shard" -le "$total_shards" && "${#batch_pids[@]}" -lt "$concurrency" ]]; do
|
||||
local name="smoke-${shard}-${total_shards}"
|
||||
local log_file="${log_dir}/${name}.log"
|
||||
|
||||
printf '[chunk-playwright] starting %s\n' "$name"
|
||||
if [[ "$shared_server" == "1" ]]; then
|
||||
BASE_URL="$base_url" PLAYWRIGHT_REUSE_SERVER=1 PLAYWRIGHT_SMOKE_PORT="$server_port" \
|
||||
bash .chunk/run-playwright-smoke.sh "${shard}/${total_shards}" >"$log_file" 2>&1 &
|
||||
else
|
||||
bash .chunk/run-playwright-smoke.sh "${shard}/${total_shards}" >"$log_file" 2>&1 &
|
||||
fi
|
||||
batch_pids+=("$!")
|
||||
names+=("$name")
|
||||
shard=$((shard + 1))
|
||||
done
|
||||
|
||||
for index in "${!batch_pids[@]}"; do
|
||||
local pid="${batch_pids[$index]}"
|
||||
local name="${names[$index]}"
|
||||
local log_file="${log_dir}/${name}.log"
|
||||
|
||||
if wait "$pid"; then
|
||||
printf '[chunk-playwright] %s passed\n' "$name"
|
||||
else
|
||||
failures=1
|
||||
printf '[chunk-playwright] %s failed\n' "$name"
|
||||
fi
|
||||
|
||||
sed "s/^/[${name}] /" "$log_file"
|
||||
done
|
||||
|
||||
batch_pids=()
|
||||
return "$failures"
|
||||
}
|
||||
|
||||
next_shard=1
|
||||
failed=0
|
||||
|
||||
start_shared_server
|
||||
|
||||
while [[ "$next_shard" -le "$total_shards" ]]; do
|
||||
if ! run_batch "$next_shard"; then
|
||||
failed=1
|
||||
fi
|
||||
next_shard=$((next_shard + concurrency))
|
||||
done
|
||||
|
||||
stop_shared_server
|
||||
exit "$failed"
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
shard="${1:-}"
|
||||
shard_label="all"
|
||||
base_url="${BASE_URL:-}"
|
||||
port="${PLAYWRIGHT_SMOKE_PORT:-41741}"
|
||||
|
||||
if [[ -n "$shard" ]]; then
|
||||
if [[ ! "$shard" =~ ^[1-9][0-9]*/[1-9][0-9]*$ ]]; then
|
||||
printf 'Usage: %s [shard/total]\n' "$0" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
shard_index="${shard%%/*}"
|
||||
shard_label="${shard//\//-}"
|
||||
if [[ -z "$base_url" ]]; then
|
||||
port=$((41740 + shard_index))
|
||||
fi
|
||||
fi
|
||||
|
||||
base_url="${base_url:-http://127.0.0.1:${port}}"
|
||||
port="$(node -e 'console.log(new URL(process.argv[1]).port || "41741")' "$base_url")"
|
||||
|
||||
log_file="${TMPDIR:-/tmp}/tolaria-playwright-smoke-${shard_label}.log"
|
||||
playwright_pid=""
|
||||
|
||||
cleanup() {
|
||||
local status=$?
|
||||
|
||||
if [[ -n "$playwright_pid" ]]; then
|
||||
kill -TERM "$playwright_pid" 2>/dev/null || true
|
||||
sleep 2
|
||||
kill -KILL "$playwright_pid" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [[ "${PLAYWRIGHT_REUSE_SERVER:-}" != "1" ]]; then
|
||||
pkill -TERM -f "playwright-smoke-server.mjs ${port}" 2>/dev/null || true
|
||||
pkill -TERM -f "vite.js --host 127.0.0.1 --port ${port}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
exit "$status"
|
||||
}
|
||||
|
||||
trap cleanup INT TERM
|
||||
|
||||
mapfile -t smoke_files < <(node <<'NODE'
|
||||
const fs = require('node:fs')
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'))
|
||||
const script = packageJson.scripts && packageJson.scripts['playwright:smoke']
|
||||
const prefix = 'playwright test --config playwright.smoke.config.ts '
|
||||
|
||||
if (!script || !script.startsWith(prefix)) {
|
||||
throw new Error('Unexpected playwright:smoke script format')
|
||||
}
|
||||
|
||||
for (const file of script.slice(prefix.length).trim().split(/\s+/)) {
|
||||
if (file) {
|
||||
console.log(file)
|
||||
}
|
||||
}
|
||||
NODE
|
||||
)
|
||||
|
||||
: > "$log_file"
|
||||
playwright_args=(
|
||||
test
|
||||
--config playwright.smoke.config.ts
|
||||
"${smoke_files[@]}"
|
||||
--reporter=line
|
||||
)
|
||||
|
||||
if [[ -n "$shard" ]]; then
|
||||
playwright_args+=(--shard "$shard")
|
||||
fi
|
||||
|
||||
printf '[chunk-playwright] running %s curated smoke files on port %s' "${#smoke_files[@]}" "$port"
|
||||
if [[ -n "$shard" ]]; then
|
||||
printf ' with shard %s' "$shard"
|
||||
fi
|
||||
printf '\n'
|
||||
|
||||
set +e
|
||||
env CI=true BASE_URL="$base_url" PLAYWRIGHT_REUSE_SERVER="${PLAYWRIGHT_REUSE_SERVER:-}" pnpm exec playwright "${playwright_args[@]}" \
|
||||
> >(tee "$log_file") 2>&1 &
|
||||
playwright_pid=$!
|
||||
wait "$playwright_pid"
|
||||
playwright_status=$?
|
||||
playwright_pid=""
|
||||
set -e
|
||||
|
||||
printf '[chunk-playwright] smoke %s exited with status %s\n' "$shard_label" "$playwright_status"
|
||||
exit "$playwright_status"
|
||||
30
product-source/hololake-platform/.chunk/run-rust-gate.sh
Normal file
30
product-source/hololake-platform/.chunk/run-rust-gate.sh
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
start_time=$(date +%s)
|
||||
|
||||
log_rust() {
|
||||
printf '[sidecar-rust +%ss] %s\n' "$(($(date +%s) - start_time))" "$*"
|
||||
}
|
||||
|
||||
mkdir -p "$HOME/Documents"
|
||||
# shellcheck disable=SC1091
|
||||
. "$HOME/.cargo/env"
|
||||
export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-2}"
|
||||
|
||||
log_rust 'clippy started'
|
||||
cargo clippy --manifest-path=src-tauri/Cargo.toml -- -D warnings
|
||||
log_rust 'clippy passed'
|
||||
|
||||
log_rust 'rustfmt started'
|
||||
cargo fmt --manifest-path=src-tauri/Cargo.toml -- --check
|
||||
log_rust 'rustfmt passed'
|
||||
|
||||
log_rust 'coverage started'
|
||||
cargo llvm-cov \
|
||||
--manifest-path src-tauri/Cargo.toml \
|
||||
--no-clean \
|
||||
--ignore-filename-regex "lib\\.rs|main\\.rs|menu\\.rs" \
|
||||
--fail-under-lines 85 \
|
||||
-- --test-threads=1
|
||||
log_rust "completed in $(($(date +%s) - start_time))s"
|
||||
395
product-source/hololake-platform/.chunk/run-sidecar-gates-local.sh
Executable file
395
product-source/hololake-platform/.chunk/run-sidecar-gates-local.sh
Executable file
|
|
@ -0,0 +1,395 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
readonly unavailable_status=86
|
||||
|
||||
rust_changed="${1:-true}"
|
||||
playwright_shards="${PLAYWRIGHT_SHARDS:-8}"
|
||||
playwright_concurrency="${PLAYWRIGHT_CONCURRENCY:-4}"
|
||||
playwright_shared_server="${PLAYWRIGHT_SHARED_SERVER:-1}"
|
||||
vitest_coverage_max_workers="${VITEST_COVERAGE_MAX_WORKERS:-${SIDECAR_VITEST_MAX_WORKERS:-2}}"
|
||||
frontend_coverage_shards="${FRONTEND_COVERAGE_SHARDS:-${SIDECAR_FRONTEND_COVERAGE_SHARDS:-2}}"
|
||||
cargo_build_jobs="${CARGO_BUILD_JOBS:-2}"
|
||||
timeout_seconds="${SIDECAR_GATE_TIMEOUT:-1800}"
|
||||
poll_interval="${SIDECAR_GATE_POLL_INTERVAL:-20}"
|
||||
launch_timeout="${SIDECAR_GATE_LAUNCH_TIMEOUT:-45}"
|
||||
launch_attempts="${SIDECAR_GATE_LAUNCH_ATTEMPTS:-3}"
|
||||
remote_workdir="${SIDECAR_REMOTE_WORKDIR:-/home/user/tolaria}"
|
||||
sidecar_prefix="${SIDECAR_NAME_PREFIX:-tolaria-hooks}"
|
||||
frontend_name="${SIDECAR_FRONTEND_NAME:-${sidecar_prefix}-frontend-2}"
|
||||
rust_name="${SIDECAR_RUST_NAME:-${sidecar_prefix}-rust}"
|
||||
playwright_name="${SIDECAR_PLAYWRIGHT_NAME:-${sidecar_prefix}-playwright}"
|
||||
state_dir="$(mktemp -d "${TMPDIR:-/tmp}/tolaria-sidecar-lanes.XXXXXX")"
|
||||
lanes_file="${state_dir}/lanes.tsv"
|
||||
|
||||
: > "$lanes_file"
|
||||
|
||||
cleanup_state() {
|
||||
rm -rf "$state_dir"
|
||||
}
|
||||
|
||||
trap cleanup_state EXIT
|
||||
|
||||
resolve_chunk_bin() {
|
||||
if [[ -n "${CHUNK_BIN:-}" && -x "$CHUNK_BIN" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v chunk >/dev/null 2>&1; then
|
||||
CHUNK_BIN="$(command -v chunk)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -x "$HOME/.local/bin/chunk" ]]; then
|
||||
CHUNK_BIN="$HOME/.local/bin/chunk"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
load_org_id() {
|
||||
if [[ -n "${CIRCLECI_ORG_ID:-}" ]]; then
|
||||
printf '%s\n' "$CIRCLECI_ORG_ID"
|
||||
return
|
||||
fi
|
||||
|
||||
node -e "const fs=require('node:fs'); const c=JSON.parse(fs.readFileSync('.chunk/config.json','utf8')); if (c.orgID) process.stdout.write(c.orgID)"
|
||||
}
|
||||
|
||||
sidecar_id_by_name() {
|
||||
local name="$1"
|
||||
|
||||
"$CHUNK_BIN" sidecar list 2>/dev/null | awk -v name="$name" '$1 == name { print $2; found=1; exit } END { exit found ? 0 : 1 }'
|
||||
}
|
||||
|
||||
create_sidecar_from_snapshot() {
|
||||
local name="$1"
|
||||
|
||||
if [[ -z "${SIDECAR_SNAPSHOT_ID:-}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo " -> Creating ${name} from snapshot ${SIDECAR_SNAPSHOT_ID}" >&2
|
||||
"$CHUNK_BIN" sidecar create --name "$name" --org-id "$org_id" --image "$SIDECAR_SNAPSHOT_ID" >/dev/null
|
||||
}
|
||||
|
||||
ensure_sidecar() {
|
||||
local name="$1"
|
||||
local explicit_id="${2:-}"
|
||||
local id
|
||||
|
||||
if [[ -n "$explicit_id" ]]; then
|
||||
printf '%s\n' "$explicit_id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if id="$(sidecar_id_by_name "$name")"; then
|
||||
printf '%s\n' "$id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo " -> Sidecar ${name} not found; provisioning it..." >&2
|
||||
if ! create_sidecar_from_snapshot "$name"; then
|
||||
"$CHUNK_BIN" sidecar setup --name "$name" --org-id "$org_id" >/dev/null
|
||||
fi
|
||||
|
||||
sidecar_id_by_name "$name"
|
||||
}
|
||||
|
||||
sync_lane() {
|
||||
local lane="$1"
|
||||
local sidecar_id="$2"
|
||||
local log_file="${state_dir}/sync-${lane}.log"
|
||||
|
||||
{
|
||||
echo "[sidecar-sync] ${lane}: syncing to ${sidecar_id}"
|
||||
if "$CHUNK_BIN" sidecar sync --sidecar-id "$sidecar_id" --workdir "$remote_workdir"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "[sidecar-sync] ${lane}: sync failed, rerunning setup once"
|
||||
"$CHUNK_BIN" sidecar setup --sidecar-id "$sidecar_id" --dir .
|
||||
"$CHUNK_BIN" sidecar sync --sidecar-id "$sidecar_id" --workdir "$remote_workdir"
|
||||
} >"$log_file" 2>&1
|
||||
}
|
||||
|
||||
sync_all_lanes() {
|
||||
local failures=0
|
||||
local frontend_pid rust_pid playwright_pid
|
||||
|
||||
sync_lane frontend "$frontend_id" &
|
||||
frontend_pid=$!
|
||||
sync_lane rust "$rust_id" &
|
||||
rust_pid=$!
|
||||
sync_lane playwright "$playwright_id" &
|
||||
playwright_pid=$!
|
||||
|
||||
for lane_pid in "$frontend_pid" "$rust_pid" "$playwright_pid"; do
|
||||
if ! wait "$lane_pid"; then
|
||||
failures=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$failures" != "0" ]]; then
|
||||
echo "Chunk sidecar sync failed"
|
||||
sed 's/^/ /' "${state_dir}"/sync-*.log 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
record_lane() {
|
||||
local lane="$1"
|
||||
local sidecar_id="$2"
|
||||
local status_file="$3"
|
||||
local log_file="$4"
|
||||
local pid_file="$5"
|
||||
|
||||
printf '%s\t%s\t%s\t%s\t%s\n' "$lane" "$sidecar_id" "$status_file" "$log_file" "$pid_file" >> "$lanes_file"
|
||||
}
|
||||
|
||||
launch_lane() {
|
||||
local lane="$1"
|
||||
local sidecar_id="$2"
|
||||
local run_id="tolaria-${lane}-$(date +%s)-$$"
|
||||
local remote_status="/tmp/${run_id}.status"
|
||||
local remote_log="/tmp/${run_id}.log"
|
||||
local remote_pid="/tmp/${run_id}.pid"
|
||||
local remote_launcher="/tmp/${run_id}.launcher.log"
|
||||
local launch_output_file="${state_dir}/launch-${lane}.log"
|
||||
local launch_attempt=1
|
||||
|
||||
while [[ "$launch_attempt" -le "$launch_attempts" ]]; do
|
||||
local launch_status=0
|
||||
local launch_pid
|
||||
local launch_elapsed=0
|
||||
|
||||
echo " -> Launching ${lane} on ${sidecar_id} (attempt ${launch_attempt}/${launch_attempts})"
|
||||
"$CHUNK_BIN" sidecar exec \
|
||||
--sidecar-id "$sidecar_id" \
|
||||
--command bash \
|
||||
--args -lc \
|
||||
--args "cd '$remote_workdir' && export RUST_CHANGED='$rust_changed' PLAYWRIGHT_SHARDS='$playwright_shards' PLAYWRIGHT_CONCURRENCY='$playwright_concurrency' PLAYWRIGHT_SHARED_SERVER='$playwright_shared_server' VITEST_COVERAGE_MAX_WORKERS='$vitest_coverage_max_workers' FRONTEND_COVERAGE_SHARDS='$frontend_coverage_shards' CARGO_BUILD_JOBS='$cargo_build_jobs' && rm -f '$remote_status' '$remote_log' '$remote_pid' '$remote_launcher' && nohup setsid -f bash -lc 'bash .chunk/run-sidecar-lane.sh $lane >\"$remote_log\" 2>&1; printf \"%s\\n\" \"\$?\" >\"$remote_status\"' </dev/null >'$remote_launcher' 2>&1" \
|
||||
>"$launch_output_file" 2>&1 &
|
||||
launch_pid=$!
|
||||
|
||||
while kill -0 "$launch_pid" 2>/dev/null; do
|
||||
if [[ "$launch_elapsed" -ge "$launch_timeout" ]]; then
|
||||
launch_status=124
|
||||
kill "$launch_pid" 2>/dev/null || true
|
||||
sleep 1
|
||||
kill -KILL "$launch_pid" 2>/dev/null || true
|
||||
wait "$launch_pid" 2>/dev/null || true
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
launch_elapsed=$((launch_elapsed + 1))
|
||||
done
|
||||
|
||||
if [[ "$launch_status" == "0" ]]; then
|
||||
wait "$launch_pid" || launch_status=$?
|
||||
fi
|
||||
|
||||
if [[ "$launch_status" == "0" ]]; then
|
||||
record_lane "$lane" "$sidecar_id" "$remote_status" "$remote_log" "$remote_pid"
|
||||
return 0
|
||||
fi
|
||||
|
||||
cat "$launch_output_file"
|
||||
if launch_state="$(poll_lane_status "$sidecar_id" "$remote_status" "$remote_log" "$remote_pid" 2>/dev/null)"; then
|
||||
launch_state="$(printf '%s\n' "$launch_state" | tail -1 | tr -d '[:space:]')"
|
||||
if [[ "$launch_state" == "running" || "$launch_state" == "0" || "$launch_state" =~ ^[1-9][0-9]*$ ]]; then
|
||||
echo " -> ${lane} appears to have started despite launch status ${launch_status}"
|
||||
record_lane "$lane" "$sidecar_id" "$remote_status" "$remote_log" "$remote_pid"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
echo "Chunk sidecar launch failed for ${lane} with status ${launch_status}"
|
||||
if [[ "$launch_attempt" -lt "$launch_attempts" ]]; then
|
||||
sleep 5
|
||||
fi
|
||||
launch_attempt=$((launch_attempt + 1))
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
fetch_remote_log_tail() {
|
||||
local lane="$1"
|
||||
local sidecar_id="$2"
|
||||
local log_file="$3"
|
||||
|
||||
echo ""
|
||||
echo "----- ${lane} log tail -----"
|
||||
"$CHUNK_BIN" sidecar exec \
|
||||
--sidecar-id "$sidecar_id" \
|
||||
--command bash \
|
||||
--args -lc \
|
||||
--args "tail -180 '$log_file' 2>/dev/null || true" 2>&1 || true
|
||||
}
|
||||
|
||||
stop_lane() {
|
||||
local sidecar_id="$1"
|
||||
local pid_file="$2"
|
||||
local log_file="$3"
|
||||
|
||||
"$CHUNK_BIN" sidecar exec \
|
||||
--sidecar-id "$sidecar_id" \
|
||||
--command bash \
|
||||
--args -lc \
|
||||
--args "if [ -s '$pid_file' ]; then pid=\$(cat '$pid_file'); kill -TERM -\"\$pid\" 2>/dev/null || kill -TERM \"\$pid\" 2>/dev/null || true; sleep 3; kill -KILL -\"\$pid\" 2>/dev/null || kill -KILL \"\$pid\" 2>/dev/null || true; fi; ps -eo pid=,command= | awk -v target='$log_file' '\$0 ~ target && \$0 !~ /awk/ { print \$1 }' | xargs -r kill -TERM 2>/dev/null || true" \
|
||||
>/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
stop_all_lanes() {
|
||||
while IFS=$'\t' read -r _lane sidecar_id _status_file log_file pid_file; do
|
||||
stop_lane "$sidecar_id" "$pid_file" "$log_file"
|
||||
done < "$lanes_file"
|
||||
}
|
||||
|
||||
poll_lane_status() {
|
||||
local sidecar_id="$1"
|
||||
local status_file="$2"
|
||||
local log_file="$3"
|
||||
local pid_file="$4"
|
||||
|
||||
"$CHUNK_BIN" sidecar exec \
|
||||
--sidecar-id "$sidecar_id" \
|
||||
--command bash \
|
||||
--args -lc \
|
||||
--args "if [ -f '$status_file' ]; then cat '$status_file'; elif test -s '$pid_file' && kill -0 \"\$(cat '$pid_file')\" 2>/dev/null; then echo running; elif ps -eo pid=,command= | awk -v target='$log_file' '\$0 ~ target && \$0 !~ /awk/ { found=1 } END { exit found ? 0 : 1 }'; then echo running; else echo missing; fi" 2>&1
|
||||
}
|
||||
|
||||
poll_lanes() {
|
||||
local started_at="$1"
|
||||
local last_heartbeat=0
|
||||
local completed_file="${state_dir}/completed"
|
||||
local failed=0
|
||||
|
||||
: > "$completed_file"
|
||||
|
||||
while true; do
|
||||
local all_done=1
|
||||
|
||||
while IFS=$'\t' read -r lane sidecar_id status_file log_file pid_file; do
|
||||
if grep -qx "$lane" "$completed_file"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
local poll_status=0
|
||||
local poll_output
|
||||
local status
|
||||
|
||||
poll_output="$(poll_lane_status "$sidecar_id" "$status_file" "$log_file" "$pid_file")" || poll_status=$?
|
||||
if [[ "$poll_status" != "0" ]]; then
|
||||
echo " -> ${lane} status poll failed: $(printf '%s\n' "$poll_output" | head -1)"
|
||||
all_done=0
|
||||
continue
|
||||
fi
|
||||
|
||||
status="$(printf '%s\n' "$poll_output" | tail -1 | tr -d '[:space:]')"
|
||||
case "$status" in
|
||||
0)
|
||||
echo "$lane" >> "$completed_file"
|
||||
echo " -> ${lane} passed"
|
||||
fetch_remote_log_tail "$lane" "$sidecar_id" "$log_file"
|
||||
;;
|
||||
running|"")
|
||||
all_done=0
|
||||
;;
|
||||
missing)
|
||||
echo " -> ${lane} stopped before writing a status file"
|
||||
fetch_remote_log_tail "$lane" "$sidecar_id" "$log_file"
|
||||
failed=1
|
||||
echo "$lane" >> "$completed_file"
|
||||
;;
|
||||
*)
|
||||
echo " -> ${lane} failed with status ${status}"
|
||||
fetch_remote_log_tail "$lane" "$sidecar_id" "$log_file"
|
||||
failed=1
|
||||
echo "$lane" >> "$completed_file"
|
||||
;;
|
||||
esac
|
||||
done < "$lanes_file"
|
||||
|
||||
if [[ "$failed" != "0" ]]; then
|
||||
stop_all_lanes
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$all_done" == "1" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local elapsed
|
||||
elapsed=$(($(date +%s) - started_at))
|
||||
if [[ "$elapsed" -ge "$timeout_seconds" ]]; then
|
||||
echo "Chunk sidecar lanes timed out after ${elapsed}s"
|
||||
stop_all_lanes
|
||||
return 124
|
||||
fi
|
||||
|
||||
if [[ $((elapsed - last_heartbeat)) -ge 60 ]]; then
|
||||
echo " -> Sidecar lanes still running (${elapsed}s elapsed)"
|
||||
last_heartbeat="$elapsed"
|
||||
fi
|
||||
|
||||
sleep "$poll_interval"
|
||||
done
|
||||
}
|
||||
|
||||
if ! resolve_chunk_bin; then
|
||||
echo "Chunk CLI not found"
|
||||
exit "$unavailable_status"
|
||||
fi
|
||||
|
||||
org_id="$(load_org_id)"
|
||||
if [[ -z "$org_id" ]]; then
|
||||
echo "Chunk org id not found"
|
||||
exit "$unavailable_status"
|
||||
fi
|
||||
|
||||
echo "Chunk sidecar lanes:"
|
||||
echo " frontend: ${frontend_name}"
|
||||
echo " rust: ${rust_name}"
|
||||
echo " playwright: ${playwright_name}"
|
||||
if [[ -n "${SIDECAR_FRONTEND_ID:-}${SIDECAR_RUST_ID:-}${SIDECAR_PLAYWRIGHT_ID:-}" ]]; then
|
||||
echo " explicit sidecar IDs are set for one or more lanes"
|
||||
fi
|
||||
echo " vitest workers=${vitest_coverage_max_workers}; frontend coverage shards=${frontend_coverage_shards}; playwright shards=${playwright_shards}; concurrency=${playwright_concurrency}; cargo jobs=${cargo_build_jobs}"
|
||||
|
||||
if ! frontend_id="$(ensure_sidecar "$frontend_name" "${SIDECAR_FRONTEND_ID:-}")"; then
|
||||
echo "Chunk frontend sidecar unavailable"
|
||||
exit "$unavailable_status"
|
||||
fi
|
||||
if ! rust_id="$(ensure_sidecar "$rust_name" "${SIDECAR_RUST_ID:-}")"; then
|
||||
echo "Chunk rust sidecar unavailable"
|
||||
exit "$unavailable_status"
|
||||
fi
|
||||
if ! playwright_id="$(ensure_sidecar "$playwright_name" "${SIDECAR_PLAYWRIGHT_ID:-}")"; then
|
||||
echo "Chunk Playwright sidecar unavailable"
|
||||
exit "$unavailable_status"
|
||||
fi
|
||||
|
||||
echo "Syncing worktree to sidecar lanes..."
|
||||
if ! sync_all_lanes; then
|
||||
exit "$unavailable_status"
|
||||
fi
|
||||
|
||||
started_at=$(date +%s)
|
||||
echo "Launching sidecar lanes..."
|
||||
launch_lane frontend "$frontend_id"
|
||||
if [[ "$rust_changed" == "true" ]]; then
|
||||
launch_lane rust "$rust_id"
|
||||
else
|
||||
echo " -> Rust lane skipped because RUST_CHANGED=false"
|
||||
fi
|
||||
launch_lane playwright "$playwright_id"
|
||||
|
||||
if ! poll_lanes "$started_at"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
elapsed=$(($(date +%s) - started_at))
|
||||
echo "Chunk sidecar lanes passed in ${elapsed}s"
|
||||
exit 0
|
||||
115
product-source/hololake-platform/.chunk/run-sidecar-gates.sh
Normal file
115
product-source/hololake-platform/.chunk/run-sidecar-gates.sh
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
start_time=$(date +%s)
|
||||
log_dir="${TMPDIR:-/tmp}/tolaria-sidecar-gates-$$"
|
||||
rust_changed="${RUST_CHANGED:-true}"
|
||||
rust_phase="${SIDECAR_RUST_PHASE:-after-coverage}"
|
||||
playwright_phase="${SIDECAR_PLAYWRIGHT_PHASE:-after}"
|
||||
playwright_shards="${PLAYWRIGHT_SHARDS:-8}"
|
||||
|
||||
mkdir -p "$log_dir"
|
||||
|
||||
if [[ -z "${VITEST_COVERAGE_MAX_WORKERS:-}" ]]; then
|
||||
if [[ "$playwright_phase" == "early" ]]; then
|
||||
export VITEST_COVERAGE_MAX_WORKERS="${SIDECAR_EARLY_VITEST_MAX_WORKERS:-2}"
|
||||
else
|
||||
export VITEST_COVERAGE_MAX_WORKERS="${SIDECAR_VITEST_MAX_WORKERS:-3}"
|
||||
fi
|
||||
fi
|
||||
|
||||
elapsed_seconds() {
|
||||
printf '%s' "$(($(date +%s) - start_time))"
|
||||
}
|
||||
|
||||
log_gate() {
|
||||
printf '[sidecar-gates +%ss] %s\n' "$(elapsed_seconds)" "$*"
|
||||
}
|
||||
|
||||
run_job() {
|
||||
local name="$1"
|
||||
shift
|
||||
local log_file="${log_dir}/${name}.log"
|
||||
|
||||
(
|
||||
set +e
|
||||
log_gate "${name} started"
|
||||
"$@" 2>&1 | tee "$log_file"
|
||||
local status=${PIPESTATUS[0]}
|
||||
log_gate "${name} exited with status ${status}"
|
||||
exit "$status"
|
||||
) &
|
||||
printf '%s:%s\n' "$name" "$!" >> "$jobs_file"
|
||||
}
|
||||
|
||||
terminate_jobs() {
|
||||
local pids
|
||||
pids="$(jobs -pr || true)"
|
||||
if [[ -n "$pids" ]]; then
|
||||
kill $pids 2>/dev/null || true
|
||||
sleep 2
|
||||
kill -KILL $pids 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
jobs_file="${log_dir}/jobs"
|
||||
: > "$jobs_file"
|
||||
trap terminate_jobs INT TERM
|
||||
|
||||
wait_for_jobs() {
|
||||
local failures=0
|
||||
|
||||
while IFS=: read -r name pid; do
|
||||
if wait "$pid"; then
|
||||
printf '[sidecar-gates] %s passed\n' "$name"
|
||||
else
|
||||
failures=1
|
||||
printf '[sidecar-gates] %s failed\n' "$name"
|
||||
fi
|
||||
done < "$jobs_file"
|
||||
|
||||
return "$failures"
|
||||
}
|
||||
|
||||
log_gate "rust phase=${rust_phase}; playwright phase=${playwright_phase}; shards=${playwright_shards}; concurrency=${PLAYWRIGHT_CONCURRENCY:-${playwright_shards}}; vitest workers=${VITEST_COVERAGE_MAX_WORKERS:-4}"
|
||||
|
||||
run_job frontend-lint pnpm lint
|
||||
run_job frontend-build pnpm build
|
||||
run_job frontend-coverage pnpm test:coverage --silent
|
||||
|
||||
if [[ "$rust_changed" == "true" && "$rust_phase" == "early" ]]; then
|
||||
run_job rust bash .chunk/run-rust-gate.sh
|
||||
elif [[ "$rust_changed" != "true" ]]; then
|
||||
log_gate 'rust skipped because RUST_CHANGED=false'
|
||||
fi
|
||||
|
||||
if [[ "$playwright_phase" == "early" ]]; then
|
||||
run_job playwright-smoke bash .chunk/run-playwright-shards.sh "$playwright_shards"
|
||||
fi
|
||||
|
||||
if ! wait_for_jobs; then
|
||||
if [[ "$playwright_phase" == "early" ]]; then
|
||||
log_gate 'one or more sidecar gates failed'
|
||||
else
|
||||
log_gate 'stopping before Playwright because a prerequisite gate failed'
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$playwright_phase" != "early" || ( "$rust_changed" == "true" && "$rust_phase" != "early" ) ]]; then
|
||||
: > "$jobs_file"
|
||||
if [[ "$rust_changed" == "true" && "$rust_phase" != "early" ]]; then
|
||||
run_job rust bash .chunk/run-rust-gate.sh
|
||||
fi
|
||||
if [[ "$playwright_phase" != "early" ]]; then
|
||||
run_job playwright-smoke bash .chunk/run-playwright-shards.sh "$playwright_shards"
|
||||
fi
|
||||
|
||||
if ! wait_for_jobs; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log_gate "completed in $(elapsed_seconds)s"
|
||||
|
||||
exit 0
|
||||
136
product-source/hololake-platform/.chunk/run-sidecar-lane.sh
Executable file
136
product-source/hololake-platform/.chunk/run-sidecar-lane.sh
Executable file
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
lane="${1:-}"
|
||||
start_time=$(date +%s)
|
||||
|
||||
elapsed_seconds() {
|
||||
printf '%s' "$(($(date +%s) - start_time))"
|
||||
}
|
||||
|
||||
log_lane() {
|
||||
printf '[sidecar-%s +%ss] %s\n' "$lane" "$(elapsed_seconds)" "$*"
|
||||
}
|
||||
|
||||
run_job() {
|
||||
local name="$1"
|
||||
shift
|
||||
local log_file="${log_dir}/${name}.log"
|
||||
|
||||
(
|
||||
set +e
|
||||
log_lane "${name} started"
|
||||
"$@" 2>&1 | tee "$log_file"
|
||||
local status=${PIPESTATUS[0]}
|
||||
log_lane "${name} exited with status ${status}"
|
||||
exit "$status"
|
||||
) &
|
||||
printf '%s:%s\n' "$name" "$!" >> "$jobs_file"
|
||||
}
|
||||
|
||||
sync_node_dependencies() {
|
||||
log_lane "syncing pnpm dependencies with lockfile"
|
||||
pnpm install --frozen-lockfile
|
||||
}
|
||||
|
||||
terminate_jobs() {
|
||||
local pids
|
||||
pids="$(jobs -pr || true)"
|
||||
if [[ -n "$pids" ]]; then
|
||||
kill $pids 2>/dev/null || true
|
||||
sleep 2
|
||||
kill -KILL $pids 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
wait_for_jobs() {
|
||||
local failures=0
|
||||
|
||||
while IFS=: read -r name pid; do
|
||||
if wait "$pid"; then
|
||||
printf '[sidecar-%s] %s passed\n' "$lane" "$name"
|
||||
else
|
||||
failures=1
|
||||
printf '[sidecar-%s] %s failed\n' "$lane" "$name"
|
||||
fi
|
||||
done < "$jobs_file"
|
||||
|
||||
return "$failures"
|
||||
}
|
||||
|
||||
run_frontend_coverage_job() {
|
||||
local shard_count="${FRONTEND_COVERAGE_SHARDS:-1}"
|
||||
|
||||
if [[ ! "$shard_count" =~ ^[1-9][0-9]*$ ]]; then
|
||||
printf 'FRONTEND_COVERAGE_SHARDS must be a positive integer\n' >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
if [[ "$shard_count" == "1" ]]; then
|
||||
run_job frontend-coverage pnpm test:coverage --silent
|
||||
return
|
||||
fi
|
||||
|
||||
run_job frontend-coverage node scripts/run-vitest-coverage-shards.mjs --silent
|
||||
}
|
||||
|
||||
run_frontend_lane() {
|
||||
log_dir="${TMPDIR:-/tmp}/tolaria-sidecar-frontend-$$"
|
||||
jobs_file="${log_dir}/jobs"
|
||||
mkdir -p "$log_dir"
|
||||
: > "$jobs_file"
|
||||
trap terminate_jobs INT TERM
|
||||
|
||||
sync_node_dependencies
|
||||
|
||||
export VITEST_COVERAGE_MAX_WORKERS="${VITEST_COVERAGE_MAX_WORKERS:-2}"
|
||||
log_lane "vitest workers=${VITEST_COVERAGE_MAX_WORKERS}; coverage shards=${FRONTEND_COVERAGE_SHARDS:-1}"
|
||||
run_job frontend-lint pnpm lint
|
||||
run_job frontend-build pnpm build
|
||||
|
||||
if ! wait_for_jobs; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
: > "$jobs_file"
|
||||
run_frontend_coverage_job
|
||||
wait_for_jobs
|
||||
}
|
||||
|
||||
run_rust_lane() {
|
||||
if [[ "${RUST_CHANGED:-true}" != "true" ]]; then
|
||||
log_lane 'skipped because RUST_CHANGED=false'
|
||||
return 0
|
||||
fi
|
||||
|
||||
bash .chunk/run-rust-gate.sh
|
||||
}
|
||||
|
||||
run_playwright_lane() {
|
||||
sync_node_dependencies
|
||||
|
||||
export PLAYWRIGHT_SHARED_SERVER="${PLAYWRIGHT_SHARED_SERVER:-1}"
|
||||
export PLAYWRIGHT_CONCURRENCY="${PLAYWRIGHT_CONCURRENCY:-4}"
|
||||
local shards="${PLAYWRIGHT_SHARDS:-8}"
|
||||
|
||||
log_lane "shards=${shards}; concurrency=${PLAYWRIGHT_CONCURRENCY}; shared server=${PLAYWRIGHT_SHARED_SERVER}"
|
||||
bash .chunk/run-playwright-shards.sh "$shards"
|
||||
}
|
||||
|
||||
case "$lane" in
|
||||
frontend)
|
||||
run_frontend_lane
|
||||
;;
|
||||
rust)
|
||||
run_rust_lane
|
||||
;;
|
||||
playwright)
|
||||
run_playwright_lane
|
||||
;;
|
||||
*)
|
||||
printf 'Usage: %s frontend|rust|playwright\n' "$0" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
log_lane "completed in $(elapsed_seconds)s"
|
||||
Loading…
Reference in a new issue