@@ -73,17 +73,19 @@ def _run(*args):
7373 print (out .encode ("ascii" , "replace" ).decode ("ascii" ))
7474 if p .returncode :
7575 raise RunError (p .returncode , out )
76+ return out
7677
7778
7879def call_ssh (* args , allow_fail = True ):
7980 if not UPLOAD_HOST or NO_UPLOAD or LOCAL_INDEX :
8081 print ("Skipping" , args , "because UPLOAD_HOST is missing" )
8182 return
8283 try :
83- _run (* _std_args (PLINK ), f"{ UPLOAD_USER } @{ UPLOAD_HOST } " , * args )
84- except RunError :
84+ return _run (* _std_args (PLINK ), f"{ UPLOAD_USER } @{ UPLOAD_HOST } " , * args )
85+ except RunError as ex :
8586 if not allow_fail :
8687 raise
88+ return ex .args [1 ]
8789
8890
8991def upload_ssh (source , dest ):
@@ -229,6 +231,13 @@ def install_sortkey(install):
229231 )
230232
231233
234+ def find_missing_from_index (url , installs ):
235+ with urlopen (url ) as r :
236+ x = {install_sortkey (i ) for i in json .load (r )["versions" ]}
237+ y = {install_sortkey (i ) for i in installs } - x
238+ return [i for i in installs if install_sortkey (i ) in y ]
239+
240+
232241UPLOADS = list (calculate_uploads ())
233242
234243if not UPLOADS :
@@ -241,8 +250,13 @@ def install_sortkey(install):
241250
242251index = {"versions" : []}
243252
253+ INDEX_MTIME = 0
254+
244255if INDEX_FILE :
245256 INDEX_PATH = url2path (INDEX_URL )
257+
258+ INDEX_MTIME = int (call_ssh (["stat" , "-c" , "%Y" , INDEX_PATH ]) or 0 )
259+
246260 try :
247261 if not LOCAL_INDEX :
248262 download_ssh (INDEX_PATH , INDEX_FILE )
@@ -257,6 +271,8 @@ def install_sortkey(install):
257271 except FileNotFoundError :
258272 pass
259273
274+ print (INDEX_PATH , "mtime =" , INDEX_MTIME )
275+
260276
261277new_installs = [trim_install (i ) for i , * _ in UPLOADS ]
262278validate_new_installs (new_installs )
@@ -293,25 +309,41 @@ def install_sortkey(install):
293309 upload_ssh (sbom , sbom_dest )
294310
295311
296- if not NO_UPLOAD :
297- if INDEX_FILE :
298- print ("Uploading" , INDEX_FILE , "to" , INDEX_URL )
299- upload_ssh (INDEX_FILE , INDEX_PATH )
312+ # Check that nobody else has published while we were uploading
313+ if INDEX_FILE and INDEX_MTIME :
314+ mtime = int (call_ssh (["stat" , "-c" , "%Y" , INDEX_PATH ]) or 0 )
315+ if mtime > INDEX_MTIME :
316+ print ("##[error]Lost a race with another publish step!" )
317+ print ("Expecting mtime" , INDEX_MTIME , "but saw" , mtime )
318+ sys .exit (1 )
319+
300320
321+ if not NO_UPLOAD :
301322 if MANIFEST_FILE :
302323 print ("Uploading" , MANIFEST_FILE , "to" , MANIFEST_URL )
303324 upload_ssh (MANIFEST_FILE , MANIFEST_PATH )
304325
326+ if INDEX_FILE :
327+ print ("Uploading" , INDEX_FILE , "to" , INDEX_URL )
328+ upload_ssh (INDEX_FILE , INDEX_PATH )
329+
305330 print ("Purging" , len (UPLOADS ), "uploaded files" )
306331 parents = set ()
307332 for i , * _ in UPLOADS :
308333 purge (i ["url" ])
309334 parents .add (i ["url" ].rpartition ("/" )[0 ] + "/" )
310335 for i in parents :
311336 purge (i )
312- if INDEX_URL :
313- purge (INDEX_URL )
314- purge (INDEX_URL .rpartition ("/" )[0 ] + "/" )
315337 if MANIFEST_URL :
316338 purge (MANIFEST_URL )
317339 purge (MANIFEST_URL .rpartition ("/" )[0 ] + "/" )
340+ if INDEX_URL :
341+ purge (INDEX_URL )
342+ purge (INDEX_URL .rpartition ("/" )[0 ] + "/" )
343+ missing = find_missing_from_index (INDEX_URL , [i for i , * _ in UPLOADS ])
344+ if missing :
345+ print ("##[error]Lost a race with another publish step!" )
346+ print ("Index at" , INDEX_URL , "does not contain installs:" )
347+ for m in missing :
348+ print (m ["id" ], m ["sort-version" ])
349+ sys .exit (1 )
0 commit comments