1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
import json
import sys
from pathlib import Path
import pytest
from scripts.docs_gates import gates
@pytest.fixture()
def artifact(tmp_path: Path) -> Path:
root = tmp_path / "en" / "rolling"
root.mkdir(parents=True)
for i in range(50):
(root / f"p{i}.html").write_text(
f'<html><head><link rel="canonical" href="https://docs.vyos.io/en/rolling/p{i}.html"/></head><body>x</body></html>'
)
(root / "index.html").write_text(
'<html><head><link rel="canonical" href="https://docs.vyos.io/en/rolling/index.html"/></head></html>'
)
(root / "vyos-documentation.pdf").write_bytes(b"%PDF-1.4 fake")
(root / "pagefind").mkdir()
(root / "pagefind" / "pagefind.js").write_text("// index")
(root / "installation").mkdir()
(root / "installation" / "index.html").write_text(
'<html><head><link rel="canonical" href="https://docs.vyos.io/en/rolling/installation/index.html"/></head></html>'
)
return tmp_path
def versions_arg(tmp_path: Path) -> Path:
"""Hermetic stand-in for workers/versions.json — writes a fixture-local
manifest with the minimal schema the gates consume (mirrors the real
file's shape for the rolling entry) so tests never depend on, or break
from, edits to the repo file."""
p = tmp_path / "versions.json"
p.write_text(json.dumps({
"schema_version": 2,
"default_lang": "en",
"default_version": "rolling",
"languages": [{"code": "en", "label": "English"}],
"versions": [
{"slug": "rolling", "label": "Rolling (development)", "status": "dev",
"binding": "DOCS_ROLLING", "aliases": ["latest"],
"pdf": "/en/rolling/vyos-documentation.pdf"},
],
}))
return p
@pytest.fixture()
def versions(tmp_path: Path) -> Path:
return versions_arg(tmp_path)
def test_pass_on_good_artifact(artifact: Path, versions: Path):
rc = gates.run(artifact=artifact, slug="rolling", versions=versions,
previous_meta=None, critical=["index.html", "installation/index.html"])
assert rc == 0
def test_fail_on_missing_critical_page(artifact: Path, versions: Path):
(artifact / "en/rolling/installation/index.html").unlink()
rc = gates.run(artifact=artifact, slug="rolling", versions=versions,
previous_meta=None, critical=["index.html", "installation/index.html"])
assert rc == 1
def test_fail_on_count_collapse(artifact: Path, versions: Path, tmp_path: Path):
meta = tmp_path / "meta.json"
meta.write_text(json.dumps({"sha": "old", "page_count": 5000})) # previous build 100x bigger
rc = gates.run(artifact=artifact, slug="rolling", versions=versions,
previous_meta=meta, critical=["index.html"])
assert rc == 1
def test_fail_on_alias_canonical(artifact: Path, versions: Path):
(artifact / "en/rolling/bad.html").write_text(
'<html><head><link rel="canonical" href="https://docs.vyos.io/en/latest/bad.html"/></head></html>'
)
rc = gates.run(artifact=artifact, slug="rolling", versions=versions,
previous_meta=None, critical=["index.html"])
assert rc == 1
def test_fail_on_missing_canonical(artifact: Path, versions: Path):
(artifact / "en/rolling/nocanon.html").write_text(
'<html><head></head><body>no canonical link at all</body></html>'
)
rc = gates.run(artifact=artifact, slug="rolling", versions=versions,
previous_meta=None, critical=["index.html"])
assert rc == 1
def test_fail_on_oversize_file(artifact: Path, versions: Path):
big = artifact / "en/rolling/huge.bin"
big.write_bytes(b"\0" * (26 * 1024 * 1024)) # > 25 MiB
rc = gates.run(artifact=artifact, slug="rolling", versions=versions,
previous_meta=None, critical=["index.html"])
assert rc == 1
def test_fail_when_declared_pdf_missing(artifact: Path, versions: Path):
(artifact / "en/rolling/vyos-documentation.pdf").unlink()
rc = gates.run(artifact=artifact, slug="rolling", versions=versions,
previous_meta=None, critical=["index.html"])
assert rc == 1
def test_critical_list_strips_before_testing_for_comments(monkeypatch, tmp_path, artifact):
# An INDENTED comment used to survive the `line.startswith("#")` test (applied to the
# UNSTRIPPED line) and become a live critical-page entry. A comment can never exist as a
# file, so it would block every deploy with "critical page missing: en/rolling/ # ...".
crit = tmp_path / "critical.txt"
crit.write_text("# leading comment\n # indented comment\n\n index.html \n")
seen: list[str] = []
monkeypatch.setattr(gates, "run",
lambda art, slug, versions, prev, critical: seen.extend(critical) or 0)
monkeypatch.setattr(sys, "argv", [
"gates", "--artifact", str(artifact), "--slug", "rolling",
"--versions", str(versions_arg(tmp_path)), "--critical-list", str(crit)])
assert gates.main() == 0
assert seen == ["index.html"]
|