update-from-hydra/update_from_hydra.py

92 lines
2.9 KiB
Python

#!/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")
nix_copy = ["nix", "copy", "--from", cache_store_uri, hydra_store_path]
print(">", *nix_copy, flush=True)
subprocess.run(nix_copy)
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()