mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 05:29:45 +00:00
51a30f71d3
Build and Test deliberately skips the smoke suite for Markdown-only changes, leaving Public docs able to accept unsafe but correctly mirrored guidance. Run the existing backup, passive diagnostic and copied-reader suites in the lightweight docs check, and retain strict failure propagation and source triggers without installing application dependencies. Contract-Neutral: Wire existing safety recipe checks into docs-only CI without changing product, workflow trust or documentation contracts. Change-source: pulse-maintainer
136 lines
5.9 KiB
Python
136 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Docs-only CI must exercise safety guidance, not just its Markdown shape.
|
|
|
|
Read the canonical block-YAML surface (also checked by workflow trust), then
|
|
execute its actual smoke command with disposable test adapters. No provider,
|
|
host service, backup or guest-agent operation is used.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import textwrap
|
|
import unittest
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
WORKFLOW = ROOT / ".github/workflows/public-docs.yml"
|
|
SAFETY_STEP = "Exercise backup safety and diagnostic recipes"
|
|
TESTS = (
|
|
"test_pve_backup_troubleshooting_docs.py",
|
|
"test_vm_disk_diagnostics.py",
|
|
"test_memory_troubleshooting_docs.py",
|
|
"test_performance_troubleshooting_docs.py",
|
|
"test_troubleshooting_logs.py",
|
|
)
|
|
|
|
|
|
def step_body(source: str, name: str) -> str:
|
|
marker = f" - name: {name}\n"
|
|
if source.count(marker) != 1:
|
|
raise AssertionError(f"expected exactly one {name} step")
|
|
return source.split(marker, 1)[1].split("\n - name:", 1)[0]
|
|
|
|
|
|
def safety_command(source: str) -> str:
|
|
body = step_body(source, SAFETY_STEP)
|
|
marker = " run: |\n"
|
|
if body.count(marker) != 1:
|
|
raise AssertionError("expected one literal safety command")
|
|
return textwrap.dedent(body.split(marker, 1)[1]).strip()
|
|
|
|
|
|
class PublicDocsWorkflowTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.source = WORKFLOW.read_text(encoding="utf-8")
|
|
|
|
def test_both_events_cover_docs_checks_runner_and_helper(self):
|
|
triggers = self.source.split("\non:\n", 1)[1].split("\npermissions:", 1)[0]
|
|
required = {
|
|
"*.md", "docs/**", "frontend-modern/public/docs/**",
|
|
"scripts/check_public_docs.py", "scripts/check_docs_mirror.py",
|
|
"scripts/readme_entrypoints_test.py", "scripts/tests/run.sh",
|
|
"scripts/tests/test_public_docs_workflow.py", "scripts/test-vm-disk.sh",
|
|
".github/workflows/public-docs.yml",
|
|
*(f"scripts/tests/{name}" for name in TESTS),
|
|
}
|
|
for event in ("pull_request", "push"):
|
|
with self.subTest(event=event):
|
|
block = triggers.split(f" {event}:\n", 1)[1]
|
|
block = re.split(r"\n [a-z_]+:\n", block, maxsplit=1)[0]
|
|
paths = re.findall(r'^ - "([^"]+)"$', block, re.MULTILINE)
|
|
self.assertTrue(required.issubset(paths), required.difference(paths))
|
|
self.assertEqual(len(paths), len(set(paths)))
|
|
self.assertIn(" push:\n branches:\n - main\n", triggers)
|
|
|
|
def test_exact_existing_suites_run_without_dependency_setup(self):
|
|
command = safety_command(self.source).replace("\\\n", " ")
|
|
self.assertEqual(shlex.split(command), ["scripts/tests/run.sh", *TESTS])
|
|
for name in TESTS:
|
|
self.assertTrue((ROOT / "scripts/tests" / name).is_file())
|
|
self.assertNotIn("actions/setup-", self.source)
|
|
self.assertNotRegex(self.source, r"\b(?:npm|pip|go) (?:ci|install|build|test)\b")
|
|
|
|
def test_existing_document_admissions_are_preserved(self):
|
|
for name, command in (
|
|
("Validate public documentation", "python3 scripts/check_public_docs.py"),
|
|
("Check getting-started safety and current plans", "python3 scripts/readme_entrypoints_test.py"),
|
|
("Check shipped docs mirror sync", "python3 scripts/check_docs_mirror.py"),
|
|
("Check documentation safety workflow contract", "python3 scripts/tests/test_public_docs_workflow.py"),
|
|
):
|
|
with self.subTest(step=name):
|
|
self.assertIn(f" run: {command}\n", step_body(self.source, name))
|
|
|
|
def test_safety_checks_cannot_be_conditionally_skipped_or_softened(self):
|
|
self.assertNotRegex(self.source, r"(?m)^\s*(?:if|continue-on-error):")
|
|
self.assertIn("permissions:\n contents: read\n", self.source)
|
|
self.assertIn(" persist-credentials: false\n", self.source)
|
|
self.assertIn(" timeout-minutes: 10\n", self.source)
|
|
|
|
def run_adapters(self, failing: str = ""):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
root = Path(temporary)
|
|
tests = root / "scripts/tests"
|
|
tests.mkdir(parents=True)
|
|
shutil.copyfile(ROOT / "scripts/tests/run.sh", tests / "run.sh")
|
|
(tests / "run.sh").chmod(0o700)
|
|
for name in TESTS:
|
|
(tests / name).write_text(
|
|
"import os\nfrom pathlib import Path\n"
|
|
f"with Path(os.environ['CALLS']).open('a') as log: log.write({name!r} + '\\n')\n"
|
|
f"raise SystemExit({1 if name == failing else 0})\n",
|
|
encoding="utf-8",
|
|
)
|
|
calls = root / "calls"
|
|
result = subprocess.run(
|
|
["bash", "-e", "-o", "pipefail", "-c", safety_command(self.source)],
|
|
cwd=root, env=dict(os.environ, CALLS=str(calls)),
|
|
text=True, capture_output=True, timeout=15,
|
|
)
|
|
return result, calls.read_text().splitlines()
|
|
|
|
def test_actual_workflow_command_runs_every_suite(self):
|
|
result, calls = self.run_adapters()
|
|
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
|
self.assertEqual(calls, list(TESTS))
|
|
self.assertIn("Summary: 5/5 passed", result.stdout)
|
|
|
|
def test_each_failed_suite_is_a_failed_workflow_command(self):
|
|
for failing in TESTS:
|
|
with self.subTest(failing=failing):
|
|
result, calls = self.run_adapters(failing)
|
|
self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)
|
|
self.assertEqual(calls, list(TESTS))
|
|
self.assertIn("Summary: 4/5 passed", result.stdout)
|
|
self.assertIn("Failures: 1", result.stdout)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|