Skip to content

Merge pull request #186 from lidge-jun/codex/ui-polish-wp3-typography #783

Merge pull request #186 from lidge-jun/codex/ui-polish-wp3-typography

Merge pull request #186 from lidge-jun/codex/ui-polish-wp3-typography #783

Workflow file for this run

name: CI
permissions:
contents: read
on:
push:
branches: [main, dev]
schedule:
- cron: '17 3 * * *'
workflow_dispatch:
inputs:
sha:
description: 'Full 40-char SHA to check out and test (release candidate gate)'
required: false
type: string
concurrency:
# Dispatched candidate runs share the release-candidate ref, so key the group
# on the input SHA too — otherwise a second candidate cancels the first.
group: ci-${{ github.workflow }}-${{ github.ref }}-${{ github.event.inputs.sha || '' }}
cancel-in-progress: true
jobs:
test:
name: test (${{ matrix.os }}, node ${{ matrix.node }}, npm ${{ matrix.npm }})
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
node: '22.23.0'
npm: '11.18.0'
- os: ubuntu-latest
node: '24.17.0'
npm: '12.0.0'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ github.event.inputs.sha || github.sha }}
- name: Assert the checked-out SHA is the dispatched one
if: ${{ github.event.inputs.sha != '' && github.event.inputs.sha != null }}
shell: bash
env:
WANT: ${{ github.event.inputs.sha }}
run: |
ACTUAL=$(git rev-parse HEAD)
if [ "$WANT" != "$ACTUAL" ]; then
echo "dispatch asked for $WANT but checked out $ACTUAL"
exit 1
fi
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node }}
# npm's content-addressed cache is npm-version agnostic, so sharing it
# across the npm 11/12 matrix legs on the same OS is intentional.
cache: npm
cache-dependency-path: |
package-lock.json
ui/package-lock.json
- name: Structure line-count drift (fast fail)
run: node scripts/refresh-structure-line-counts.mjs --check
- name: Pin npm
run: npm install -g npm@${{ matrix.npm }}
- name: Install root deps
run: npm ci
- name: Provider registry generated-file drift
run: node scripts/generate-provider-types.mjs --check
- name: Native dependency smoke
run: npm run test:native-deps
- name: Install ui deps
run: npm --prefix ui ci --no-audit --no-fund
- name: Install policy contract
run: npm run test:install-policy
- name: npm 12 pending-script oracle
if: matrix.npm == '12.0.0'
run: npm run test:install-policy:npm12
- name: Typecheck
run: npm run typecheck
- name: Typecheck tests
run: npm run typecheck:tests
- name: Test inventory
run: npm run test:inventory
- name: Build server (tsc emit)
run: npm run build:server
- name: Build cli (tsc emit)
run: npm run build:cli
- name: Build ui
run: npm --prefix ui run build
- name: Run tests
run: npm test
timeout-minutes: 20
- name: Lint package.json
if: matrix.os == 'ubuntu-latest' && matrix.npm == '11.18.0'
run: npm run lint:pkg
- name: Audit root production dependencies
if: matrix.os == 'ubuntu-latest' && matrix.npm == '11.18.0'
run: node scripts/audit-gate.mjs --audit-level high --omit dev
- name: Audit UI build dependencies
if: matrix.os == 'ubuntu-latest' && matrix.npm == '11.18.0'
run: node scripts/audit-gate.mjs --prefix ui --audit-level high
- name: Package install smoke
run: npm run test:package-install
timeout-minutes: 15
- name: Global install, update, and package-local OAuth smoke
run: npm run test:package-global-update
timeout-minutes: 15
- name: CLI smoke (grok --help)
run: node bin/ima2.js grok --help
- name: CLI smoke (video --help)
run: node bin/ima2.js video --help
- name: CLI smoke (capabilities)
run: node bin/ima2.js capabilities --json
- name: CLI smoke (--version)
run: node bin/ima2.js --version
- name: Graceful shutdown (SIGINT clean exit)
if: runner.os != 'Windows'
shell: bash
run: |
node server.js &
SERVER_PID=$!
sleep 3
kill -SIGINT $SERVER_PID 2>/dev/null || true
TIMEOUT=10; while kill -0 $SERVER_PID 2>/dev/null && [ $TIMEOUT -gt 0 ]; do sleep 1; TIMEOUT=$((TIMEOUT-1)); done
if kill -0 $SERVER_PID 2>/dev/null; then
echo "::error::Server did not exit within 10s after SIGINT"
kill -9 $SERVER_PID 2>/dev/null || true
exit 1
fi
wait $SERVER_PID
EXIT_CODE=$?
echo "Server exited with code $EXIT_CODE"
if [ $EXIT_CODE -ne 0 ]; then
echo "::warning::Server exited with non-zero code $EXIT_CODE (may be signal-based exit)"
fi
- name: Verify install scripts in sync
if: matrix.os == 'ubuntu-latest' && matrix.npm == '11.18.0'
run: |
diff scripts/install-mac.sh site/public/install-mac.sh
diff scripts/install-linux.sh site/public/install-linux.sh
diff scripts/install-windows.ps1 site/public/install-windows.ps1
- name: Publish dry-run
if: matrix.os == 'ubuntu-latest' && matrix.npm == '11.18.0'
run: npm run publish:dry-run
# Windows is a supported install target, so its coverage is kept — but it is
# off the release path. The two Windows legs were the slowest thing on the
# board and they gated every release cut, while the only failure they ever
# produced was EPERM in a test's own `rmSync` teardown on a temp dir the OS
# had not released yet. That is a Windows filesystem behaviour, not a defect
# in the shipped package, and it blocked releases that were otherwise green
# on every other leg.
#
# `schedule` only: never on push, and never on the workflow_dispatch that
# release.yml uses for its candidate gate. A regression here is caught within
# a day and fixed on its own merit instead of stopping a release.
windows:
name: windows (node ${{ matrix.node }}, npm ${{ matrix.npm }})
if: github.event_name == 'schedule'
runs-on: windows-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- node: '22.23.0'
npm: '11.18.0'
- node: '24.17.0'
npm: '12.0.0'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node }}
cache: npm
cache-dependency-path: |
package-lock.json
ui/package-lock.json
- name: Pin npm
run: npm install -g npm@${{ matrix.npm }}
- name: Install root deps
run: npm ci
- name: Native dependency smoke
run: npm run test:native-deps
- name: Install ui deps
run: npm --prefix ui ci --no-audit --no-fund
- name: Typecheck
run: npm run typecheck
- name: Build server (tsc emit)
run: npm run build:server
- name: Build cli (tsc emit)
run: npm run build:cli
- name: Build ui
run: npm --prefix ui run build
- name: Run tests
run: npm test
timeout-minutes: 20
- name: Package install smoke
run: npm run test:package-install
timeout-minutes: 15
- name: CLI smoke (--version)
run: node bin/ima2.js --version
- name: CLI smoke (capabilities)
run: node bin/ima2.js capabilities --json
e2e:
name: frontend e2e (ubuntu)
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '22.23.0'
cache: npm
cache-dependency-path: |
package-lock.json
ui/package-lock.json
- name: Install root deps
run: npm ci
- name: Install ui deps
run: npm --prefix ui ci --no-audit --no-fund
- name: Install Playwright Chromium
run: npx --prefix ui playwright install --with-deps chromium
- name: Build ui
run: npm --prefix ui run build
- name: Run frontend e2e
run: npm --prefix ui run test:e2e
- name: Upload e2e failure artifacts
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-failure-context
path: ui/test-results/
if-no-files-found: ignore
retention-days: 7