给路由 parity 门禁补反向覆盖,模板里的 location 必须被矩阵声明
Project CI / AI game creator shell Rust crates (push) Successful in 1m24s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m58s
Project CI / AI game creator shell Rust lane 2/2 (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled

- check-pingora-route-parity 新增 validateNginxLocationsAreCovered:两份 Nginx 模板里出现的每条 location 都必须被矩阵某条用例的 nginx 片段(location 前缀)声明,否则判红
- 这条针对的正是 2026-09-29 发行网关路由那类漂移:此前只做正向检查(矩阵片段必须存在于模板),模板单方面加路由时门禁一直是绿的
- 矩阵新增 web_root_spa(samplePath=/ → static/web/spa_fallback,片段 location = / + try_files /index.html =404;)并把三个新 id 列入必查清单;Pingora 试点文档补根路径回退与反向覆盖说明
- 验证:check:pingora-route-parity OK(24 路由)、check:nginx-spa-routes OK(12 路由 / 3 模板)、cargo test -p pingora-gateway 39 passed、check:production-ops、prettier / eslint / encoding / doc-index / diff 全绿;变异验证:往生产模板插一条无矩阵声明的 location → 只有反向覆盖报「production 模板的 location 没有被矩阵覆盖」
This commit is contained in:
kdletters
2026-09-29 07:29:41 +08:00
parent 5fee115f10
commit 38eb5b69ed
4 changed files with 42 additions and 2 deletions
+24
View File
@@ -42,6 +42,7 @@ const REQUIRED_ROUTE_IDS = [
'profile_spa_fallback',
'games_spa_fallback',
'games_release_gateway',
'web_root_spa',
'web_spa_case_trailing_slash',
'web_unknown_path_exact',
'creation_unknown_path_exact',
@@ -241,6 +242,28 @@ function validateRustTestUsesMatrix() {
}
}
// 反向覆盖:模板里出现的每条 location 都必须被矩阵某条用例声明过。
// 只做正向检查(矩阵片段存在于模板)会漏掉「Nginx 模板加/改了路由、矩阵与 Pingora 没跟上」——
// 2026-09-29 的发行网关路由就是这样:Nginx 有三份、Pingora 和矩阵都没有,门禁一直是绿的。
function validateNginxLocationsAreCovered() {
for (const environment of ['production', 'development']) {
const source = files[environment];
const locationFragments = matrix.routes
.flatMap((route) => route.nginx?.[environment] ?? [])
.map((fragment) => fragment.trim())
.filter((fragment) => fragment.startsWith('location'));
for (const match of source.matchAll(/^[ \t]*location\b[^\n]*/gmu)) {
const line = match[0].trim().replace(/\s*\{\s*$/u, '');
if (line.startsWith('#')) {
continue;
}
if (!locationFragments.some((fragment) => line.startsWith(fragment))) {
fail(`${environment} 模板的 location 没有被矩阵覆盖: ${line}`);
}
}
}
}
function validateRustMainSpaRoutes() {
const routeBlock = pingoraGatewaySource.match(
/const MAIN_SPA_PATHS: &\[&str\] = &\[([\s\S]*?)\];/u,
@@ -268,6 +291,7 @@ function validateRustMainSpaRoutes() {
validateMatrixShape();
validateRustTestUsesMatrix();
validateNginxLocationsAreCovered();
validateRustMainSpaRoutes();
if (failures.length > 0) {