From 0f4e589cf1fd73457b213a369c17c22a01adc621 Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sun, 12 Jul 2026 22:51:13 +0900 Subject: [PATCH] fix(ci): guard wbs verdict coverage --- .gitea/workflows/ci.yml | 2 +- tools/validate_gitea_ci_workflow_lint_v1.py | 34 +++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 14fc1b43..5b5d4a60 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -146,7 +146,7 @@ jobs: # 가능한 것만 나열한다. 실제 KIS API/라이브 앱이 전제인 나머지 DONE 작업은 # spec/60의 execution.mode: not_ci_reproducible 로 별도 표시되어 # validate_quant_engine_wbs_v1.py 가 verdict 부재를 FAIL로 취급하지 않는다. - for task in QE-M0-01 QE-M0-02 QE-M0-03 QE-M0-04 QE-M0-05 QE-M0-06 QE-M0-07 QE-M1-05 QE-M1-06 QE-M2-01 QE-M2-06; do + for task in QE-M0-01 QE-M0-02 QE-M0-03 QE-M0-04 QE-M0-05 QE-M0-06 QE-M0-07 QE-M1-05 QE-M1-06 QE-M2-01 QE-M2-03 QE-M2-06 QE-M3-01 QE-M3-02 QE-M3-03 QE-M3-04 QE-M3-05; do python3 tools/verify_wbs_task_v1.py --task "$task" done diff --git a/tools/validate_gitea_ci_workflow_lint_v1.py b/tools/validate_gitea_ci_workflow_lint_v1.py index ead75bac..11d0fa50 100644 --- a/tools/validate_gitea_ci_workflow_lint_v1.py +++ b/tools/validate_gitea_ci_workflow_lint_v1.py @@ -2,6 +2,7 @@ from __future__ import annotations import argparse import json +import re from pathlib import Path import yaml @@ -35,17 +36,46 @@ def main() -> int: core = jobs.get("validate-core") or {} services = core.get("services") or {} postgres = services.get("postgres") or {} + ci_text = workflow_path.read_text(encoding="utf-8") ports = postgres.get("ports") or [] if any(str(port).strip() == "5432:5432" for port in ports): errors.append("validate-core.services.postgres.ports contains fixed host mapping 5432:5432") - if "PGHOST: postgres" not in workflow_path.read_text(encoding="utf-8"): + if "PGHOST: postgres" not in ci_text: errors.append("workflow does not pin PGHOST=postgres for CI database steps") - if "QE_WBS_PG_DSN=host=postgres" not in workflow_path.read_text(encoding="utf-8"): + if "QE_WBS_PG_DSN=host=postgres" not in ci_text: errors.append("workflow does not publish QE_WBS_PG_DSN with service hostname") + spec_path = ROOT / "spec" / "60_quant_engine_wbs.yaml" + spec = _load_yaml(spec_path) + done_tasks: list[str] = [] + for task_id, task in (spec.get("tasks") or {}).items(): + if (task or {}).get("status") != "DONE": + continue + mode = ((task or {}).get("execution") or {}).get("mode") + if mode == "not_ci_reproducible": + continue + done_tasks.append(task_id) + done_tasks.sort() + + match = re.search( + r"for task in (?P.+?); do\s+python3 tools/verify_wbs_task_v1\.py --task \"?\$?task\"?\s+done", + ci_text, + re.S, + ) + if not match: + errors.append("workflow missing Generate DONE WBS Verdicts task list") + else: + declared = re.findall(r"QE-[A-Z0-9-]+", match.group("tasks")) + missing = [task for task in done_tasks if task not in declared] + extra = [task for task in declared if task not in done_tasks] + if missing: + errors.append("workflow omits DONE verdict tasks: " + ", ".join(missing)) + if extra: + errors.append("workflow includes non-DONE verdict tasks: " + ", ".join(extra)) + result = { "formula_id": "GITEA_CI_WORKFLOW_LINT_V1", "gate": "PASS" if not errors else "FAIL",