From 5177d942e477507a94369207d15feef325652e5b Mon Sep 17 00:00:00 2001 From: clerie Date: Fri, 21 Jul 2023 21:46:03 +0200 Subject: [PATCH] Init repository --- flake.lock | 27 ++++++++++++++ flake.nix | 37 ++++++++++++++++++ pyproject.toml | 23 ++++++++++++ update_from_hydra.py | 89 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 pyproject.toml create mode 100644 update_from_hydra.py diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..69f94c6 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1688679045, + "narHash": "sha256-t3xGEfYIwhaLTPU8FLtN/pLPytNeDwbLI6a7XFFBlGo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3c7487575d9445185249a159046cc02ff364bff8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3dab73f --- /dev/null +++ b/flake.nix @@ -0,0 +1,37 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + outputs = { self, nixpkgs, ... }: { + packages.x86_64-linux = let + pkgs = import nixpkgs { system = "x86_64-linux"; }; + in { + update-from-hydra = pkgs.python3Packages.buildPythonPackage rec { + pname = "update-from-hydra"; + version = "0.0.1"; + + src = ./.; + + format = "pyproject"; + + buildInputs = [ pkgs.python3Packages.hatchling ]; + propagatedBuildInputs = [ pkgs.python3Packages.requests ]; + }; + default = self.packages.x86_64-linux.update-from-hydra; + }; + + apps.x86_64-linux = { + update-from-hydra = { + type = "app"; + program = self.packages.x86_64-linux.update-from-hydra + "/bin/update-from-hydra"; + }; + default = self.apps.x86_64-linux.update-from-hydra; + }; + + hydraJobs = { + inherit (self) + packages; + }; + }; +} + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b062086 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,23 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "update-from-hydra" +version = "0.0.1" +authors = [ + { name="clerie", email="hallo@clerie.de" }, +] +description = "" +requires-python = ">=3.7" +classifiers = [ + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", +] +dependencies = [ + "requests" +] + + +[project.scripts] +update-from-hydra = "update_from_hydra:cli" diff --git a/update_from_hydra.py b/update_from_hydra.py new file mode 100644 index 0000000..2808df6 --- /dev/null +++ b/update_from_hydra.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +import argparse +import hashlib +from pathlib import Path +import requests +import subprocess +import sys + +def get_hydra_store_path(url): + """ + Accepts an url to a hydra build. + Can be: + https://hydra.clerie.de/job/nixfiles/nixfiles/iso/latest-finished + Or: + https://hydra.clerie.de/build/917 + """ + + r = requests.get(url, headers={"Accept": "application/json"}) + r.raise_for_status() + + return Path(r.json()["buildoutputs"]["out"]["path"]) + + +def cli(): + parser = argparse.ArgumentParser( + prog="update-from-hydra", + description="Fetch the latest build of a Hydra job and set it as a specified symlink", + ) + parser.add_argument("hydra_url") + parser.add_argument("update_path") + parser.add_argument("cache_store_uri") + args = parser.parse_args() + hydra_url = args.hydra_url + update_path = Path(args.update_path).absolute() + cache_store_uri = args.cache_store_uri + + print("Update url:", hydra_url) + print("Path to update:", update_path) + + current_store_path = None + + if update_path.exists(): + if not update_path.is_symlink(): + print("Path to update is not a symlink") + exit(1) + + current_store_path = update_path.readlink() + print("Current store path:", current_store_path) + else: + print("No current store path, update path does not exist") + + print("Look up Hydra build metadata") + hydra_store_path = get_hydra_store_path(hydra_url) + print("Store path in hydra:", hydra_store_path) + + if current_store_path == hydra_store_path: + print("Current store path is up to date") + exit() + + print("Downloading new store paths") + subprocess.run(["nix", "copy", "--from", cache_store_uri, hydra_store_path]) + print("Finished downloading") + + print("Updating path to update") + update_path.parent.mkdir(parents=True, exist_ok=True) + tmp_update_path = update_path.parent / ( update_path.name + ".new") + print("Creating temporary symlink:", tmp_update_path) + tmp_update_path.symlink_to(hydra_store_path) + print("Rename symlink to:", update_path) + tmp_update_path.rename(update_path) + + print("Adding to gcroot") + try: + gcroots_dir = Path("/nix/var/nix/gcroots/update-from-hydra") + update_dir_hash = hashlib.sha256(bytes(update_path)).hexdigest() + gcroots_dir.mkdir(parents=True, exist_ok=True) + gcroots_symlink = gcroots_dir / update_dir_hash + tmp_gcroots_symlink = gcroots_dir / (update_dir_hash + ".new") + print("Creating temporary symlink:", tmp_gcroots_symlink) + tmp_gcroots_symlink.symlink_to(update_path) + print("Rename symlink to:", gcroots_symlink) + tmp_gcroots_symlink.rename(gcroots_symlink) + except PermissionError: + print("Unable to create garbage collector root") + + +if __name__ == "__main__": + cli()