Skip to content

Commit 59e6187

Browse files
fix: replace hardcoded release-audit with real inline audit, add pyright dev dep by reviewer-B
1 parent ab91ee2 commit 59e6187

2 files changed

Lines changed: 96 additions & 24 deletions

File tree

.github/workflows/release-audit.yml

Lines changed: 95 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,105 @@ jobs:
2121
- name: Run release audit
2222
run: |
2323
python3 - <<'PY'
24-
import json, os, pathlib, sys
25-
26-
repo = pathlib.Path.cwd().name
27-
scorecard = {"overall_grade": "A", "angles_passing": 8, "angles_total": 8, "blockers": 0, "angles": []}
28-
angles = [
29-
("README", "A"),
30-
("License", "A"),
31-
("CI/CD", "A"),
32-
("Dependencies", "A"),
33-
("Tests", "A"),
34-
("Versioning", "A"),
35-
("Changelog", "A"),
36-
("Security", "A"),
37-
]
38-
for name, grade in angles:
39-
scorecard["angles"].append({"angle": name, "grade": grade})
40-
41-
out_dir = pathlib.Path("scorecard")
24+
import json, pathlib, sys
25+
26+
repo = pathlib.Path.cwd()
27+
scorecard = {"overall_grade": "A", "angles_passing": 0, "angles_total": 8, "blockers": 0, "angles": []}
28+
29+
def check(name, grade, detail):
30+
scorecard["angles"].append({"angle": name, "grade": grade, "detail": detail})
31+
if grade == "A":
32+
scorecard["angles_passing"] += 1
33+
elif grade == "F":
34+
scorecard["blockers"] += 1
35+
36+
# 1. README
37+
readme = repo / "README.md"
38+
if readme.exists() and len(readme.read_text()) > 200:
39+
check("README", "A", "README.md exists and has content")
40+
else:
41+
check("README", "F", "README.md missing or too short")
42+
43+
# 2. License
44+
lic = repo / "LICENSE"
45+
if lic.exists() and len(lic.read_text()) > 100:
46+
check("License", "A", "LICENSE file present")
47+
else:
48+
check("License", "F", "LICENSE file missing or too short")
49+
50+
# 3. CI/CD
51+
wf_dir = repo / ".github" / "workflows"
52+
wf_files = list(wf_dir.glob("*.yml")) + list(wf_dir.glob("*.yaml"))
53+
if len(wf_files) >= 1:
54+
check("CI/CD", "A", f"{len(wf_files)} workflow(s) found")
55+
else:
56+
check("CI/CD", "F", "No CI/CD workflows found")
57+
58+
# 4. Dependencies
59+
pyproj = repo / "pyproject.toml"
60+
if pyproj.exists():
61+
check("Dependencies", "A", "pyproject.toml found")
62+
else:
63+
check("Dependencies", "F", "pyproject.toml missing")
64+
65+
# 5. Tests
66+
tests = repo / "tests"
67+
test_files = list(tests.glob("test_*.py")) + list(tests.glob("*_test.py"))
68+
if len(test_files) >= 1:
69+
check("Tests", "A", f"{len(test_files)} test file(s) found")
70+
else:
71+
check("Tests", "F", "No test files found")
72+
73+
# 6. Versioning
74+
if pyproj.exists():
75+
import tomllib
76+
data = tomllib.loads(pyproj.read_text())
77+
ver = data.get("project", {}).get("version", "")
78+
if ver:
79+
check("Versioning", "A", f"Version {ver} set in pyproject.toml")
80+
else:
81+
check("Versioning", "F", "No version in pyproject.toml")
82+
else:
83+
check("Versioning", "F", "Cannot check version — pyproject.toml missing")
84+
85+
# 7. Changelog
86+
changelog = repo / "CHANGELOG.md"
87+
if changelog.exists() and len(changelog.read_text()) > 50:
88+
check("Changelog", "A", "CHANGELOG.md present")
89+
else:
90+
check("Changelog", "C", "CHANGELOG.md missing or too short")
91+
92+
# 8. Security
93+
sec = repo / "SECURITY.md"
94+
if sec.exists() and len(sec.read_text()) > 50:
95+
check("Security", "A", "SECURITY.md present")
96+
else:
97+
check("Security", "C", "SECURITY.md missing or too short")
98+
99+
# Compute overall grade
100+
if scorecard["blockers"] > 0:
101+
scorecard["overall_grade"] = "F"
102+
elif scorecard["angles_passing"] == scorecard["angles_total"]:
103+
scorecard["overall_grade"] = "A"
104+
elif scorecard["angles_passing"] >= scorecard["angles_total"] - 2:
105+
scorecard["overall_grade"] = "B"
106+
else:
107+
scorecard["overall_grade"] = "C"
108+
109+
out_dir = repo / "scorecard"
42110
out_dir.mkdir(exist_ok=True)
43-
(out_dir / f"{repo}.json").write_text(json.dumps(scorecard, indent=2))
111+
(out_dir / f"{repo.name}.json").write_text(json.dumps(scorecard, indent=2))
44112
45113
print("## Release Audit (8 angles)")
46114
print()
47-
print(f"**Overall grade: {scorecard['overall_grade']}** ({scorecard['angles_passing']}/{scorecard['angles_total']} angles passing)")
115+
print(f"**Overall grade: {scorecard['overall_grade']}** ({scorecard['angles_passing']}/{scorecard['angles_total']} angles passing, {scorecard['blockers']} blocker(s))")
48116
print()
49-
print("| Angle | Grade |")
50-
print("|-------|-------|")
117+
print("| Angle | Grade | Detail |")
118+
print("|-------|-------|--------|")
51119
for a in scorecard["angles"]:
52-
print(f"| {a['angle']} | {a['grade']} |")
120+
print(f"| {a['angle']} | {a['grade']} | {a['detail']} |")
121+
122+
if scorecard["blockers"] > 0:
123+
print(f"\n::error::{scorecard['blockers']} release-blocker angle(s) — see audit output above")
124+
sys.exit(1)
53125
PY

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ all = [
5050
"click-to-mcp>=0.4.0",
5151
"deadcode>=0.1.1",
5252
]
53-
dev = ["pytest>=7.0.0"]
53+
dev = ["pytest>=7.0.0", "pyright>=1.1.300"]
5454

5555
[project.urls]
5656
Homepage = "https://github.com/Coding-Dev-Tools/devforge"

0 commit comments

Comments
 (0)