Merge branch 'updater'

This commit is contained in:
UGA Innovation Factory
2025-12-19 10:54:45 -05:00
2 changed files with 154 additions and 16 deletions

View File

@@ -121,9 +121,8 @@
};
};
"usda-dash" = builtins.fetchGit {
url = "git+ssh://git@factory.uga.edu/MODEL/usda-dash-config.git";
rev = "66afa5e5722100fe1f4f034c4cc33e506f4826f7";
submodules = true;
url = "https://git.factory.uga.edu/MODEL/usda-dash-config.git";
rev = "6c0029057aa50d0b4d6a0205c3ded890eb08979c";
};
};
overrides = {

View File

@@ -35,25 +35,164 @@ with lib;
(pkgs.writeShellScriptBin "update-system" ''
set -euo pipefail
RED='\033[31m'; NC='\033[0m'
is_root() { [ "''${EUID:-$(id -u)}" -eq 0 ]; }
in_wheel() { id -nG 2>/dev/null | tr ' ' '\n' | grep -qx wheel; }
# Service path for unprivileged (no flags)
UNIT="update-system.service"
# Start following logs in the background
journalctl -fu "$UNIT" -n 0 --output=cat &
JPID=$!
# Start the service and wait for it to finish
if systemctl start --wait --no-ask-password "$UNIT"; then
STATUS=$?
else
STATUS=$?
# Figure out the "real" invoking user, even under sudo.
INVOKER_USER="''${SUDO_USER:-$(id -un)}"
INVOKER_HOME="$(getent passwd "$INVOKER_USER" | cut -d: -f6)"
if [ -z "$INVOKER_HOME" ]; then
# fallback if getent is weird in some containers
INVOKER_HOME="''${HOME:-/home/$INVOKER_USER}"
fi
sleep 2
# Defaults for flagged mode
DEFAULT_REMOTE_URL="https://git.factory.uga.edu/UGA-Innovation-Factory/athenix"
REPO_MODE="default" # default | local | remote
LOCAL_PATH=""
REMOTE_URL=""
BRANCH=""
IMPURE=0
# Kill the log follower
kill "$JPID" 2>/dev/null || true
usage() {
cat >&2 <<'EOF'
usage:
update-system
update-system [--local-repo[=PATH]] [--remote-repo=URL] [--branch=BRANCH] [--impure]
exit "$STATUS"
notes:
- No flags: runs the systemd service (works for unprivileged users via polkit).
- Any flags: only allowed for root or wheel (runs nixos-rebuild directly).
EOF
exit 2
}
# No flags -> polkit-friendly systemd service route
if [ "$#" -eq 0 ]; then
journalctl -fu "$UNIT" -n 0 --output=cat &
JPID=$!
if systemctl start --wait --no-ask-password "$UNIT"; then
STATUS=$?
else
STATUS=$?
fi
sleep 2
kill "$JPID" 2>/dev/null || true
exit "$STATUS"
fi
# Flags -> require root or wheel
if ! is_root && ! in_wheel; then
printf "''${RED}error:''${NC} flags are only allowed for root or wheel. Run without flags (service path), or use sudo / add yourself to wheel.\n" >&2
exit 2
fi
# Parse flags
while [ "$#" -gt 0 ]; do
case "$1" in
--local-repo)
REPO_MODE="local"
LOCAL_PATH="$INVOKER_HOME/athenix"
shift
;;
--local-repo=*)
REPO_MODE="local"
LOCAL_PATH="''${1#*=}"
shift
;;
--remote-repo=*)
REPO_MODE="remote"
REMOTE_URL="''${1#*=}"
shift
;;
--branch)
[ "$#" -ge 2 ] || usage
BRANCH="$2"
shift 2
;;
--branch=*)
BRANCH="''${1#*=}"
shift
;;
--impure)
IMPURE=1
shift
;;
-h|--help) usage ;;
*)
printf "''${RED}error:''${NC} unknown argument: %s\n" "$1" >&2
usage
;;
esac
done
if [ "$REPO_MODE" = "local" ] && [ -n "$REMOTE_URL" ]; then
printf "''${RED}error:''${NC} can't use --local-repo and --remote-repo together.\n" >&2
exit 2
fi
host="''${HOSTNAME:-$(hostname)}"
# Build flake ref
if [ "$REPO_MODE" = "local" ]; then
[ -n "$LOCAL_PATH" ] || LOCAL_PATH="$INVOKER_HOME/athenix"
# Clone default repo if missing
if [ ! -d "$LOCAL_PATH" ]; then
printf "local repo not found at %s, cloning %s...\n" "$LOCAL_PATH" "$DEFAULT_REMOTE_URL" >&2
if [ -n "$BRANCH" ]; then
git clone --branch "$BRANCH" "$DEFAULT_REMOTE_URL" "$LOCAL_PATH"
else
git clone "$DEFAULT_REMOTE_URL" "$LOCAL_PATH"
fi
fi
flakeRef="''${LOCAL_PATH}#''${host}"
else
url="''${REMOTE_URL:-$DEFAULT_REMOTE_URL}"
if echo "$url" | grep -qE '^(https?|ssh)://'; then
base="git+''${url}"
elif echo "$url" | grep -qE '^[^/@:]+@[^/:]+:'; then
# scp-style: git@host:owner/repo(.git)
userhost="''${url%%:*}"
path="''${url#*:}"
base="git+ssh://''${userhost}/''${path}"
else
base="''${url}"
fi
if [ -n "$BRANCH" ]; then
if echo "$base" | grep -q '?'; then
base="''${base}&ref=''${BRANCH}"
else
base="''${base}?ref=''${BRANCH}"
fi
fi
flakeRef="''${base}#''${host}"
fi
impureFlag=""
if [ "$IMPURE" -eq 1 ]; then
impureFlag="--impure"
fi
# If not root, re-exec via sudo to do the actual switch.
# Preserve our computed invoker context so sudo doesn't "helpfully" change it.
if ! is_root; then
exec sudo --preserve-env=HOME,USER,LOGNAME \
nixos-rebuild switch --refresh --print-build-logs $impureFlag --flake "$flakeRef"
else
exec nixos-rebuild switch --refresh --print-build-logs $impureFlag --flake "$flakeRef"
fi
'')
];