diff options
| author | sommerfeld <sommerfeld@sommerfeld.dev> | 2026-09-17 15:05:36 +0100 |
|---|---|---|
| committer | sommerfeld <sommerfeld@sommerfeld.dev> | 2026-09-17 15:05:36 +0100 |
| commit | aff435a0fb3a56b1d7b738c7dede363440884b3a (patch) | |
| tree | 07acb41d37760aa169ee42dbeb69da3621cc7489 /scripts/canonical.py | |
| parent | a7f74c1fa4b89c5829f5896842eb7248c820704c (diff) | |
| download | dotfiles-aff435a0fb3a56b1d7b738c7dede363440884b3a.tar.gz dotfiles-aff435a0fb3a56b1d7b738c7dede363440884b3a.tar.bz2 dotfiles-aff435a0fb3a56b1d7b738c7dede363440884b3a.zip | |
Add the Canonical laptop profile and setup workflows
Diffstat (limited to 'scripts/canonical.py')
| -rw-r--r-- | scripts/canonical.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/scripts/canonical.py b/scripts/canonical.py new file mode 100644 index 0000000..2ff6310 --- /dev/null +++ b/scripts/canonical.py @@ -0,0 +1,137 @@ +"""Install declared corporate packages without removing existing packages.""" + +import argparse +import json +import os +import platform +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + + +def packages(source: str) -> list[str]: + return [ + line.strip() + for line in (ROOT / "meta/canonical" / f"{source}.txt").read_text().splitlines() + if line.strip() and not line.startswith("#") + ] + + +def snap_install_commands() -> list[list[str]]: + return [ + ["sudo", "snap", "install", name, "--channel=stable"] + + (["--classic"] if name == "ghostty" else []) + for name in packages("snap") + ] + + +def flatpak_install_commands() -> list[list[str]]: + return [ + [ + "flatpak", + "remote-add", + "--user", + "--if-not-exists", + "flathub", + "https://flathub.org/repo/flathub.flatpakrepo", + ], + [ + "flatpak", + "install", + "--user", + "--assumeyes", + "flathub", + *packages("flatpak"), + ], + ] + + +def update_commands() -> list[list[str]]: + # An untargeted refresh respects Snap holds. Explicit targets override them. + return [ + ["sudo", "apt-get", "update"], + ["sudo", "apt-get", "upgrade"], + ["sudo", "snap", "refresh"], + ] + + +def require_canonical() -> None: + data = json.loads( + subprocess.check_output(["chezmoi", "data", "-S", str(ROOT)], text=True) + ) + if data.get("machineRole") != "canonical": + raise SystemExit("This command requires machineRole=canonical.") + if platform.freedesktop_os_release().get("ID") != "ubuntu": + raise SystemExit("This command requires Ubuntu.") + + +def install() -> None: + subprocess.run(["sudo", "apt-get", "update"], check=True) + subprocess.run(["sudo", "apt-get", "install", *packages("apt")], check=True) + for command in snap_install_commands(): + if subprocess.run( + ["snap", "list", command[3]], + check=False, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ).returncode: + subprocess.run(command, check=True) + for command in flatpak_install_commands(): + subprocess.run(command, check=True) + + +def check() -> None: + commands = [ + ["lsb_release", "-ds"], + *[ + ["systemctl", "is-active", unit] + for unit in ["display-manager", "snapd", "apparmor", "nix-daemon"] + ], + ["landscape-config", "--actively-registered"], + ["snap", "connections", "thunderbird"], + ["snap", "list", *packages("snap")], + ["gnome-extensions", "list", "--enabled"], + ["flatpak", "list", "--user", "--app"], + *[["flatpak", "info", "--user", app] for app in packages("flatpak")], + ["getent", "passwd", str(os.getuid())], + ["getsubids", os.environ.get("USER", "")], + ["getsubids", "-g", os.environ.get("USER", "")], + ] + failed = False + for command in commands: + print("\n> " + " ".join(command), flush=True) + try: + failed |= subprocess.run(command, check=False).returncode != 0 + except FileNotFoundError: + print(f"Missing: {command[0]}") + failed = True + if failed: + raise SystemExit(1) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "action", choices=["install", "update", "flatpak-update", "extensions", "check"] + ) + args = parser.parse_args() + require_canonical() + if args.action == "install": + install() + elif args.action == "check": + check() + else: + commands = update_commands() + if args.action == "flatpak-update": + commands = [ + ["flatpak", "update", "--user", "--assumeyes", *packages("flatpak")] + ] + elif args.action == "extensions": + commands = [["gext", "install", *packages("extensions")]] + for command in commands: + subprocess.run(command, check=True) + + +if __name__ == "__main__": + main() |
