mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-01 04:42:10 +03:00
* fix(cli): stabilize setup-claude.test.ts flake — inject dry-run log sink (#5959) Root cause (isolated empirically, 5/10 fail on the pristine base): the dry-run path of syncClaudeProfilesFromModels console.log's a multi-byte box-drawing heading ("── [dry-run] … ──"). Under the node:test runner that write lands on the test child's stdout and corrupts the runner's V8-serialized event stream ~50% of the time ("Unable to deserialize cloned data due to invalid or unsupported version"), killing the file at the first logging test. ASCII-only logging never reproduced it (0/20); the unicode heading alone reproduced it (10/20). Fix: syncClaudeProfilesFromModels accepts an injectable log sink (opts.log, CLI default unchanged: console.log). The dry-run test injects a collector — keeping unicode off the child's stdout — and gains assertions on the dry-run report (path + parsed settings content), which FAIL on the old code (log ignored) and PASS on the new one. Validation: 0/30 failures post-fix vs 5/10 pre-fix on the same tree. Baselines: complexity 2003->2006 and cognitive 859->860 are inherited post-3a3d618fe release drift — measured identical on the pristine base with and without this change (notes added in both files). * test(ci): collect the orphaned tests/unit/executors/ directory (base-red unblock) #5800 created tests/unit/executors/ outside every unit-runner brace glob, so its 2 test files (firecrawl-fetch, xai-executor) never ran anywhere and check:test-discovery flags them as NEW orphans on the pristine base, red-flagging every PR into release/v3.8.44. Added 'executors' to the runner globs in package.json (7 scripts), ci.yml unit shards, quality.yml TIA glob, build-test-impact-map.mjs, and the test-discovery gate's COLLECTORS (the gate enforces those stay in sync). Both files pass when actually collected (10/10); cli+executors under suite flags: 99/99. * chore(quality): complexity baseline 2006 -> 2007 (CI-observed value) The GitHub fast-gates runner measures 2007 where local measures 2006 — the same local-vs-CI off-by-one documented in the 2026-06-26 note. Pin the CI-observed value so the gate is deterministic where it runs. * fix(i18n): add the 6 missing en.json keys flagged by settings-i18n-keys (base-red unblock) providers.iconUrlLabel/iconUrlHint (referenced by AddCompatibleProviderModal and EditCompatibleNodeModal) and settings.authz.cors.wildcard.title/desc (the #5602 CORS_ALLOW_ALL banner in AuthzSection) shipped without their en.json messages — 'direct translation calls have English messages' fails on the pristine release tip, red-flagging every PR. git log -S proves the keys never existed (not a merge-eat). Scanner test: 10/10 green.
149 lines
6.5 KiB
YAML
149 lines
6.5 KiB
YAML
name: Quality Gates
|
|
|
|
on:
|
|
pull_request:
|
|
branches: ["release/**"]
|
|
types: [opened, synchronize, reopened, ready_for_review]
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
CI_NODE_VERSION: "24"
|
|
|
|
jobs:
|
|
fast-gates:
|
|
name: Fast Quality Gates
|
|
runs-on: ubuntu-latest
|
|
# tsx gates (known-symbols, route-guard-membership) import modules that open
|
|
# SQLite on load; provide DB env so a fresh CI DB initializes cleanly.
|
|
env:
|
|
JWT_SECRET: ci-lint-secret-with-sufficient-length-for-validation
|
|
API_KEY_SECRET: ci-lint-api-key-secret-long
|
|
DISABLE_SQLITE_AUTO_BACKUP: "true"
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version: ${{ env.CI_NODE_VERSION }}
|
|
cache: npm
|
|
- run: npm ci
|
|
- run: npm run check:provider-consistency
|
|
- run: npm run check:fetch-targets
|
|
- run: npm run check:openapi-routes
|
|
- run: npm run check:docs-symbols
|
|
- name: Docs accuracy (fabricated-docs + i18n mirrors, strict)
|
|
run: npm run check:docs-all
|
|
- run: npm run check:deps
|
|
- run: npm run check:file-size
|
|
- run: npm run check:error-helper
|
|
- run: npm run check:migration-numbering
|
|
- run: npm run check:public-creds
|
|
- run: npm run check:db-rules
|
|
- run: npm run check:known-symbols
|
|
- run: npm run check:route-guard-membership
|
|
- run: npm run check:test-discovery
|
|
- run: npm run check:test-runner-api
|
|
# Guards tap.testFiles drift: a covering unit test absent from stryker.conf.json
|
|
# tap.testFiles makes its module's mutants survive on a cold nightly-mutation run,
|
|
# false-failing the blocking mutationScore ratchet. See check-mutation-test-coverage.mjs.
|
|
- run: npm run check:mutation-test-coverage
|
|
- run: npm run check:any-budget:t11
|
|
# Build-scope guard: fails if worktrees/cruft leak into the tsconfig include
|
|
# scope (would OOM `next build`). Instant. See incident 2026-06-25 / #5031.
|
|
- run: npm run check:build-scope
|
|
# Pack-policy (unexpected-files allowlist) WITHOUT a build — catches a stray file
|
|
# leaking into the npm tarball (v3.8.36: 6 ops bin/*.sh) per-PR instead of only on
|
|
# the release PR's heavy Package Artifact job.
|
|
- run: npm run check:pack-policy
|
|
# Complexity + cognitive-complexity ratchets on the fast-path (PR→release) so
|
|
# cycle drift is rebaselined PER-PR instead of cascading onto the release PR's
|
|
# Quality Ratchet (v3.8.36: +30 complexity / +15 cognitive surfaced only post-merge).
|
|
- run: npm run check:complexity
|
|
- run: npm run check:cognitive-complexity
|
|
- name: Typecheck (core)
|
|
run: npm run typecheck:core
|
|
# TIA: build the impact map at runtime (gitignored, ~21MB) and run only the
|
|
# unit tests impacted by this PR's changed files. Fail-safe runs the FULL
|
|
# unit suite on hub/unmapped changes — TIA accelerates, never replaces, the net.
|
|
#
|
|
# BLOCKING (flipped 2026-06-17). The pre-existing release unit test-debt that kept
|
|
# this advisory was cleared: #4030 (16 Zod/registry reds, lossless restore) and
|
|
# #4063 (the last red — the LiveWS boot test — root-caused as a real event-loop
|
|
# stall in the WS sidecar, fixed + relocated to the integration suite). A full
|
|
# ci.yml run on release/v3.8.28 then showed all 8 unit shards green, so PR->release
|
|
# now blocks on unit-test regressions in the impacted set (typecheck:core already
|
|
# blocked above). Fail-safe still runs the FULL unit suite on hub/unmapped changes.
|
|
- name: Impacted unit tests (TIA, fail-safe full; blocking)
|
|
env:
|
|
GITHUB_BASE_REF: ${{ github.base_ref }}
|
|
run: |
|
|
git fetch --no-tags origin "$GITHUB_BASE_REF" || true
|
|
node scripts/quality/build-test-impact-map.mjs
|
|
SEL="$(node scripts/quality/select-impacted-tests.mjs)"
|
|
if [ -z "$SEL" ]; then echo "No source/test changes — skipping unit tests"; exit 0; fi
|
|
# CI runners are 4-vCPU; run at --test-concurrency=4 (matching the ci.yml unit
|
|
# job) rather than test:unit's local-tuned concurrency=20. Oversubscribing the
|
|
# runner makes timing-sensitive tests (db-backup, upstream-timeout, ...) flake,
|
|
# which must not happen on a blocking gate. DATA_DIR isolation keeps the parallel
|
|
# run race-free regardless of concurrency.
|
|
if echo "$SEL" | grep -q "__RUN_ALL__"; then
|
|
echo "Fail-safe: running FULL unit suite (CI concurrency)"; npm run test:unit:ci; exit $?
|
|
fi
|
|
echo "Running impacted tests:"; echo "$SEL"
|
|
mapfile -t FILES <<< "$SEL"
|
|
node --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 "${FILES[@]}"
|
|
|
|
fast-vitest:
|
|
name: Vitest (fast-path)
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
JWT_SECRET: ci-lint-secret-with-sufficient-length-for-validation
|
|
API_KEY_SECRET: ci-lint-api-key-secret-long
|
|
DISABLE_SQLITE_AUTO_BACKUP: "true"
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version: ${{ env.CI_NODE_VERSION }}
|
|
cache: npm
|
|
- run: npm ci
|
|
- run: npm run test:vitest
|
|
|
|
fast-unit:
|
|
name: Unit Tests fast-path (${{ matrix.shard }}/2)
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
shard: [1, 2]
|
|
env:
|
|
JWT_SECRET: ci-lint-secret-with-sufficient-length-for-validation
|
|
API_KEY_SECRET: ci-lint-api-key-secret-long
|
|
DISABLE_SQLITE_AUTO_BACKUP: "true"
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version: ${{ env.CI_NODE_VERSION }}
|
|
cache: npm
|
|
- run: npm ci
|
|
- run: >
|
|
node --max-old-space-size=4096 --import tsx
|
|
--import ./tests/_setup/isolateDataDir.ts
|
|
--test --test-force-exit --test-concurrency=4 --test-shard=${{ matrix.shard }}/2
|
|
tests/unit/*.test.ts
|
|
"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,dashboard,db,db-adapters,docs,executors,gamification,guardrails,lib,mcp,runtime,security,services,settings,shared,ui}/**/*.test.ts"
|