Path: blob/trunk/scripts/update_multitool_binaries.py
8296 views
#!/usr/bin/env python1"""Update tool binaries in a Bazel rules_multitool lockfile.23This script updates the version of tool binaries defined in a Bazel rules_multitool lockfile.4If the tool has binaries hosted in a public GitHub repo's Release assets, it will update the5lockfile's URL and hash to the latest versions, otherwise it will skip it.67See: https://github.com/theoremlp/rules_multitool89-----------------------------------------------------------------------------------------------------------10usage: update_multitool_binaries.py [-h] [--file LOCKFILE_PATH]1112options:13-h, --help show this help message and exit14--file LOCKFILE_PATH path to multitool lockfile (defaults to 'multitool.lock.json' in workspace directory)15-----------------------------------------------------------------------------------------------------------16"""1718import argparse19import json20import os21import re22import urllib.request232425def run(lockfile_path):26with open(lockfile_path) as f:27data = json.load(f)2829for tool in [tool for tool in data if tool != "$schema"]:30match = re.search(f"download/(.*?)/{tool}", data[tool]["binaries"][0]["url"])31if match:32version = match[1]33else:34continue35match = re.search("github.com/(.*?)/releases", data[tool]["binaries"][0]["url"])36if match:37releases_url = f"https://api.github.com/repos/{match[1]}/releases/latest"38else:39continue40try:41with urllib.request.urlopen(releases_url) as response:42json_resp = json.loads(response.read())43new_version = json_resp["tag_name"]44assets = json_resp["assets"]45except Exception:46continue47if new_version != version:48print(f"found new version of '{tool}': {new_version}")49urls = [asset.get("browser_download_url") for asset in assets]50hashes = [asset.get("digest").split(":")[1] for asset in assets]51bare_version = version.lstrip("v")52bare_new = new_version.lstrip("v")53for binary in data[tool]["binaries"]:54new_url = binary["url"].replace(version, new_version)55new_file = binary["file"].replace(version, new_version)56if bare_version != version:57new_url = new_url.replace(bare_version, bare_new)58new_file = new_file.replace(bare_version, bare_new)59new_hash = hashes[urls.index(new_url)]60binary["url"] = new_url61binary["file"] = new_file62binary["sha256"] = new_hash6364with open(lockfile_path, "w") as f:65json.dump(data, f, indent=2)66f.write("\n")6768print(f"\ngenerated new '{lockfile_path}' with updated urls and hashes")697071def main():72parser = argparse.ArgumentParser()73workspace_dir = os.environ.get("BUILD_WORKSPACE_DIRECTORY", os.getcwd())74parser.add_argument(75"--file",76dest="lockfile_path",77default=os.path.join(workspace_dir, "multitool.lock.json"),78help="path to multitool lockfile (defaults to 'multitool.lock.json' in workspace directory)",79)80args = parser.parse_args()81run(args.lockfile_path)828384if __name__ == "__main__":85main()868788