1111import requests
1212import tarfile
1313from os import listdir
14- from os .path import isfile , join
14+ from os .path import isfile , join , splitext
1515import re
16+ import subprocess
1617
1718from github import Github , GithubException , UnknownObjectException
1819
@@ -210,6 +211,61 @@ def move_asset(filepath, filename):
210211 except shutil .SameFileError :
211212 pass # the macOS release copy fails with being the same file (already in the artifacts directory)
212213
214+ def get_binary_version (binary_path ):
215+ """
216+ Sample output from go version -m <binary>:
217+ ...
218+ build -compiler=gc
219+ build -ldflags="-X \" main.Version=2024.8.3-6-gec072691\" -X \" main.BuildTime=2024-09-10-1027 UTC\" "
220+ build CGO_ENABLED=1
221+ ...
222+
223+ This function parses the above output to retrieve the following substring 2024.8.3-6-gec072691.
224+ To do this a start and end indexes are computed and the a slice is extracted from the output using them.
225+ """
226+ needle = "main.Version="
227+ cmd = ['go' ,'version' , '-m' , binary_path ]
228+ process = subprocess .Popen (cmd , stdout = subprocess .PIPE , stderr = subprocess .PIPE )
229+ output , _ = process .communicate ()
230+ version_info = output .decode ()
231+
232+ # Find start of needle
233+ needle_index = version_info .find (needle )
234+ # Find backward slash relative to the beggining of the needle
235+ relative_end_index = version_info [needle_index :].find ("\\ " )
236+ # Calculate needle position plus needle length to find version beggining
237+ start_index = needle_index + len (needle )
238+ # Calculate needle position plus relative position of the backward slash
239+ end_index = needle_index + relative_end_index
240+ return version_info [start_index :end_index ]
241+
242+ def assert_asset_version (binary_path , release_version ):
243+ """
244+ Asserts that the artifacts have the correct release_version.
245+ The artifacts that are checked must not have an extension expecting .exe and .tgz.
246+ In the occurrence of any other extension the function exits early.
247+ """
248+ try :
249+ shutil .rmtree ('tmp' )
250+ except OSError :
251+ pass
252+ _ , ext = os .path .splitext (binary_path )
253+ if ext == '.exe' or ext == '' :
254+ binary_version = get_binary_version (binary_path )
255+ elif ext == '.tgz' :
256+ tar = tarfile .open (binary_path , "r:gz" )
257+ tar .extractall ("tmp" , filter = 'data' )
258+ tar .close ()
259+ binary_path = os .path .join (os .getcwd (), 'tmp' , 'cloudflared' )
260+ binary_version = get_binary_version (binary_path )
261+ else :
262+ return
263+
264+ if binary_version != release_version :
265+ logging .error (f"Version mismatch { binary_path } , binary_version { binary_version } release_version { release_version } " )
266+ exit (1 )
267+
268+
213269def main ():
214270 """ Attempts to upload Asset to Github Release. Creates Release if it doesn't exist """
215271 try :
@@ -221,6 +277,7 @@ def main():
221277 for filename in onlyfiles :
222278 binary_path = os .path .join (args .path , filename )
223279 logging .info ("binary: " + binary_path )
280+ assert_asset_version (binary_path , args .release_version )
224281 elif os .path .isfile (args .path ):
225282 logging .info ("binary: " + binary_path )
226283 else :
@@ -233,6 +290,9 @@ def main():
233290
234291 if os .path .isdir (args .path ):
235292 onlyfiles = [f for f in listdir (args .path ) if isfile (join (args .path , f ))]
293+ for filename in onlyfiles :
294+ binary_path = os .path .join (args .path , filename )
295+ assert_asset_version (binary_path , args .release_version )
236296 for filename in onlyfiles :
237297 binary_path = os .path .join (args .path , filename )
238298 upload_asset (release , binary_path , filename , args .release_version , args .kv_account_id , args .namespace_id ,
0 commit comments