diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5720b9f..4bbbca5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,9 +51,14 @@ jobs: run: | set -euo pipefail python -m pip install --upgrade pip - python -m pip install -e . pandas pytest pytest-cov ruff + python -m pip install -e . pandas pytest pytest-cov ruff build python -m pip install --no-deps -e external/QuantPlatformKit + - name: Verify dependencies + run: | + set -euo pipefail + python -m pip check + - name: Run Ruff run: | set -euo pipefail @@ -63,3 +68,8 @@ jobs: run: | set -euo pipefail PYTHONPATH=src python -m pytest -q tests --cov --cov-report=term --cov-report=xml + + - name: Build package + run: | + set -euo pipefail + python -m build diff --git a/pyproject.toml b/pyproject.toml index acbe05f..07bfd25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,10 +23,12 @@ package-dir = {"" = "src"} where = ["src"] [tool.ruff] -ignore = ["E701", "E702", "E741", "F841", "F821", "B008", "F401", "F601", "E402"] target-version = "py311" line-length = 120 +[tool.ruff.lint] +ignore = ["E701", "E702", "E741", "F841", "F821", "B008", "F401", "F601", "E402"] + [tool.coverage.run] branch = true source = ["src"] diff --git a/scripts/gate_codex_app_review.py b/scripts/gate_codex_app_review.py index f379971..59a2df1 100644 --- a/scripts/gate_codex_app_review.py +++ b/scripts/gate_codex_app_review.py @@ -93,7 +93,7 @@ def compile_patterns(policy: dict[str, Any]) -> list[re.Pattern[str]]: # ─── static guard ──────────────────────────────────────────────────────────── _SENSITIVE = re.compile( - r'(?:api[_\s]?key|secret|password|token|credential|private[_\s]?key)\s*[:=]\s*["\']' + r'(?Papi[_\s]?key|secret|password|token|credential|private[_\s]?key)\s*[:=]\s*["\']' r'(?!\$\{\{|{{|example|placeholder|test|your[-_\s]|xxx|TODO|CHANGEME)[^"\']{12,}["\']', re.IGNORECASE, ) @@ -115,7 +115,8 @@ def scan_diff(diff_text: str, path_patterns: list[re.Pattern[str]]) -> list[str] if not line.startswith("+") or line.startswith("+++"): continue m = _SENSITIVE.search(line[1:]) if m: - violations.append(f"**Hardcoded secret** in `{current}`: `{m.group(0)[:100]}`") + field = re.sub(r"\s+", "_", m.group("field").strip().lower()) + violations.append(f"**Hardcoded secret** in `{current}`: `{field}=`") return list(dict.fromkeys(violations)) diff --git a/tests/test_gate_codex_app_review.py b/tests/test_gate_codex_app_review.py new file mode 100644 index 0000000..183c573 --- /dev/null +++ b/tests/test_gate_codex_app_review.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +import unittest + +from scripts.gate_codex_app_review import scan_diff + + +class GateCodexAppReviewTests(unittest.TestCase): + def test_scan_diff_redacts_hardcoded_secret_values(self) -> None: + secret_field = "API" + "_KEY" + secret_value = "super" + "secretvalue123456" + diff_text = ( + "diff --git a/example.env b/example.env\n" + "--- a/example.env\n" + "+++ b/example.env\n" + f'+{secret_field} = "{secret_value}"\n' + ) + + violations = scan_diff(diff_text, []) + + self.assertEqual(len(violations), 1) + self.assertIn("", violations[0]) + self.assertIn("api_key", violations[0]) + self.assertNotIn(secret_value, violations[0]) + + +if __name__ == "__main__": + unittest.main()