{ 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 ]; }; }