Path: blob/trunk/scripts/update_multitool_binaries.py
3987 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 current 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]51for binary in data[tool]["binaries"]:52new_url = binary["url"].replace(version, new_version)53new_file = binary["file"].replace(version, new_version)54new_hash = hashes[urls.index(new_url)]55binary["url"] = new_url56binary["file"] = new_file57binary["sha256"] = new_hash5859with open(lockfile_path, "w") as f:60json.dump(data, f, indent=2)61f.write("\n")6263print(f"\ngenerated new '{lockfile_path}' with updated urls and hashes")646566def main():67parser = argparse.ArgumentParser()68parser.add_argument(69"--file",70dest="lockfile_path",71default=os.path.join(os.getcwd(), "multitool.lock.json"),72help="path to multitool lockfile (defaults to 'multitool.lock.json' in current directory)",73)74args = parser.parse_args()75run(args.lockfile_path)767778if __name__ == "__main__":79main()808182