r2 复审(reviewer-updatee2e-r2,p2-4items;被抓出一个真洞,mission 翻回 active)逐条落地。 P2-1(本轮核心,真洞)allowlist 的归属原来按「最近一行 `- name:`」切块,于是任何不写成 `- name: <x>` 的步骤都继承上一块的名字;被放行的 `update-e2e` 恰好是 ci.yml 里最后一个 `- name:`,所以追加到文件末尾的一切都落在它的块里。复审三条真实注入(无名 `- run:`、无名步骤的 整个 job、flow 风格步骤)当时全绿。现在: - `split_items()` 按 YAML **列表项**切块(每个 `- ` 起一项;比当前项深的行归当前项;同级或更浅的 非列表行**结束**当前项)。项名 = 该项内**同级**的 `name:` 键(键序无关;`run: |` 块里的 `name: dummy` 不算;`run: echo "name: x"` 也不算)。 - **默认拒绝**:落不到列表项上的行(`jobs:` 之前的孤儿行、job 级 `run:` 这类项外键)带 feature 即红; 没有 `name:` 的项带 feature 即红。不再有「继承上一块」这回事。 - 三条复审注入 + 本轮新增三条(`jobs:` 之前的孤儿行、`run: |` 里夹带并伪造 name、shell 变量拼接) 都进了自测向量;在**真仓库文件**上重跑也是全红。 P2-2(同族误杀): - 键序无关:允许的那一步把 `run:` 写在 `name:` 之前仍绿(旧实现会报到上一块的名字上)。 - `cargo hack check --all-targets` 不再被误判成 `--all`(正则收紧到 `--all(?![-\w])`)。 - Cargo 的 `update-test-source = [ … ]` **跨行声明**不再被误判成「写进了别的 feature 列表」 (`scan_manifest` 增加 `in_declaration` 状态)。 P2-3 `Fixture::run` 的第二条断言比错对象:原来比夹具字段 `self.dest`,手写 `fx.run(&["apply","--dest","<测试二进制>","--json"])` 两条都过。现在从 `args` 里解析真实 `--dest` 值(含 `--dest=` 形式)再 canonicalize 比较;夹具字段那份作为额外一道保留。 P2-4 `release-guard.yml` 的步骤级注释还停在 r1 的扫描面:改成「含复合 action / packaging 递归 / Makefile 等 + 归属按列表项判 + 唯一允许 ci.yml 的 update-e2e 一步」。 自测数据搬到 `packaging/tests/guard_vectors.json`(基线 8 个文件 + 26 条向量:21 红 / 6 绿), 脚本本身从 379 行降到 373 行(守门仍 ≤400);README §14 补上归属规则与「抓不住」清单。 验证(本机,全部 exit 0): - 守门正式扫描绿;`--self-test` 21 条注入全红 + 6 条基线/放行绿;向量文件缺失时 exit 1(不静默)。 - **真仓注入**(在真 ci.yml / release-build.yml / cli/Cargo.toml 上改完即还原):复审三条(无名步骤 / 无名 job / flow 步骤)全红;本轮新增三条(孤儿行 / `run: |` 夹带 / shell 拼接)全红; 三条合法写法(键序、`--all-targets`、跨行声明)全绿;还原后基线绿。 - E2E:debug 6 绿、release 6 绿(`running 3 tests` ×2,0.26s / 0.23s,非 0 measured)。 - `cargo clippy -p unlucky-cli --all-targets --features update-test-source -- -D warnings` 干净; `cargo fmt --all -- --check` 干净;全仓 400 行扫描无超限(守门 373 / 向量 194 / ci.yml 317)。 约束遵守:未 push;`PUBLISH_SLOTS` 只列 `windows-x64`(未动);release 侧仍无该 feature;跨卷 bug 未碰。 ⚠ 仍未验:CI 里 E2E 真跑起来本机验不了(只证明 workflow 写对 + 守门放行,首跑要等推送后看 Actions)。
195 lines
8.4 KiB
JSON
195 lines
8.4 KiB
JSON
{
|
||
"baseline": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_test --test update_e2e_tamper_test\n",
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - run: cargo build --release\n",
|
||
".github/workflows/release-publish.yml": "jobs:\n update-e2e:\n steps:\n - run: echo publish\n",
|
||
"packaging/make_artifacts.py": "def build():\n return 'cargo build --release'\n",
|
||
"packaging/tests/build.sh": "#!/bin/sh\ncargo build --release\n",
|
||
"Makefile": "build:\n\tcargo build --release\n",
|
||
"Cargo.toml": "[workspace]\nmembers = []\n",
|
||
"crates/core/Cargo.toml": "[features]\nupdate-test-source = []\n# 注释里提到它不算违规\n"
|
||
},
|
||
"vectors": [
|
||
{
|
||
"label": "allowlist:ci.yml 的 update-e2e 一步",
|
||
"expect": "green",
|
||
"files": {}
|
||
},
|
||
{
|
||
"label": "allowlist:同一步放进 release-build.yml",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_test --test update_e2e_tamper_test\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "allowlist:步骤名改成 update-e2e-r2",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e-r2\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_test --test update_e2e_tamper_test\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "allowlist:少了 --test update_e2e_test",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_tamper_test\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "allowlist:发布工作流里另起一步",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/release-publish.yml": "jobs:\n update-e2e:\n steps:\n - name: leak\n - run: cargo build --release --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "allowlist:ci.yml 里另一个具名步骤",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_test --test update_e2e_tamper_test\n - name: another\n - run: cargo build --release --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-1 ①:末尾追加无名步骤",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_test --test update_e2e_tamper_test\n - run: cargo build --release --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-1 ②:末尾追加无名步骤的整个 job",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_test --test update_e2e_tamper_test\n release-from-ci:\n steps:\n - run: cargo build --release --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-1 ③:flow 风格步骤",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - name: update-e2e\n if: runner.os == 'Windows'\n run: |\n cargo test --release -p unlucky-cli --features update-test-source \\\n --test update_e2e_test --test update_e2e_tamper_test\n - {name: release-build, run: \"cargo build --features update-test-source\"}\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-1 ④:步骤写在 jobs: 之前(孤儿行)",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": " - run: cargo build --release --features update-test-source\njobs:\n update-e2e:\n steps:\n - run: echo hi\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-1 ⑤:`run: |` 块里伪造 `name: update-e2e`",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - run: |\n echo 'name: update-e2e'\n cargo build --release --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2 ①:`#` 在引号内、真命令在后面",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - run: echo \"#\"; cargo build --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2 ②:shell 变量拼接(字面量仍在)",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - run: FEAT=\"update-test-source\"; cargo build --features \"$FEAT\"\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "Cargo ①:default 把 feature 带上",
|
||
"expect": "red",
|
||
"files": {
|
||
"crates/core/Cargo.toml": "[features]\nupdate-test-source = []\n# 注释里提到它不算违规\ndefault = [\"update-test-source\"]\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "Cargo ②:别的 feature 依赖它",
|
||
"expect": "red",
|
||
"files": {
|
||
"crates/core/Cargo.toml": "[features]\nupdate-test-source = []\n# 注释里提到它不算违规\nrelease = [\"update-test-source\"]\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "误杀 ①:注释里提到该 feature",
|
||
"expect": "green",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n # 这里不许加 update-test-source\n - run: cargo build --release\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "误杀 ②:允许的那一步把 `run:` 写在 `name:` 之前(键序无关)",
|
||
"expect": "green",
|
||
"files": {
|
||
".github/workflows/ci.yml": "jobs:\n update-e2e:\n steps:\n - run: cargo test --release --features update-test-source --test update_e2e_test\n name: update-e2e\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "误杀 ③:`cargo hack check --all-targets`(不打开任何 feature)",
|
||
"expect": "green",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - run: cargo hack check --all-targets\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "误杀 ④:Cargo 多行 feature 声明",
|
||
"expect": "green",
|
||
"files": {
|
||
"crates/core/Cargo.toml": "[features]\nupdate-test-source = [\n \"unlucky-core/update-test-source\",\n \"unlucky-cli/update-test-source\",\n]\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2:cargo hack --feature-powerset",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - run: cargo hack --feature-powerset build\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2:cargo hack --each-feature",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - run: cargo hack --each-feature build\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2:cargo hack --all",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/release-build.yml": "jobs:\n update-e2e:\n steps:\n - run: cargo hack --all build\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2 扫描面:packaging/tests/build.sh",
|
||
"expect": "red",
|
||
"files": {
|
||
"packaging/tests/build.sh": "#!/bin/sh\ncargo build --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2 扫描面:.github/actions/rebuild/action.yml",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/actions/rebuild/action.yml": "runs:\n using: composite\n steps:\n - run: cargo build --features update-test-source\n shell: bash\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2 扫描面:.github/workflows/nested/extra.yml",
|
||
"expect": "red",
|
||
"files": {
|
||
".github/workflows/nested/extra.yml": "jobs:\n update-e2e:\n steps:\n - run: cargo build --release --features update-test-source\n"
|
||
}
|
||
},
|
||
{
|
||
"label": "P2-2 扫描面:Makefile",
|
||
"expect": "red",
|
||
"files": {
|
||
"Makefile": "build:\n\tcargo build --release --features update-test-source\n"
|
||
}
|
||
}
|
||
]
|
||
}
|