PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
certify_documentation.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Create a commit-scoped documentation certification after strict validation."""
3
4from __future__ import annotations
5
6import argparse
7import datetime as dt
8import subprocess
9import sys
10from pathlib import Path
11
12
13REPO_ROOT = Path(__file__).resolve().parents[2]
14
15
16def run(command: list[str], label: str) -> None:
17 """!
18 @brief Run one certification gate and stream its output.
19 @param[in] command Executable and arguments for the gate.
20 @param[in] label Human-readable gate label.
21 @return None.
22 """
23
24 print(f"==> {label}", flush=True)
25 completed = subprocess.run(command, cwd=REPO_ROOT, check=False)
26 if completed.returncode != 0:
27 raise RuntimeError(f"{label} failed with exit code {completed.returncode}.")
28
29
30def git_output(*args: str) -> str:
31 """!
32 @brief Return trimmed output from one Git command.
33 @param[in] args Arguments passed after `git`.
34 @return Decoded, trimmed Git stdout.
35 """
36
37 return subprocess.check_output(["git", *args], cwd=REPO_ROOT, text=True).strip()
38
39
41 """!
42 @brief Require that HEAD names a clean, commit-scoped source revision.
43 @return Full SHA of the clean HEAD revision.
44 """
45
46 if git_output("status", "--porcelain"):
47 raise RuntimeError(
48 "Documentation certification requires a clean working tree so its result can be "
49 "claimed for one commit. Commit or stash changes, then rerun."
50 )
51 return git_output("rev-parse", "HEAD")
52
53
55 """!
56 @brief Fail certification when Doxygen reports a warning.
57 @return None.
58 """
59
60 warning_log = REPO_ROOT / "logs" / "doxygen.warnings"
61 warnings = warning_log.read_text(encoding="utf-8").strip() if warning_log.exists() else ""
62 if warnings:
63 raise RuntimeError(
64 "Doxygen emitted warnings; documentation cannot be certified.\n" + warnings
65 )
66
67
68def write_certificate(sha: str, runtime_checked: bool) -> Path:
69 """!
70 @brief Write a reproducible certification record for one validated revision.
71 @param[in] sha Full Git revision validated by the certification gates.
72 @param[in] runtime_checked Whether the PETSc/MPI runtime suite was included.
73 @return Path of the generated certificate.
74 """
75
76 certificate = REPO_ROOT / "logs" / f"documentation-certificate-{sha}.md"
77 timestamp = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat()
78 runtime_gate = "`make check-full`" if runtime_checked else "not run"
79 scope_statement = (
80 "This full certification is authoritative only for the commit named above. "
81 "Any source, configuration, example, or documentation change requires a new certification.\n"
82 if runtime_checked
83 else "This structural certification is authoritative only for the commit named above and "
84 "does not certify PETSc/MPI runtime behavior. A pre-push policy may reuse a recent full "
85 "certificate only when it establishes that runtime-relevant files are unchanged.\n"
86 )
87 certificate.write_text(
88 "# PICurv Documentation Certification\n\n"
89 f"- Certified commit: `{sha}`\n"
90 f"- Certified at (UTC): `{timestamp}`\n"
91 "- Markdown links: passed\n"
92 "- Public-header and implementation comment audit: passed\n"
93 "- PETSc option-ingress manifest audit: passed\n"
94 "- Example/template and configuration regression suite: passed\n"
95 "- Doxygen HTML build: passed with zero warnings\n"
96 f"- PETSc/MPI runtime validation: {runtime_gate}\n\n"
97 + scope_statement,
98 encoding="utf-8",
99 )
100 return certificate
101
102
103def parse_args(argv: list[str]) -> argparse.Namespace:
104 """!
105 @brief Parse documentation-certification command-line arguments.
106 @param[in] argv Arguments excluding the executable name.
107 @return Parsed command-line namespace.
108 """
109
110 parser = argparse.ArgumentParser(
111 description="Validate and certify PICurv documentation for the current clean Git commit."
112 )
113 parser.add_argument(
114 "--runtime",
115 action="store_true",
116 help="also run the PETSc/MPI `make check-full` runtime validation gate",
117 )
118 parser.add_argument(
119 "--no-certificate",
120 action="store_true",
121 help="run the gates without writing logs/documentation-certificate-<sha>.md",
122 )
123 return parser.parse_args(argv)
124
125
126def main(argv: list[str] | None = None) -> int:
127 """!
128 @brief Run the commit-scoped documentation certification workflow.
129 @param[in] argv Optional command-line arguments excluding the executable name.
130 @return Process status code.
131 """
132
133 args = parse_args(sys.argv[1:] if argv is None else argv)
134 try:
136 run([sys.executable, "tests/tooling/check_markdown_links.py"], "Markdown links")
137 run([sys.executable, "tests/tooling/audit_function_docs.py"], "function documentation")
138 run([sys.executable, "tests/tooling/audit_ingress.py"], "option-ingress manifest")
139 run(
140 [sys.executable, "-m", "pytest", "-q", "tests/test_repo_consistency.py", "tests/test_config_regressions.py"],
141 "example/template and configuration validation",
142 )
143 run(["make", "--no-print-directory", "build-docs"], "Doxygen HTML build")
145 if args.runtime:
146 run(["make", "--no-print-directory", "check-full"], "PETSc/MPI runtime validation")
147 if not args.no_certificate:
148 certificate = write_certificate(sha, args.runtime)
149 certification_kind = "full" if args.runtime else "structural"
150 print(f"{certification_kind.capitalize()} documentation certification through commit {sha}: {certificate}")
151 return 0
152 except (RuntimeError, subprocess.CalledProcessError) as error:
153 print(f"Documentation certification failed: {error}", file=sys.stderr)
154 return 1
155
156
157if __name__ == "__main__":
158 raise SystemExit(main())
None run(list[str] command, str label)
Run one certification gate and stream its output.
None ensure_empty_doxygen_warning_log()
Fail certification when Doxygen reports a warning.
str require_clean_revision()
Require that HEAD names a clean, commit-scoped source revision.
argparse.Namespace parse_args(list[str] argv)
Parse documentation-certification command-line arguments.
int main(list[str]|None argv=None)
Run the commit-scoped documentation certification workflow.
Path write_certificate(str sha, bool runtime_checked)
Write a reproducible certification record for one validated revision.
str git_output(*str args)
Return trimmed output from one Git command.