158 lines
4.4 KiB
Nix
158 lines
4.4 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.services.git-pull-timer;
|
|
in
|
|
{
|
|
options.services.git-pull-timer = {
|
|
enable = mkEnableOption "git pull timer service";
|
|
|
|
onCalendar = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [ "daily" ];
|
|
description = "OnCalendar options for the timer (systemd calendar format)";
|
|
example = [
|
|
"hourly"
|
|
"daily"
|
|
"*:0/30"
|
|
];
|
|
};
|
|
|
|
onBoot = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = "Enable OnBootSec = 5min option for the timer";
|
|
};
|
|
|
|
persistent = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Persistent option for the timer (catch up missed runs)";
|
|
};
|
|
|
|
remoteAddresses = mkOption {
|
|
type = types.listOf types.str;
|
|
default = null;
|
|
description = "List of git remote addresses to try in order";
|
|
example = [
|
|
"git@github.com:user/repo.git"
|
|
"https://github.com/user/repo.git"
|
|
];
|
|
};
|
|
|
|
directory = mkOption {
|
|
type = types.str;
|
|
default = "/etc/nixos";
|
|
description = "Directory where the git repository should be located";
|
|
};
|
|
|
|
user = mkOption {
|
|
type = types.str;
|
|
default = null;
|
|
description = "User to run the git operations as";
|
|
};
|
|
|
|
group = mkOption {
|
|
type = types.str;
|
|
default = null;
|
|
description = "Group to run the git operations as";
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
assertions = [
|
|
{
|
|
assertion = cfg.remoteAddresses != null && cfg.remoteAddresses != [ ];
|
|
message = "services.git-pull-timer.remoteAddresses must be set and non-empty";
|
|
}
|
|
{
|
|
assertion = cfg.user != null;
|
|
message = "services.git-pull-timer.user must be set";
|
|
}
|
|
{
|
|
assertion = cfg.group != null;
|
|
message = "services.git-pull-timer.group must be set";
|
|
}
|
|
];
|
|
|
|
systemd.services.git-pull-timer = {
|
|
description = "Pull git repository";
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStartPre = [
|
|
"+${pkgs.coreutils}/bin/mkdir -p ${cfg.directory}"
|
|
"+${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${cfg.directory}"
|
|
];
|
|
ExecStart = pkgs.writeShellScript "git-pull-script" ''
|
|
set -e
|
|
cd ${cfg.directory}
|
|
|
|
# Check if this is a git repository
|
|
if ! ${pkgs.git}/bin/git rev-parse --git-dir > /dev/null 2>&1; then
|
|
echo "No git repository found, attempting to clone..."
|
|
|
|
# Try each remote address in order
|
|
success=false
|
|
${concatMapStringsSep "\n" (addr: ''
|
|
if [ "$success" = "false" ]; then
|
|
echo "Trying to clone from: ${addr}"
|
|
if ${pkgs.git}/bin/git clone ${addr} . 2>/dev/null; then
|
|
echo "Successfully cloned from: ${addr}"
|
|
success=true
|
|
else
|
|
echo "Failed to clone from: ${addr}"
|
|
fi
|
|
fi
|
|
'') cfg.remoteAddresses}
|
|
|
|
if [ "$success" = "false" ]; then
|
|
echo "All clone attempts failed"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Git repository exists, pulling updates..."
|
|
|
|
# Check if there are unstaged changes
|
|
if ! ${pkgs.git}/bin/git diff --quiet; then
|
|
echo "Unstaged changes detected, stashing..."
|
|
${pkgs.git}/bin/git stash push -m "Auto-stash before pull $(date)"
|
|
fi
|
|
|
|
# Check if there are staged changes
|
|
if ! ${pkgs.git}/bin/git diff --cached --quiet; then
|
|
echo "Staged changes detected, pulling with rebase..."
|
|
${pkgs.git}/bin/git pull --rebase
|
|
else
|
|
echo "No staged changes, doing regular pull..."
|
|
${pkgs.git}/bin/git pull
|
|
fi
|
|
fi
|
|
'';
|
|
User = cfg.user;
|
|
Group = cfg.group;
|
|
};
|
|
wants = [ "network-online.target" ];
|
|
after = [ "network-online.target" ];
|
|
};
|
|
|
|
systemd.timers.git-pull-timer = {
|
|
description = "Timer for git pull service";
|
|
timerConfig =
|
|
{
|
|
OnCalendar = cfg.onCalendar;
|
|
Persistent = cfg.persistent;
|
|
}
|
|
// optionalAttrs cfg.onBoot {
|
|
OnBootSec = "5min";
|
|
};
|
|
wantedBy = [ "timers.target" ];
|
|
};
|
|
};
|
|
}
|