diff --git a/modules/home/programs/update-checker/default.nix b/modules/home/programs/update-checker/default.nix new file mode 100644 index 0000000..3ed1720 --- /dev/null +++ b/modules/home/programs/update-checker/default.nix @@ -0,0 +1,273 @@ +{ + config, + pkgs, + ... +}: +let + update-checker = pkgs.writeScriptBin "update-checker" '' + #!/usr/bin/env nix-shell + #! nix-shell -i python3 --pure + #! nix-shell -p python3 python3Packages.pygithub python3Packages.feedparser python3Packages.requests nix-prefetch-scripts nix + + import os + import json + import subprocess + from github import Github + from github import Auth + import feedparser + import requests + + token = os.get_env("GITHUB_TOKEN") + + auth = Auth.Token(token) + + def check_github(owner, repo, version): + try: + release = None + result = None + prefetch = None + ghub = Github(auth=auth) + print(" getting repo " + owner + "/" + repo) + repo = ghub.get_repo(owner + "/" + repo) + if "-b" in version: + release = repo.get_releases()[0] + latest_version = release.name + else: + try: + release = repo.get_latest_release() + latest_version = release.tag_name + except: + tags = repo.get_tags() + try: + if tags is not None: + latest_version = tags[0].name + except: + commits = repo.get_commits() + latest_version = commits[0].sha + + if latest_version is not None: + + if latest_version.replace("v",\"\") != version.replace("v",\""): + print(" update found") + print(" Current version: " + version) + print(" Latest version: " + latest_version) + result = subprocess.check_output(["nix-prefetch-git", "--quiet", repo.clone_url, "--rev", latest_version]) + prefetch = json.loads(result) + print(" New hash: " + prefetch.get("hash")) + else: + print(" no update") + ghub.close() + except Exception as e: + print(e) + + def check_codeberg(owner, repo, version): + feed = feedparser.parse("https://codeberg.org/{0}/{1}/releases.rss".format(owner, repo)) + if feed.status == 200: + entry = feed.entries[0] + if entry.title.replace("v","") != version.replace("v",""): + print(" update found") + print(" Current version: " + version) + print(" Latest version: " + entry.title) + sha256 = subprocess.check_output(["nix-prefetch-url", url.replace("''\${version}", entry.title.replace("v", ""))]) + prefetch = subprocess.check_output(["nix", "hash", "convert", "--hash-algo", "sha256", str(sha256.decode("utf-8").strip())]) + print(" New hash: " + prefetch.decode("utf-8").strip()) + else: + print(" no update") + + def check_open_vsx(publisher, name, version): + open_vsx = requests.get("https://open-vsx.org/api/" + publisher + "/" + name) + if open_vsx.status_code == 200: + extension = open_vsx.json() + latest_version = extension.get("version") + url = extension.get("files").get("download") + if latest_version.replace("v","") != version.replace("v",""): + print(" update found") + print(" Current version: " + version) + print(" Latest version: " + latest_version) + sha256 = subprocess.check_output(["nix-prefetch-url", url]) + prefetch = subprocess.check_output(["nix", "hash", "convert", "--hash-algo", "sha256", str(sha256.decode("utf-8").strip())]) + print(" New hash: " + prefetch.decode("utf-8").strip()) + else: + print(" no update") + + def parse_nix(package_spec): + version = None + url = None + current_hash = None + owner = None + repo = None + pname = None + name = None + publisher = None + for line in package_spec.readlines(): + if "owner = "" in line and owner is None: + owner = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if "repo = "" in line and repo is None: + repo = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if "version = "" in line and version is None: + version = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if "rev = "" in line and "''\${version}" not in line: + version = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if "url = "" in line and url is None: + url = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if "sha256 = "" in line or " hash = "" in line and current_hash is None: + current_hash = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if "pname = "" in line and pname is None: + pname = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if " name = "" in line and name is None: + name = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + if "publisher = "" in line and publisher is None: + publisher = line.split(" = ")[-1].replace(""", "").replace(";\n", "") + + if url is None and repo is not None: + if "pname" in repo: + repo = repo.replace("''\${pname}", pname) + url = "https://github.com/{0}/{1}/releases/tag/{2}".format(owner, repo, version) + + if url is not None and repo is None and "github" in url: + owner = url.split("github.com/")[-1].split("/")[0] + repo = url.split("github.com/")[-1].split("/")[1] + + if url is not None and repo is None and "codeberg" in url: + owner = url.split("codeberg.org/")[-1].split("/")[0] + repo = url.split("codeberg.org/")[-1].split("/")[1] + + if url is not None and version is None: + version = url.split("/")[-1].replace(".tar.gz", "") + + if url is not None and publisher is not None: + url = url.replace("''\${publisher}", publisher).replace("''\${name}", name) + + return url, current_hash, owner, repo, pname, name, publisher, version + + def parse_json(json_versions, flavor=""): + versions = json.load(json_versions) + linux_versions = versions.get("linux") + config_versions = versions.get("config") + patch_versions = versions.get("patches") + zfs_versions = versions.get("zfs") + + check_kernel(linux_versions, flavor) + check_cachy_config(config_versions, flavor) + check_patch_versions(patch_versions, flavor) + check_zfs_versions(zfs_versions, flavor) + + def check_kernel(linux_versions, flavor=""): + srcinfo = requests.get("https://raw.githubusercontent.com/CachyOS/linux-cachyos/master/linux-cachyos" + flavor + "/.SRCINFO") + for line in srcinfo.text.split("\n"): + if "pkgver = " in line: + kernel_version = line.split("=")[-1].strip() + if kernel_version[-2:] == ".0": + kernel_version = kernel_version[:-2] + if flavor in ["", "-lts", "-server", "-gcc", "-hardened"]: + release_src = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-" + kernel_version + ".tar.xz" + if flavor == "-rc": + release_src = "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-" + kernel_version.replace(".rc", "-rc") + ".tar.gz" + sha256 = subprocess.check_output(["nix-prefetch-url", release_src]) + prefetch = subprocess.check_output(["nix", "hash", "convert", "--hash-algo", "sha256", str(sha256.decode("utf-8").strip())]) + current_version = linux_versions.get("version") + current_hash = linux_versions.get("hash") + latest_hash = prefetch.decode("utf-8").strip() + print(" Checking linux versions...") + if current_hash != latest_hash: + print(" Current rev: " + current_version) + print(" Current hash: " + current_hash) + print(" New rev: " + kernel_version) + print(" New hash: " + latest_hash) + else: + print(" no update") + + def check_cachy_config(config_versions, flavor=""): + result = subprocess.check_output(["nix-prefetch-git", "--quiet", "https://github.com/CachyOS/linux-cachyos.git"]) + prefetch = json.loads(result) + current_version = config_versions.get("rev") + latest_version = prefetch.get("rev") + print(" Checking config versions...") + if current_version != latest_version: + print(" Current rev: " + current_version) + print(" New rev: " + latest_version) + print(" New hash: " + prefetch.get("hash")) + else: + print(" no update") + + def check_patch_versions(patch_versions, flavor=""): + result = subprocess.check_output(["nix-prefetch-git", "--quiet", "https://github.com/CachyOS/kernel-patches.git"]) + prefetch = json.loads(result) + current_version = patch_versions.get("rev") + latest_version = prefetch.get("rev") + print(" Checking patch versions...") + if current_version != latest_version: + print(" Current rev: " + current_version) + print(" New rev: " + latest_version) + print(" New hash: " + prefetch.get("hash")) + else: + print(" no update") + + def kconfig_to_nix(flavor=""): + kconfig_result = subprocess.check_output(["nix", "build", ".#nixosConfigurations.jallen-nas.pkgs.linuxPackages_cachyos" + flavor + ".kernel.kconfigToNix", "--no-link", "--print-out-paths"]) + config_file = kconfig_result.decode("utf-8").strip() + if flavor == "": + cachy_flavor = "-gcc" + result = subprocess.check_output(["cat", config_file]) + with open("/etc/nixos/packages/linux-cachyos/config-nix/cachyos" + cachy_flavor + ".x86_64-linux.nix", "w") as config: + config.write(result.decode("utf-8").strip()) + + def check_zfs_versions(zfs_versions, flavor=""): + result = requests.get("https://raw.githubusercontent.com/CachyOS/linux-cachyos/master/linux-cachyos" + flavor + "/PKGBUILD") + for line in result.text.split("\n"): + if "git+https://github.com/cachyos/zfs.git#commit=" in line: + zfs_rev = line.split("zfs.git#commit=")[-1].replace("")", "") + result = subprocess.check_output(["nix-prefetch-git", "--quiet", "https://github.com/CachyOS/zfs.git", "--rev", zfs_rev]) + prefetch = json.loads(result) + current_version = zfs_versions.get("rev") + latest_version = prefetch.get("rev") + print(" Checking zfs versions...") + if current_version != latest_version: + print(" Current rev: " + current_version) + print(" New rev: " + latest_version) + print(" New hash: " + prefetch.get("hash")) + else: + print(" no update") + + for (root,dirs,files) in os.walk("/etc/nixos/packages",topdown=True): + if "default.nix" in files and "versions.json" not in files: + continue + print(root.split("/")[-1]) + with open(root + "/default.nix", "r") as package_spec: + url, current_hash, owner, repo, pname, name, publisher, version = parse_nix(package_spec) + + if owner is not None and repo is not None and "codeberg" in url: + check_codeberg(owner, repo, version) + + elif owner is not None and repo is not None and "github" in url: + check_github(owner, repo, version) + + elif publisher is not None and "open-vsx" in url: + check_open_vsx(publisher, name, version) + + else: + if url is not None: + print(url) + + if "default.nix" in files and "versions.json" in files: + with open(root + "/versions.json", "r") as json_versions: + print("Checking Linux CachyOS") + parse_json(json_versions) + with open(root + "/versions-rc.json", "r") as json_versions: + print("Checking Linux CachyOS RC") + parse_json(json_versions, "-rc") + with open(root + "/versions-lts.json", "r") as json_versions: + print("Checking Linux CachyOS LTS") + parse_json(json_versions, "-lts") + with open(root + "/versions-hardened.json", "r") as json_versions: + print("Checking Linux CachyOS Hardened") + parse_json(json_versions, "-hardened") + ''; +in +{ + imports = [ ../options.nix ]; + + config = { + home.packages = [ update-checker ]; + }; +} diff --git a/modules/nixos/programs/default.nix b/modules/nixos/programs/default.nix index 4d84d30..2b973b2 100644 --- a/modules/nixos/programs/default.nix +++ b/modules/nixos/programs/default.nix @@ -82,6 +82,7 @@ in environment = { systemPackages = with pkgs; [ attic-client + dislocker uutils-coreutils-noprefix uutils-diffutils uutils-findutils