From 50912480b93c73278e99790b1715c814c3b9ee55 Mon Sep 17 00:00:00 2001 From: Chinpo Nya Date: Tue, 4 Apr 2023 19:46:14 +0200 Subject: [PATCH] automate nix package updates --- contrib/package/nix/copyparty/default.nix | 8 +-- contrib/package/nix/copyparty/pin.json | 5 ++ contrib/package/nix/copyparty/update.py | 77 +++++++++++++++++++++++ 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 contrib/package/nix/copyparty/pin.json create mode 100755 contrib/package/nix/copyparty/update.py diff --git a/contrib/package/nix/copyparty/default.nix b/contrib/package/nix/copyparty/default.nix index 8832aea8..2daca125 100644 --- a/contrib/package/nix/copyparty/default.nix +++ b/contrib/package/nix/copyparty/default.nix @@ -2,6 +2,7 @@ , pyvips, pyftpdlib, pyopenssl, impacket, ffmpeg }: let + pinData = lib.importJSON ./pin.json; pyEnv = python.withPackages (ps: with ps; [ # mandatory @@ -21,11 +22,10 @@ let ]); in stdenv.mkDerivation rec { pname = "copyparty"; - version = "1.6.11"; + version = pinData.version; src = fetchurl { - url = - "https://github.com/9001/copyparty/releases/download/v${version}/copyparty-sfx.py"; - hash = "sha256-0JbjOrZm70UhOJndOhBzX2K1RBM5y3N0+TsjLQtsjTQ="; + url = pinData.url; + hash = pinData.hash; }; buildInputs = [ makeWrapper ]; dontUnpack = true; diff --git a/contrib/package/nix/copyparty/pin.json b/contrib/package/nix/copyparty/pin.json new file mode 100644 index 00000000..214b99fe --- /dev/null +++ b/contrib/package/nix/copyparty/pin.json @@ -0,0 +1,5 @@ +{ + "url": "https://github.com/9001/copyparty/releases/download/v1.6.11/copyparty-sfx.py", + "version": "1.6.11", + "hash": "sha256-0JbjOrZm70UhOJndOhBzX2K1RBM5y3N0+TsjLQtsjTQ=" +} \ No newline at end of file diff --git a/contrib/package/nix/copyparty/update.py b/contrib/package/nix/copyparty/update.py new file mode 100755 index 00000000..363773c0 --- /dev/null +++ b/contrib/package/nix/copyparty/update.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 + +# Update the Nix package pin +# +# Usage: ./update.sh [PATH] +# When the [PATH] is not set, it will fetch the latest release from the repo. +# With [PATH] set, it will hash the given file and generate the URL, +# base on the version contained within the file + +import base64 +import json +import hashlib +import sys +import re +from pathlib import Path + +OUTPUT_FILE = Path("pin.json") +TARGET_ASSET = "copyparty-sfx.py" +HASH_TYPE = "sha256" +LATEST_RELEASE_URL = "https://api.github.com/repos/9001/copyparty/releases/latest" +DOWNLOAD_URL = lambda version: f"https://github.com/9001/copyparty/releases/download/v{version}/{TARGET_ASSET}" + + +def get_formatted_hash(binary): + hasher = hashlib.new("sha256") + hasher.update(binary) + asset_hash = hasher.digest() + encoded_hash = base64.b64encode(asset_hash).decode("ascii") + return f"{HASH_TYPE}-{encoded_hash}" + + +def version_from_sfx(binary): + result = re.search(b'^VER = "(.*)"$', binary, re.MULTILINE) + if result: + return result.groups(1)[0].decode("ascii") + + raise ValueError("version not found in provided file") + + +def remote_release_pin(): + import requests + + response = requests.get(LATEST_RELEASE_URL).json() + version = response["tag_name"].lstrip("v") + asset_info = [a for a in response["assets"] if a["name"] == TARGET_ASSET][0] + download_url = asset_info["browser_download_url"] + asset = requests.get(download_url) + formatted_hash = get_formatted_hash(asset.content) + + result = {"url": download_url, "version": version, "hash": formatted_hash} + return result + + +def local_release_pin(path): + asset = path.read_bytes() + version = version_from_sfx(asset) + download_url = DOWNLOAD_URL(version) + formatted_hash = get_formatted_hash(asset) + + result = {"url": download_url, "version": version, "hash": formatted_hash} + return result + + +def main(): + if len(sys.argv) > 1: + asset_path = Path(sys.argv[1]) + result = local_release_pin(asset_path) + else: + result = remote_release_pin() + + print(result) + json_result = json.dumps(result, indent=4) + OUTPUT_FILE.write_text(json_result) + + +if __name__ == "__main__": + main()