jekyll-theme-zer0 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/_data/ai.yml +10 -0
- data/_data/backlog.yml +65 -37
- data/_data/navigation/docs.yml +4 -0
- data/_data/theme_backgrounds.yml +24 -0
- data/_includes/components/component-showcase.html +77 -16
- data/_includes/components/search-modal.html +28 -4
- data/_includes/core/color-mode-init.html +35 -0
- data/_includes/core/head.html +9 -0
- data/_includes/core/tokens-inline.html +5 -0
- data/_layouts/author.html +22 -1
- data/_layouts/root.html +15 -1
- data/scripts/bin/validate +1 -0
- data/scripts/ci/classify_changes.py +129 -0
- data/scripts/issues/dispatch.py +478 -0
- data/scripts/issues/test_verify_close.py +118 -0
- data/scripts/issues/triage.py +1046 -0
- data/scripts/issues/verify_close.py +179 -0
- metadata +9 -2
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
test_verify_close.py — dependency-free unit tests for the verify-and-close gate.
|
|
4
|
+
|
|
5
|
+
Run: python3 scripts/issues/test_verify_close.py (no pytest needed; exits non-zero on failure)
|
|
6
|
+
|
|
7
|
+
Covers the policy filter (which verdicts may close) and the CI gate's fail-CLOSED
|
|
8
|
+
behaviour. The CI gate is exercised with a stubbed `_gh_api` so the tests never
|
|
9
|
+
touch the network. These are the safety-critical paths: a bug here could close a
|
|
10
|
+
real, unresolved issue.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
18
|
+
import verify_close as vc # noqa: E402
|
|
19
|
+
|
|
20
|
+
PASSED = 0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def check(name: str, cond: bool) -> None:
|
|
24
|
+
global PASSED
|
|
25
|
+
if not cond:
|
|
26
|
+
print(f"FAIL: {name}")
|
|
27
|
+
raise SystemExit(1)
|
|
28
|
+
PASSED += 1
|
|
29
|
+
print(f"ok: {name}")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
PLAN = {
|
|
33
|
+
"repo": "bamr87/zer0-mistakes",
|
|
34
|
+
"issues": [
|
|
35
|
+
{"number": 241, "verify_candidate": True},
|
|
36
|
+
{"number": 242, "verify_candidate": True},
|
|
37
|
+
{"number": 999, "verify_candidate": False}, # protected/bot — never closable
|
|
38
|
+
],
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_policy_filter() -> None:
|
|
43
|
+
verify = {"verdicts": [
|
|
44
|
+
{"number": 241, "resolved": True, "confidence": "high", "evidence": "_config.yml:685"},
|
|
45
|
+
{"number": 999, "resolved": True, "confidence": "high", "evidence": "x"}, # not a candidate
|
|
46
|
+
{"number": 242, "resolved": True, "confidence": "low", "evidence": "weak"}, # low confidence
|
|
47
|
+
{"number": 242, "resolved": False, "confidence": "high", "evidence": "open"}, # not resolved
|
|
48
|
+
{"number": 241, "resolved": True, "confidence": "high", "evidence": ""}, # no evidence (dupe)
|
|
49
|
+
]}
|
|
50
|
+
picks = {p["number"] for p in vc.closable(PLAN, verify)}
|
|
51
|
+
check("only the resolved+high+evidenced candidate is closable", picks == {241})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_non_candidate_never_closable() -> None:
|
|
55
|
+
verify = {"verdicts": [
|
|
56
|
+
{"number": 999, "resolved": True, "confidence": "high", "evidence": "real-looking"},
|
|
57
|
+
]}
|
|
58
|
+
check("a non-verify_candidate is dropped (defense in depth)", vc.closable(PLAN, verify) == [])
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _stub_api(mapping):
|
|
62
|
+
"""Return a fake _gh_api that yields mapping[path] (substring match) or None."""
|
|
63
|
+
def fake(path: str):
|
|
64
|
+
for key, val in mapping.items():
|
|
65
|
+
if key in path:
|
|
66
|
+
return val
|
|
67
|
+
return None
|
|
68
|
+
return fake
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_ci_gate_green() -> None:
|
|
72
|
+
orig = vc._gh_api
|
|
73
|
+
vc._gh_api = _stub_api({
|
|
74
|
+
"/status": {"state": "success", "total_count": 2},
|
|
75
|
+
"/check-runs": {"check_runs": [
|
|
76
|
+
{"name": "build", "status": "completed", "conclusion": "success"},
|
|
77
|
+
{"name": "lint", "status": "completed", "conclusion": "skipped"},
|
|
78
|
+
]},
|
|
79
|
+
})
|
|
80
|
+
try:
|
|
81
|
+
green, _ = vc.ci_gate("o/r")
|
|
82
|
+
check("all-green status + check-runs passes the gate", green is True)
|
|
83
|
+
finally:
|
|
84
|
+
vc._gh_api = orig
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_ci_gate_fails_closed() -> None:
|
|
88
|
+
orig = vc._gh_api
|
|
89
|
+
cases = {
|
|
90
|
+
"failing check-run": {
|
|
91
|
+
"/status": {"state": "success", "total_count": 1},
|
|
92
|
+
"/check-runs": {"check_runs": [{"name": "build", "status": "completed", "conclusion": "failure"}]},
|
|
93
|
+
},
|
|
94
|
+
"pending check-run": {
|
|
95
|
+
"/status": {"state": "success", "total_count": 1},
|
|
96
|
+
"/check-runs": {"check_runs": [{"name": "build", "status": "in_progress", "conclusion": None}]},
|
|
97
|
+
},
|
|
98
|
+
"failing commit status": {
|
|
99
|
+
"/status": {"state": "failure", "total_count": 1},
|
|
100
|
+
"/check-runs": {"check_runs": []},
|
|
101
|
+
},
|
|
102
|
+
"api error (None)": {}, # _gh_api returns None for everything → fail closed
|
|
103
|
+
}
|
|
104
|
+
try:
|
|
105
|
+
for label, mapping in cases.items():
|
|
106
|
+
vc._gh_api = _stub_api(mapping)
|
|
107
|
+
green, why = vc.ci_gate("o/r")
|
|
108
|
+
check(f"gate fails CLOSED on {label}", green is False and bool(why))
|
|
109
|
+
finally:
|
|
110
|
+
vc._gh_api = orig
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
test_policy_filter()
|
|
115
|
+
test_non_candidate_never_closable()
|
|
116
|
+
test_ci_gate_green()
|
|
117
|
+
test_ci_gate_fails_closed()
|
|
118
|
+
print(f"\nAll {PASSED} verify_close assertions passed.")
|