response network popover takes the reference anatomy: the trusted-cer… #137
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| # Nightly full matrix: no path gating, no cache restore — the cold | |
| # safety net that catches anything the scoped runs wrongly skipped. | |
| schedule: | |
| - cron: '0 3 * * *' | |
| permissions: | |
| contents: read | |
| # A newer push to the same ref supersedes the running sweep — never | |
| # stack two full runs. | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Computes which slices of the tree a push touched, so the non-turbo | |
| # jobs (the extension shards) can skip when nothing they cover | |
| # changed. Turbo-driven jobs skip work through their cache instead. | |
| changes: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| outputs: | |
| extension: ${{ steps.filter.outputs.extension }} | |
| steps: | |
| # Only pushes have a diff base to gate on — every other trigger | |
| # runs the full matrix and never reads this job's output. | |
| - name: Checkout code | |
| if: github.event_name == 'push' | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect changed paths | |
| if: github.event_name == 'push' | |
| id: filter | |
| uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 | |
| with: | |
| filters: | | |
| extension: | |
| - 'apps/extension/**' | |
| - 'packages/**' | |
| - 'pnpm-lock.yaml' | |
| - 'package.json' | |
| - 'turbo.json' | |
| - 'tsconfig.base.json' | |
| - '.github/workflows/ci.yml' | |
| # Fast tripwires: lint (warn-only until the lint-debt session), | |
| # typecheck, and the i18n gates. Fails in minutes when a push is | |
| # structurally broken, while the test matrix grinds in parallel. | |
| gates: | |
| runs-on: ubuntu-latest | |
| # Job timeouts sit at ~2x each job's observed wall time so a wedged | |
| # infra step (dead apt mirror, hung install) releases the concurrency | |
| # slot in minutes instead of holding it for the 6h default. | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22.x | |
| cache: pnpm | |
| - name: Cache Electron | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/electron | |
| key: electron-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: electron-${{ runner.os }}- | |
| # Content-addressed replay of unchanged tasks across runs; the | |
| # nightly scheduled run stays cold on purpose. | |
| - name: Cache turbo | |
| if: github.event_name != 'schedule' | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: .turbo/cache | |
| key: turbo-gates-${{ runner.os }}-${{ github.sha }} | |
| restore-keys: turbo-gates-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Lint | |
| run: pnpm biome check . || echo "::warning::Lint issues found — see output above" | |
| - name: Typecheck all packages | |
| run: pnpm turbo typecheck | |
| - name: i18n hardcoded-string scan | |
| run: pnpm turbo scan:i18n | |
| - name: i18n locale-catalog lint | |
| run: pnpm turbo lint:i18n-locales | |
| # Plain-node vitest packages, serialized through turbo so suites that | |
| # bind ports (daemon, web) never contend on one VM. | |
| test-packages: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22.x | |
| cache: pnpm | |
| - name: Cache Electron | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/electron | |
| key: electron-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: electron-${{ runner.os }}- | |
| - name: Cache turbo | |
| if: github.event_name != 'schedule' | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: .turbo/cache | |
| key: turbo-test-packages-${{ runner.os }}-${{ github.sha }} | |
| restore-keys: turbo-test-packages-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Test node packages | |
| run: > | |
| pnpm turbo test --concurrency=1 | |
| --filter=@openheaders/core | |
| --filter=@openheaders/i18n | |
| --filter=@openheaders/oracle | |
| --filter=@openheaders/oracle-host-browser | |
| --filter=@openheaders/nm-host | |
| --filter=@openheaders/cli | |
| --filter=@openheaders/daemon | |
| --filter=@openheaders/web | |
| # The two electron-as-node suites, isolated on their own VM and | |
| # serialized — Electron suites flake under same-machine contention. | |
| test-electron-hosts: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22.x | |
| cache: pnpm | |
| - name: Cache Electron | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/electron | |
| key: electron-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: electron-${{ runner.os }}- | |
| # The runner's regional apt mirror (azure.archive) blackholes often | |
| # enough to wedge apt past its own timeouts — route straight to the | |
| # canonical archive, and keep the short acquire timeouts as the | |
| # backstop for any remaining slow leg. | |
| - name: Install Electron system dependencies | |
| run: > | |
| sudo sed -i 's|http://azure.archive.ubuntu.com/ubuntu|https://archive.ubuntu.com/ubuntu|' /etc/apt/apt-mirrors.txt && | |
| sudo apt-get -o Acquire::Retries=1 -o Acquire::http::Timeout=15 -o Acquire::https::Timeout=15 update && | |
| sudo apt-get -o Acquire::Retries=1 -o Acquire::http::Timeout=15 -o Acquire::https::Timeout=15 install -y | |
| libgtk-3-0 libnotify4 libnss3 libxss1 libasound2t64 libgbm1 | |
| - name: Cache turbo | |
| if: github.event_name != 'schedule' | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: .turbo/cache | |
| key: turbo-electron-hosts-${{ runner.os }}-${{ github.sha }} | |
| restore-keys: turbo-electron-hosts-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Test electron hosts | |
| run: > | |
| pnpm turbo test --concurrency=1 | |
| --filter=@openheaders/oracle-host-node | |
| --filter=@openheaders/desktop | |
| # The extension suite's cost is per-file overhead across ~1,400 test | |
| # files, so it shards near-linearly. Path-gated: only pushes that | |
| # touch the extension or its inputs pay the three runners; every | |
| # non-push trigger (PR, dispatch, nightly) runs unconditionally. | |
| test-extension: | |
| name: test-extension (shard ${{ matrix.shard }}/3) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| needs: changes | |
| if: github.event_name != 'push' || needs.changes.outputs.extension == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [1, 2, 3] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22.x | |
| cache: pnpm | |
| - name: Cache Electron | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/electron | |
| key: electron-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: electron-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # Typecheck stays off here: the shard runners never build workspace | |
| # deps, so @openheaders/ui's dist-pointed types resolve to any and | |
| # tsc storms. Test-file types ride the gates job's turbo typecheck | |
| # (extension typecheck script runs tsconfig.test.json too). | |
| - name: Test extension (shard ${{ matrix.shard }}/3) | |
| run: > | |
| pnpm --filter @openheaders/extension exec vitest run | |
| --shard=${{ matrix.shard }}/3 | |
| --typecheck.enabled=false | |
| --reporter=default --reporter=github-actions | |
| build-e2e: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22.x | |
| cache: pnpm | |
| - name: Cache Electron | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/electron | |
| key: electron-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: electron-${{ runner.os }}- | |
| # The runner's regional apt mirror (azure.archive) blackholes often | |
| # enough to wedge apt past its own timeouts — route straight to the | |
| # canonical archive, and keep the short acquire timeouts as the | |
| # backstop for any remaining slow leg. | |
| - name: Install Electron system dependencies | |
| run: > | |
| sudo sed -i 's|http://azure.archive.ubuntu.com/ubuntu|https://archive.ubuntu.com/ubuntu|' /etc/apt/apt-mirrors.txt && | |
| sudo apt-get -o Acquire::Retries=1 -o Acquire::http::Timeout=15 -o Acquire::https::Timeout=15 update && | |
| sudo apt-get -o Acquire::Retries=1 -o Acquire::http::Timeout=15 -o Acquire::https::Timeout=15 install -y | |
| libgtk-3-0 libnotify4 libnss3 libxss1 libasound2t64 libgbm1 | |
| - name: Cache turbo | |
| if: github.event_name != 'schedule' | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: .turbo/cache | |
| key: turbo-build-e2e-${{ runner.os }}-${{ github.sha }} | |
| restore-keys: turbo-build-e2e-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # The web, extension, and desktop builds each peak ~4GB, so on the | |
| # public 4-core/16GB runner two app builds share the box safely but | |
| # three would not — and the heap cap stays lifted past Node's | |
| # default so the big builds can reach their real working sets. | |
| # The extension builds its chrome target only: one leg proves the | |
| # pipeline, the e2e never loads it, and the four-browser matrix | |
| # belongs to the release lanes. | |
| - name: Build all packages | |
| run: pnpm turbo build --concurrency=2 --filter=!@openheaders/extension | |
| env: | |
| NODE_OPTIONS: --max-old-space-size=6144 | |
| - name: Build extension (chrome only) | |
| run: pnpm turbo build:chrome --filter=@openheaders/extension | |
| env: | |
| NODE_OPTIONS: --max-old-space-size=6144 | |
| # Ubuntu 24.04 confines unprivileged user namespaces behind AppArmor, | |
| # which breaks Electron's sandbox under xvfb. | |
| - name: Allow unprivileged user namespaces for the Electron sandbox | |
| run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 | |
| # The desktop's TUI gate probes PATH for `oh` — without it every | |
| # provisioning state collapses to the install dialog. | |
| - name: Put the built oh CLI on PATH | |
| run: | | |
| printf '#!/bin/sh\nexec node "%s/apps/cli/dist/cli.js" "$@"\n' "$PWD" | sudo tee /usr/local/bin/oh >/dev/null | |
| sudo chmod +x /usr/local/bin/oh | |
| command -v oh | |
| - name: E2E — CLI provisioning (desktop + oh + pty) | |
| run: xvfb-run --auto-servernum pnpm --filter @openheaders/desktop exec playwright test --trace retain-on-failure tests/e2e/cli-provision.spec.ts | |
| - name: Upload e2e traces on failure | |
| if: failure() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: cli-provision-e2e-results | |
| path: apps/desktop/tests/e2e/test-results | |
| if-no-files-found: ignore | |
| retention-days: 7 |