Skip to content

chore(deps): bump dompurify from 3.4.3 to 3.4.13 in /dashboard #7753

chore(deps): bump dompurify from 3.4.3 to 3.4.13 in /dashboard

chore(deps): bump dompurify from 3.4.3 to 3.4.13 in /dashboard #7753

Workflow file for this run

name: CI
on:
pull_request:
branches:
- main
- develop
push:
branches:
- main
- develop
tags:
- 'v*'
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
lint-pr-title:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: 'feat
fix
docs
style
refactor
perf
test
build
ci
chore
revert
'
requireScope: false
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '22'
cache: npm
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Run hygiene check
run: npm run hygiene-check
- name: 'Security check - prevent shell: true'
run: npm run security-check
- name: Run linter
run: npm run lint
feat-minor-bump-gate:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Enforce approved minor bump label for feat PRs
uses: actions/github-script@v9
with:
script: |
const pr = context.payload.pull_request;
if (!pr) {
core.info('Not a pull request event; skipping gate.');
return;
}
// Fetch live PR data from the API instead of using the frozen payload.
// This ensures re-runs pick up title changes and labels added after the initial push.
const { data: livePr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
});
const title = livePr.title || '';
const isFeat = /^feat(\(.+\))?!?:\s/i.test(title);
if (!isFeat) {
core.info(`PR title is not feat:* (${title}); gate passed.`);
return;
}
const labels = (livePr.labels || []).map(label => label.name);
if (labels.includes('approved-minor-bump')) {
core.info('approved-minor-bump label present; feat gate passed.');
return;
}
core.setFailed('feat: PRs require the approved-minor-bump label before CI can pass.');
sdk-drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v4
id: filter
with:
filters: |
sdk-related:
- 'openapi.yaml'
- 'src/routes/**'
- 'src/schemas/**'
- 'packages/client/**'
- 'packages/python-client/**'
- '.github/workflows/ci.yml'
- uses: actions/setup-node@v6
if: github.event_name == 'push' || steps.filter.outputs.sdk-related == 'true'
with:
node-version: '22'
cache: npm
- uses: actions/setup-python@v6
if: github.event_name == 'push' || steps.filter.outputs.sdk-related == 'true'
with:
python-version: '3.12'
cache: pip
cache-dependency-path: packages/python-client/pyproject.toml
- name: Install dependencies
if: github.event_name == 'push' || steps.filter.outputs.sdk-related == 'true'
run: npm ci
- name: Check generated OpenAPI contract
if: github.event_name == 'push' || steps.filter.outputs.sdk-related == 'true'
run: npm run openapi:check
- name: Check generated TypeScript SDK
if: github.event_name == 'push' || steps.filter.outputs.sdk-related == 'true'
run: npm run sdk:ts:check
- name: Check generated Python SDK
if: github.event_name == 'push' || steps.filter.outputs.sdk-related == 'true'
run: npm run sdk:py:check
test:
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
node-version:
- '20'
- '22'
steps:
- uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: npm
- name: Install dependencies
run: npm ci
- name: Security audit
run: npm audit --audit-level=high
- name: Lockfile lint
run: npx lockfile-lint --type npm --path package-lock.json --validate-https
- name: TypeScript check
run: npx tsc --noEmit
- name: Build
run: npm run build
- name: Run server smoke UAT
run: npm run test:smoke
- name: Start Aegis
shell: bash
run: |
node dist/cli.js --port 9100 > aegis.log 2>&1 &
echo "AEGIS_PID=$!" >> "$GITHUB_ENV"
- name: Smoke test health endpoint
run: node scripts/ci-smoke-health.mjs
- name: Stop Aegis
if: always()
shell: bash
run: |
if [ -n "${AEGIS_PID:-}" ]; then
kill "$AEGIS_PID" || true
fi
- name: Check bundle size
run: "THRESHOLD_KB=2080\nSERVER_SIZE=$(find dist/ -name \"*.js\" ! -path \"\
*/__tests__/*\" ! -path \"*/dashboard/*\" -exec du -ck {} + | tail -1 | awk '{print $1}')\nSERVER_SIZE_KB=$((SERVER_SIZE))\n\
echo \"## Bundle Size Report\" >> \"$GITHUB_STEP_SUMMARY\"\necho \"\" >> \"\
$GITHUB_STEP_SUMMARY\"\necho \"| Scope | Size (KB) | Threshold (KB) | Status\
\ |\" >> \"$GITHUB_STEP_SUMMARY\"\necho \"|-------|-----------|----------------|--------|\"\
\ >> \"$GITHUB_STEP_SUMMARY\"\nif [ \"$SERVER_SIZE_KB\" -gt \"$THRESHOLD_KB\"\
\ ]; then\n echo \"| Server (excl. tests) | ${SERVER_SIZE_KB} | ${THRESHOLD_KB}\
\ | \u274C Exceeds threshold |\" >> \"$GITHUB_STEP_SUMMARY\"\n echo \"::error::Server\
\ bundle size ${SERVER_SIZE_KB}KB exceeds ${THRESHOLD_KB}KB threshold\"\n\
\ exit 1\nelse\n echo \"| Server (excl. tests) | ${SERVER_SIZE_KB} | ${THRESHOLD_KB}\
\ | \u2705 Within budget |\" >> \"$GITHUB_STEP_SUMMARY\"\n echo \"Server\
\ bundle size: ${SERVER_SIZE_KB}KB (threshold: ${THRESHOLD_KB}KB)\"\nfi\n"
- name: Build dashboard
run: cd dashboard && npm ci && npm run build
- name: Run dashboard E2E tests (PR gate)
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20'
run: cd dashboard && npx vitest run
- name: Run tests with coverage
run: npm test -- --coverage
- name: Enforce coverage thresholds
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20'
run: |
echo "## Coverage Threshold Enforcement" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Metric | Threshold | Enforced |" >> "$GITHUB_STEP_SUMMARY"
echo "|--------|-----------|----------|" >> "$GITHUB_STEP_SUMMARY"
echo "| Lines | 65% | ✅ |" >> "$GITHUB_STEP_SUMMARY"
echo "| Branches | 65% | ✅ |" >> "$GITHUB_STEP_SUMMARY"
echo "| Functions | 65% | ✅ |" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "> Thresholds are enforced by vitest config (vitest.config.ts)." >> "$GITHUB_STEP_SUMMARY"
echo "> If this step runs, all coverage thresholds passed." >> "$GITHUB_STEP_SUMMARY"
- name: Upload coverage reports
uses: actions/upload-artifact@v4
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20'
with:
name: coverage-report
path: coverage/
retention-days: 7
- name: Audit tracked files
run: "FOUND=$(git ls-files | grep -E '(^should$|results\\.tsv|^state/|\\.tsbuildinfo$|\\\
.env$|\\.log$|\\.tmp$|\\.bak$|\\.swp$)' || true)\nif [ -n \"$FOUND\" ]; then\n\
\ echo \"::error::Blacklisted files found in git tracking\"\n echo \"$FOUND\"\
\n exit 1\nfi\necho \"Audit passed - no blacklisted files found\"\n"
platform-smoke:
if: ${{ (github.event_name == 'pull_request' && github.base_ref == 'develop') || (github.event_name == 'push' && github.ref == 'refs/heads/develop') }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- windows-latest
- macos-latest
node-version:
- '22'
steps:
- uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: npm
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run server smoke UAT
run: npm run test:smoke
- name: Run platform smoke subset
run: >
npx vitest run
src/__tests__/platform-shell.test.ts
src/__tests__/path-utils-909.test.ts
src/__tests__/hook-paths-909.test.ts
src/__tests__/startup.test.ts
src/__tests__/config.test.ts
- name: Run config watcher smoke
run: npx vitest run src/__tests__/config-hot-reload-1753.test.ts
test-matrix:
if: ${{ startsWith(github.ref, 'refs/tags/') }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
node-version:
- '20'
- '22'
steps:
- uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: npm
- name: Install dependencies
run: npm ci
- name: Security audit
run: npm audit --audit-level=high
- name: Lockfile lint
run: npx lockfile-lint --type npm --path package-lock.json --validate-https
- name: TypeScript check
run: npx tsc --noEmit
- name: Build
run: npm run build
- name: Run server smoke UAT
run: npm run test:smoke
- name: Start Aegis (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: |
node dist/cli.js --port 9100 > aegis.log 2>&1 &
echo "AEGIS_PID=$!" >> "$GITHUB_ENV"
- name: Start Aegis (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$proc = Start-Process -FilePath node -ArgumentList 'dist/cli.js', '--port', '9100' -PassThru -WindowStyle Hidden
"AEGIS_PID=$($proc.Id)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Smoke test health endpoint (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: node scripts/ci-smoke-health.mjs
- name: Smoke test health endpoint (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: node scripts/ci-smoke-health.mjs
- name: Stop Aegis (Linux/macOS)
if: always() && runner.os != 'Windows'
shell: bash
run: |
if [ -n "${AEGIS_PID:-}" ]; then
kill "$AEGIS_PID" || true
fi
- name: Stop Aegis (Windows)
if: always() && runner.os == 'Windows'
shell: pwsh
run: |
if ($env:AEGIS_PID) {
Stop-Process -Id ([int]$env:AEGIS_PID) -Force -ErrorAction SilentlyContinue
}
- name: Check bundle size
if: runner.os != 'Windows'
run: "THRESHOLD_KB=2080\nSERVER_SIZE=$(find dist/ -name \"*.js\" ! -path \"\
*/__tests__/*\" ! -path \"*/dashboard/*\" -exec du -ck {} + | tail -1 | awk '{print $1}')\nSERVER_SIZE_KB=$((SERVER_SIZE))\n\
echo \"## Bundle Size Report\" >> \"$GITHUB_STEP_SUMMARY\"\necho \"\" >> \"\
$GITHUB_STEP_SUMMARY\"\necho \"| Scope | Size (KB) | Threshold (KB) | Status\
\ |\" >> \"$GITHUB_STEP_SUMMARY\"\necho \"|-------|-----------|----------------|--------|\"\
\ >> \"$GITHUB_STEP_SUMMARY\"\nif [ \"$SERVER_SIZE_KB\" -gt \"$THRESHOLD_KB\"\
\ ]; then\n echo \"| Server (excl. tests) | ${SERVER_SIZE_KB} | ${THRESHOLD_KB}\
\ | ❌ Exceeds threshold |\" >> \"$GITHUB_STEP_SUMMARY\"\n echo \"::error::Server\
\ bundle size ${SERVER_SIZE_KB}KB exceeds ${THRESHOLD_KB}KB threshold\"\n\
\ exit 1\nelse\n echo \"| Server (excl. tests) | ${SERVER_SIZE_KB} | ${THRESHOLD_KB}\
\ | ✅ Within budget |\" >> \"$GITHUB_STEP_SUMMARY\"\n echo \"Server bundle\
\ size: ${SERVER_SIZE_KB}KB (threshold: ${THRESHOLD_KB}KB)\"\nfi\n"
- name: Build dashboard
run: cd dashboard && npm ci && npm run build
- name: Run dashboard E2E tests (PR gate)
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20'
run: cd dashboard && npx vitest run
- name: Run tests with coverage
run: npm test -- --coverage
- name: Upload coverage reports
uses: actions/upload-artifact@v4
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '20'
with:
name: coverage-report
path: coverage/
retention-days: 7
- name: Audit tracked files
if: runner.os != 'Windows'
run: "FOUND=$(git ls-files | grep -E '(^should$|results\\.tsv|^state/|\\.tsbuildinfo$|\\\
.env$|\\.log$|\\.tmp$|\\.bak$|\\.swp$)' || true)\nif [ -n \"$FOUND\" ]; then\n\
\ echo \"::error::Blacklisted files found in git tracking\"\n echo \"$FOUND\"\
\n exit 1\nfi\necho \"Audit passed - no blacklisted files found\"\n"
dashboard-e2e:
if: github.event_name == 'pull_request' && github.base_ref == 'develop'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '22'
cache: npm
- name: Install dashboard dependencies
run: cd dashboard && npm ci
- name: Install Playwright Chromium
run: cd dashboard && npx playwright install --with-deps chromium
- name: Run dashboard E2E (required specs)
run: cd dashboard && npx playwright test e2e/login.spec.ts e2e/session-list.spec.ts e2e/audit.spec.ts --project=chromium
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: dashboard-playwright-report
path: dashboard/playwright-report/
retention-days: 7
- name: Upload Playwright test results
if: always()
uses: actions/upload-artifact@v4
with:
name: dashboard-playwright-test-results
path: dashboard/test-results/
retention-days: 7
auto-label-test:
runs-on: ubuntu-latest
if: "github.event_name == 'push' ||\n(github.event_name == 'pull_request' && (\n\
\ contains(github.event.pull_request.changed_files, '.github/actions/auto-label/')\
\ ||\n contains(github.event.pull_request.changed_files, '.github/workflows/auto-label.yml')\n\
))\n"
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '22'
- name: Install action dependencies
working-directory: .github/actions/auto-label
run: npm ci
- name: Run auto-label tests
working-directory: .github/actions/auto-label
run: npx vitest run --reporter=verbose