Skip to content

Commit bade488

Browse files
committed
TUN-8631: Abort release on version mismatch
Closes TUN-8631 Approved-by: Gonçalo Garcia <[email protected]> Approved-by: Devin Carr <[email protected]> MR: https://gitlab.cfdata.org/cloudflare/tun/cloudflared/-/merge_requests/1579
1 parent b426c62 commit bade488

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

github_release.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
import requests
1212
import tarfile
1313
from os import listdir
14-
from os.path import isfile, join
14+
from os.path import isfile, join, splitext
1515
import re
16+
import subprocess
1617

1718
from 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+
213269
def 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

Comments
 (0)