170170AUTHORING_REFERENCE_MANIFEST = (
171171 REPO_ROOT / "docs/site/scripts/authoring-reference-sources.json"
172172)
173+ IDENTIFIER_CATALOG_CONTRACT = (
174+ REPO_ROOT / "products/identifiers/contracts/catalog-source.json"
175+ )
176+
177+
178+ def identifier_catalog_inputs (
179+ contract_path : Path = IDENTIFIER_CATALOG_CONTRACT ,
180+ ) -> tuple [str , ...]:
181+ """Derive every source path that can change the public identifier catalog."""
182+
183+ contract = json .loads (contract_path .read_text (encoding = "utf-8" ))
184+ schema_groups = contract .get ("schemaSources" )
185+ records = contract .get ("records" )
186+ if not isinstance (schema_groups , list ) or not isinstance (records , list ):
187+ raise ValueError (
188+ f"identifier catalog has an invalid source contract: { contract_path } "
189+ )
190+
191+ inputs = [
192+ "products/identifiers/**" ,
193+ "crates/registry-relay-v2/src/problem.rs" ,
194+ ]
195+ for index , group in enumerate (schema_groups ):
196+ pattern = group .get ("glob" ) if isinstance (group , dict ) else None
197+ if not isinstance (pattern , str ) or not pattern :
198+ raise ValueError (f"identifier schemaSources[{ index } ] has no glob" )
199+ inputs .append (pattern )
200+ source = group .get ("sourcePath" )
201+ if source is not None :
202+ if not isinstance (source , str ) or not source :
203+ raise ValueError (
204+ f"identifier schemaSources[{ index } ] has an invalid sourcePath"
205+ )
206+ inputs .append (source )
207+ for index , record in enumerate (records ):
208+ source = record .get ("sourcePath" ) if isinstance (record , dict ) else None
209+ if not isinstance (source , str ) or not source :
210+ raise ValueError (f"identifier records[{ index } ] has no sourcePath" )
211+ inputs .append (source )
212+
213+ if any (source .startswith (("/" , "../" )) for source in inputs ):
214+ raise ValueError ("identifier catalog inputs must be repository-relative" )
215+ return tuple (dict .fromkeys (inputs ))
216+
217+
218+ IDENTIFIER_CATALOG_INPUTS = identifier_catalog_inputs ()
173219
174220
175221def authoring_reference_contract_sources (
@@ -405,6 +451,10 @@ def classify(
405451 seeds .update (PLATFORM_PACKAGES )
406452 elif path .startswith ("products/relay-v2/" ):
407453 seeds .update (RELAY_V2_PACKAGES )
454+ elif path .startswith ("products/identifiers/" ):
455+ # The catalog gate compiles its focused Relay V2 exporter.
456+ # Catalog-only tooling does not require the full Rust matrix.
457+ pass
408458 elif path in {
409459 "docs/site/src/data/generated/relay-support.json" ,
410460 "docs/site/src/data/relay-support.yaml" ,
@@ -421,6 +471,10 @@ def classify(
421471 )
422472 complete = run_all or force_all
423473
474+ identifiers = complete or any (
475+ matches (path , * IDENTIFIER_CATALOG_INPUTS ) for path in paths
476+ )
477+
424478 platform = complete or any (
425479 matches (
426480 path ,
@@ -644,6 +698,7 @@ def classify(
644698 "client_bindings" : client_bindings ,
645699 "registryctl_tutorial" : registryctl_tutorial ,
646700 "evidence_tutorial" : evidence_tutorial ,
701+ "identifiers" : identifiers ,
647702 }
648703
649704
0 commit comments