2525# -- Connect and read timeouts in secs
2626TIMEOUT = (10 , 60 )
2727
28- # -- Prefix of the parts index asset published by packages whose device
29- # -- databases are fetched on demand (openxc7). The rest of the asset name
30- # -- is the release tag's date, the same rule apio uses for every asset.
28+ # -- Names under which a release publishes its parts index: the name the
29+ # -- document has inside the package, and the dated asset name apio derives
30+ # -- from the tag. Both are accepted, so that renaming the asset to the
31+ # -- former does not need this script and the toolchain to change at once.
32+ PARTS_INDEX_NAME = "PARTS-INDEX.json"
3133PARTS_INDEX_PREFIX = "apio-xilinx-parts-index-"
3234
35+ # -- Packages whose device databases are fetched on demand, and the first
36+ # -- release tag that is. Their earlier releases carried the databases
37+ # -- inside the package and need no index; from these tags on, a release
38+ # -- without one is broken, not old.
39+ PARTS_INDEX_REQUIRED_FROM = {"openxc7" : "2026-08-29" }
40+
3341# -- The parts index schema that apio's loader
3442# -- (apio/managers/xilinx_chipdb.py) knows how to read. A release with a
3543# -- different schema renamed or reshaped the fields the loader uses, so
3644# -- bump this together with the loader.
37- PARTS_INDEX_SCHEMA = 5
45+ PARTS_INDEX_SCHEMA_VERSION = 5
3846
3947
4048def github_api_headers () -> dict [str , str ]:
@@ -103,7 +111,7 @@ def check_package(package_name: str, package_config: Dict):
103111
104112 # -- If this package fetches its device databases on demand, check that
105113 # -- the databases its index promises are actually published.
106- check_parts_index (tag , assets )
114+ check_parts_index (package_name , tag , assets )
107115
108116
109117def check_parts_index_content (index_name : str , index : Dict , assets : Dict ):
@@ -158,34 +166,57 @@ def check_parts_index_content(index_name: str, index: Dict, assets: Dict):
158166 )
159167
160168
161- def check_parts_index (tag : str , assets : Dict ):
169+ def find_parts_index (package_name : str , tag : str , assets : Dict ) -> str :
170+ """Return the name of the release's parts index asset, or None if the
171+ release has none and is not required to have one."""
172+
173+ # -- Preferred name, the one the document has inside the package.
174+ if PARTS_INDEX_NAME in assets :
175+ return PARTS_INDEX_NAME
176+
177+ # -- Dated name. Asset names are derived from the tag's date, so it
178+ # -- must be the one named after this tag: an index from another
179+ # -- release describes another release's assets.
180+ dated = [n for n in assets if n .startswith (PARTS_INDEX_PREFIX )]
181+ assert len (dated ) <= 1 , dated
182+ if dated :
183+ expected_name = PARTS_INDEX_PREFIX + tag .replace ("-" , "" ) + ".json"
184+ if dated [0 ] != expected_name :
185+ print (
186+ f"Error: expected index '{ expected_name } ', "
187+ f"found '{ dated [0 ]} '"
188+ )
189+ sys .exit (1 )
190+ return dated [0 ]
191+
192+ # -- No index. For a package that fetches its databases on demand that
193+ # -- is a broken release, not an old one, so do not pass it silently.
194+ required_from = PARTS_INDEX_REQUIRED_FROM .get (package_name )
195+ if required_from and tag >= required_from :
196+ print (
197+ f"Error: release '{ tag } ' of package '{ package_name } ' has no "
198+ f"parts index, and releases from '{ required_from } ' on need one"
199+ )
200+ sys .exit (1 )
201+
202+ return None
203+
204+
205+ def check_parts_index (package_name : str , tag : str , assets : Dict ):
162206 """Check the on-demand device databases of a release, if it has any.
163207
164208 Packages whose device databases are fetched on demand (openxc7)
165209 publish an index asset that tells apio which database file to download
166210 for a given part. 'assets' maps the release's asset names to their
167211 github metadata."""
168212
169- # -- Packages without on-demand databases publish no index.
170- index_names = [n for n in assets if n .startswith (PARTS_INDEX_PREFIX )]
171- if not index_names :
213+ index_name = find_parts_index (package_name , tag , assets )
214+ if index_name is None :
172215 return
173- assert len (index_names ) == 1 , index_names
174- index_name = index_names [0 ]
175216
176217 print ()
177218 print (f"Checking parts index [{ index_name } ]" )
178219
179- # -- Asset names are derived from the tag's date, so the index of this
180- # -- release must be the one named after this tag.
181- expected_name = PARTS_INDEX_PREFIX + tag .replace ("-" , "" ) + ".json"
182- if index_name != expected_name :
183- print (
184- f"Error: expected index '{ expected_name } ', "
185- f"found '{ index_name } '"
186- )
187- sys .exit (1 )
188-
189220 # -- Fetch the index. It is a small json (tens of KB). No github token
190221 # -- here: the download url redirects to blob storage, which rejects a
191222 # -- forwarded Authorization header.
@@ -197,10 +228,10 @@ def check_parts_index(tag: str, assets: Dict):
197228
198229 # -- A different schema means the fields apio's loader reads were
199230 # -- renamed or reshaped.
200- if index .get ("schema" ) != PARTS_INDEX_SCHEMA :
231+ if index .get ("schema" ) != PARTS_INDEX_SCHEMA_VERSION :
201232 print (
202233 f"Error: { index_name } has schema { index .get ('schema' )} , but "
203- f"apio's loader expects schema { PARTS_INDEX_SCHEMA } "
234+ f"apio's loader expects schema { PARTS_INDEX_SCHEMA_VERSION } "
204235 )
205236 sys .exit (1 )
206237
0 commit comments