4040GENERATED_DIAGRAMS_REPO = "cockroachdb/generated-diagrams"
4141GITHUB_API_BASE = "https://api.github.com"
4242VERSIONS_CSV = Path ("src/current/_data/versions.csv" )
43+ DOCS_ROOT = Path ("src/current" )
4344
4445# ---------------------------------------------------------------------------
4546# HTTP
@@ -69,6 +70,17 @@ def _api_get(path: str) -> dict | None:
6970# Core logic
7071# ---------------------------------------------------------------------------
7172
73+ def has_docs_folder (version : str ) -> bool :
74+ """Return True if a docs folder exists for this version.
75+
76+ Handles both naming conventions: v20_1 (underscore) and v23.1 (dot).
77+ """
78+ ver = version .lstrip ("v" )
79+ dot_form = DOCS_ROOT / f"v{ ver } "
80+ underscore_form = DOCS_ROOT / f"v{ ver .replace ('.' , '_' )} "
81+ return dot_form .is_dir () or underscore_form .is_dir ()
82+
83+
7284_cache : dict [str , bool ] = {}
7385
7486
@@ -88,13 +100,16 @@ def load_versions_csv() -> list[dict]:
88100 return list (csv .DictReader (f ))
89101
90102
91- def run_checks (rows : list [dict ], _exists_fn = None ) -> list [dict ]:
103+ def run_checks (rows : list [dict ], _exists_fn = None , _has_docs_fn = None ) -> list [dict ]:
92104 """Check each versions.csv row for branch existence and staleness.
93105
94106 _exists_fn is injectable for unit tests; defaults to branch_exists.
107+ _has_docs_fn is injectable for unit tests; defaults to has_docs_folder.
95108 """
96109 if _exists_fn is None :
97110 _exists_fn = branch_exists
111+ if _has_docs_fn is None :
112+ _has_docs_fn = has_docs_folder
98113
99114 failures = []
100115 checked : set [str ] = set ()
@@ -105,6 +120,11 @@ def run_checks(rows: list[dict], _exists_fn=None) -> list[dict]:
105120 if not branch or branch == "N/A" :
106121 continue
107122
123+ # Skip versions that have been archived from the site.
124+ if not _has_docs_fn (version ):
125+ print (f" { version :8s} → { branch } ... SKIP (archived)" )
126+ continue
127+
108128 # (a) Does the listed branch exist?
109129 if branch not in checked :
110130 checked .add (branch )
@@ -179,9 +199,11 @@ def format_comment(failures: list[dict]) -> str:
179199def _run_self_tests () -> None :
180200 """Unit tests for run_checks logic using injected exists functions."""
181201
182- def _quiet (rows , exists_fn ):
202+ _no_call = lambda b : (_ for _ in ()).throw (AssertionError ("unexpected call" ))
203+
204+ def _quiet (rows , exists_fn , has_docs_fn = lambda v : True ):
183205 with contextlib .redirect_stdout (io .StringIO ()):
184- return run_checks (rows , _exists_fn = exists_fn )
206+ return run_checks (rows , _exists_fn = exists_fn , _has_docs_fn = has_docs_fn )
185207
186208 # branch_missing: listed branch does not exist
187209 rows = [{"major_version" : "v26.1" , "crdb_branch_name" : "release-26.1" }]
@@ -204,14 +226,25 @@ def _quiet(rows, exists_fn):
204226
205227 # N/A entries are skipped entirely
206228 rows = [{"major_version" : "v24.1" , "crdb_branch_name" : "N/A" }]
207- failures = _quiet (rows , lambda b : ( _ for _ in ()). throw ( AssertionError ( "unexpected call" )) )
229+ failures = _quiet (rows , _no_call )
208230 assert failures == [], failures
209231
210232 # empty branch field is skipped
211233 rows = [{"major_version" : "v25.1" , "crdb_branch_name" : "" }]
212- failures = _quiet (rows , lambda b : ( _ for _ in ()). throw ( AssertionError ( "unexpected call" )) )
234+ failures = _quiet (rows , _no_call )
213235 assert failures == [], failures
214236
237+ # archived versions (no docs folder) are skipped
238+ rows = [{"major_version" : "v1.0" , "crdb_branch_name" : "release-1.0" }]
239+ failures = _quiet (rows , _no_call , has_docs_fn = lambda v : False )
240+ assert failures == [], failures
241+
242+ # non-archived version with missing branch still fails
243+ rows = [{"major_version" : "v26.1" , "crdb_branch_name" : "release-26.1" }]
244+ failures = _quiet (rows , lambda b : False , has_docs_fn = lambda v : True )
245+ assert len (failures ) == 1 , failures
246+ assert failures [0 ]["type" ] == "branch_missing" , failures
247+
215248 print ("All self-tests passed." )
216249 sys .exit (0 )
217250
0 commit comments