mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-02 13:22:11 +03:00
OmniRoute v3.8.29 — 115 commits since v3.8.28. Full CHANGELOG + 41 i18n mirrors. All content quality gates green (build, unit 8/8, vitest 188/188, PR test policy, quality gates extended, docs sync, quality ratchet). Remaining red CI checks are pre-existing release flakes (coverage-shard/integration/node-compat teardown), a new transitive undici advisory in electron devDeps, and a workflow-level CodeQL fail (0 open alerts). VPS-validated by the operator.
112 lines
6.7 KiB
YAML
112 lines
6.7 KiB
YAML
name: Nightly Mutation
|
|
on:
|
|
schedule:
|
|
- cron: "17 3 * * *"
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
stryker:
|
|
name: Stryker mutation (batch ${{ matrix.batch.name }} — advisory)
|
|
runs-on: ubuntu-latest
|
|
# Mutation testing is expensive. History of the budget:
|
|
# - Full 8-module set TIMED OUT at the 180min cap (run 27705123780 = exactly 180min).
|
|
# The two god-files chatCore.ts/combo.ts dominated ~2/3 of the mutants and were
|
|
# removed from stryker.conf.json `mutate`.
|
|
# - The remaining 6 modules in 3 batches: auth.ts and accountFallback.ts are large; the
|
|
# a (auth+publicCreds) and b (accountFallback+error) batches still ran near the 180min
|
|
# cap (the perTest dry-run over ~130 covering test files is itself costly), so the two
|
|
# big modules are now ISOLATED into their own batches (a=auth, b=accountFallback).
|
|
# - Onda 3 / Fase 9 T5 re-add: combo.ts was split into 11 leaves; the 8 well-covered
|
|
# combo/* leaves are back in `mutate` (covered by the 24 combo-*.test.ts), grouped into
|
|
# 2 batches (d=heavy, e=light). After #4204 (D7b) merged, the reset-aware quota pair
|
|
# quotaScoring/quotaStrategies was added as batch f. A covering-test audit then added the
|
|
# 6 chatCore/* leaves with direct unit coverage as batch g. A follow-up then wrote dedicated
|
|
# unit tests for 6 more leaves and added them as batch h. A final follow-up added dedicated
|
|
# tests (no mock.module — fetch-override + crafted inputs + temp-DATA_DIR) for telemetryHelpers
|
|
# + memorySkillsInjection + semanticCache (its cache-HIT block now has a setCachedResponse
|
|
# fixture) as batch i — ALL 15/15 chatCore leaves are now mutated. See
|
|
# _mutate_godfiles_excluded_comment in stryker.conf.json.
|
|
# 9 PARALLEL batches, each overriding the mutate set via `--mutate` (Stryker 9 CLI:
|
|
# `-m, --mutate <comma-list>`; the conf's `mutate[]` remains the local-run default/union).
|
|
# - Cold-seeding budget (per-batch `timeout-minutes: ${{ matrix.batch.timeout || 180 }}`):
|
|
# a COLD run must COMPLETE once to write stryker-incremental.json (Stryker writes it only on
|
|
# a successful finish); a job cancelled at the cap writes nothing, so the next run is cold
|
|
# again — an infinite never-seeds loop. actions/cache is also branch-scoped, so each branch
|
|
# (incl. release) must seed its OWN cache via a run with enough headroom. Measured cold runs
|
|
# (run 27801802713): a/b never finished even isolated; c=180min CANCELLED (4 modules),
|
|
# d=180min CANCELLED (3 combo modules), g=142min, h=132min, e=66, f=45, i=33. So a/b/c/d get
|
|
# 350min (job max 360) and g/h a 240min variance buffer; once seeded, later nightlies only
|
|
# re-test changed mutants and fit well under the default. NOTE: batch c's old "2 modules ~2h"
|
|
# assumption went stale when c grew to 4 modules — keep this budget in sync with the matrix.
|
|
# Full coverage every night in parallel; wall-clock = the slowest batch's cold run until seeded.
|
|
# Runs at stryker concurrency=4 with per-process DATA_DIR isolation
|
|
# (tests/_setup/isolateDataDir.ts) — see _concurrency_comment in stryker.conf.json.
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
batch:
|
|
# Per-batch `timeout` (minutes) tiers the cold-seeding budget by measured cost — see the
|
|
# cold-run measurements in the comment above. Batches without the key default to 180.
|
|
# a/b (large isolated modules) + c/d (4 and 3 modules, observed to exceed 180min cold) get
|
|
# 350 (GitHub-hosted job max is 360); g/h (142/132min cold — within runner-variance distance
|
|
# of the 180 cap) get a 240 buffer. e/f/i (33-66min) stay at the 180 default.
|
|
- name: a
|
|
mutate: "src/sse/services/auth.ts"
|
|
timeout: 350
|
|
- name: b
|
|
mutate: "open-sse/services/accountFallback.ts"
|
|
timeout: 350
|
|
- name: c
|
|
mutate: "src/server/authz/routeGuard.ts,src/shared/utils/circuitBreaker.ts,open-sse/utils/error.ts,open-sse/utils/publicCreds.ts"
|
|
timeout: 350
|
|
- name: d
|
|
mutate: "open-sse/services/combo/comboStructure.ts,open-sse/services/combo/autoStrategy.ts,open-sse/services/combo/validateQuality.ts"
|
|
timeout: 350
|
|
- name: e
|
|
mutate: "open-sse/services/combo/shadowRouting.ts,open-sse/services/combo/targetSorters.ts,open-sse/services/combo/comboPredicates.ts,open-sse/services/combo/rrState.ts,open-sse/services/combo/comboData.ts"
|
|
- name: f
|
|
mutate: "open-sse/services/combo/quotaScoring.ts,open-sse/services/combo/quotaStrategies.ts"
|
|
- name: g
|
|
mutate: "open-sse/handlers/chatCore/comboContextCache.ts,open-sse/handlers/chatCore/idempotency.ts,open-sse/handlers/chatCore/passthroughHelpers.ts,open-sse/handlers/chatCore/responseHeaders.ts,open-sse/handlers/chatCore/sanitization.ts,open-sse/handlers/chatCore/upstreamTimeouts.ts"
|
|
timeout: 240
|
|
- name: h
|
|
mutate: "open-sse/handlers/chatCore/headers.ts,open-sse/handlers/chatCore/logTruncation.ts,open-sse/handlers/chatCore/memoryExtraction.ts,open-sse/handlers/chatCore/nonStreamingSse.ts,open-sse/handlers/chatCore/passthroughToolNames.ts,open-sse/handlers/chatCore/executorHelpers.ts"
|
|
timeout: 240
|
|
- name: i
|
|
mutate: "open-sse/handlers/chatCore/telemetryHelpers.ts,open-sse/handlers/chatCore/memorySkillsInjection.ts,open-sse/handlers/chatCore/semanticCache.ts"
|
|
# Per-batch budget: a/b/c/d override to 350min, g/h to 240min; the rest default to 180min.
|
|
# `matrix.batch.timeout` is null for batches without the key -> `|| 180`.
|
|
timeout-minutes: ${{ matrix.batch.timeout || 180 }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version: "24"
|
|
cache: npm
|
|
- run: npm ci
|
|
- name: Restore Stryker incremental cache
|
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
with:
|
|
path: reports/mutation/stryker-incremental.json
|
|
key: stryker-incremental-${{ matrix.batch.name }}-${{ github.run_id }}
|
|
restore-keys: stryker-incremental-${{ matrix.batch.name }}-
|
|
- name: Run Stryker (advisory)
|
|
id: stryker
|
|
continue-on-error: true
|
|
env:
|
|
BATCH_MUTATE: ${{ matrix.batch.mutate }}
|
|
run: npx stryker run --mutate "$BATCH_MUTATE"
|
|
- name: Upload mutation report
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: mutation-report-${{ matrix.batch.name }}
|
|
path: reports/mutation/
|
|
if-no-files-found: warn
|
|
retention-days: 14
|