fix only first of multiple consecutive updates being applied

This commit is contained in:
bit 2025-08-22 17:22:07 +02:00
parent a44fd5e362
commit 450e62d142

View File

@ -18,168 +18,174 @@
... ...
}: }:
'' ''
#!/usr/bin/env bash do_update() {
set -e hostname=$(${hostname})
new_system=$(nix build --refresh --no-link --print-out-paths "${cfg.flake}#nixosConfigurations.''${hostname}.config.system.build.toplevel")
hostname=$(${hostname})
new_system=$(nix build --no-link --print-out-paths "${cfg.flake}#nixosConfigurations.''${hostname}.config.system.build.toplevel") last_flake_update_time() {
nix flake metadata --refresh --json "$1" | ${jq} .lastModified
last_flake_update_time() { }
nix flake metadata --refresh --json "$1" | ${jq} .lastModified
} updated_since_reboot() {
[[ $(${stat} -c %Y /run/current-system) -gt $(($(${date} +%s) - $(${cut} -d. -f1 /proc/uptime) + $(${units} --compact --one-line "ceil($(${units} --compact --one-line "$(${systemd-analyze} time | head -n 1 | ${grep} -Eo "\S+\s+$")" seconds))"))) ]]
updated_since_reboot() { }
[[ $(${stat} -c %Y /run/current-system) -gt $(($(${date} +%s) - $(${cut} -d. -f1 /proc/uptime) + $(${units} --compact --one-line "ceil($(${units} --compact --one-line "$(${systemd-analyze} time | head -n 1 | ${grep} -Eo "\S+\s+$")" seconds))"))) ]]
} boot_system_path() {
bpath=""
boot_system_path() { btime=0
bpath="" for f in /nix/var/nix/profiles/*
btime=0 do
for f in /nix/var/nix/profiles/* if [[ -z $bpath ]] || [[ $btime -lt $(${stat} -c %Y $f) ]]
do then
if [[ -z $bpath ]] || [[ $btime -lt $(${stat} -c %Y $f) ]] bpath=$f
then btime=$(${stat} -c %Y $f)
bpath=$f fi
btime=$(${stat} -c %Y $f) done
fi if [[ -d "/nix/var/nix/profiles/system-profiles/" ]] && [[ -n "$(ls -A /nix/var/nix/profiles/system-profiles/)" ]]
done then
if [[ -d "/nix/var/nix/profiles/system-profiles/" ]] && [[ -n "$(ls -A /nix/var/nix/profiles/system-profiles/)" ]] for f in /nix/var/nix/profiles/system-profiles/*
then do
for f in /nix/var/nix/profiles/system-profiles/* if [[ -z $bpath ]] || [[ $btime -lt $(${stat} -c %Y $f) ]]
do then
if [[ -z $bpath ]] || [[ $btime -lt $(${stat} -c %Y $f) ]] bpath=$f
then btime=$(${stat} -c %Y $f)
bpath=$f fi
btime=$(${stat} -c %Y $f) done
fi fi
done echo "$bpath"
fi }
echo "$bpath"
} last_update_time() {
rpath=$(${realpath} /run/current-system)
last_update_time() { rtime=$(${stat} -c %Y /run/current-system)
rpath=$(${realpath} /run/current-system) boot_system=$(boot_system_path)
rtime=$(${stat} -c %Y /run/current-system) bpath=$(${realpath} "$boot_system")
boot_system=$(boot_system_path) btime=$(${stat} -c %Y "$boot_system")
bpath=$(${realpath} "$boot_system") if [[ "''${rpath}" == "''${bpath}" ]]
btime=$(${stat} -c %Y "$boot_system") then
if [[ "''${rpath}" == "''${bpath}" ]] if ! updated_since_reboot
then then
if ! updated_since_reboot echo $btime
then return
echo $btime fi
return fi
fi if [[ $rtime -gt $btime ]]
fi then
if [[ $rtime -gt $btime ]] echo $rtime
then else
echo $rtime echo $btime
fi
}
latest_system=$(boot_system_path)
if [[ "$(${realpath} /run/booted-system)" == "$(${realpath} /run/current-system)" ]] && [[ "$(${realpath} /run/booted-system)" == "$(${realpath} "$latest_system")" ]]
then
if [[ -f /boot/grub/grub.cfg ]]
then
if [[ $(($(${date} +%s) - $(${cut} -d. -f1 /proc/uptime))) -gt $(${stat} -c %Y /boot/grub/grub.cfg) ]]
then
echo "persisting boot system"
"$(${realpath} /run/booted-system)/bin/switch-to-configuration" "boot"
fi
fi
fi
if [[ "$new_system" == "$(${realpath} /run/current-system)" ]] && [[ "$new_system" == "$(${realpath} "$latest_system")" ]]
then
echo "system is up-to-date"
exit 0
fi
system_update_time=$(last_update_time)
flake_update_time=$(last_flake_update_time "${cfg.flake}")
echo "last system update: $(${date} -d @"$system_update_time")"
echo "last flake update: $(${date} -d @"$flake_update_time")"
if [[ -z "$1" ]] && [[ "$system_update_time" -gt "$flake_update_time" ]]
then
echo ""
echo "System is newer than remote!"
echo "This happens if the system was updated manually or a system update failed."
echo "Skipping system update to prevent potential downgrade!"
exit 0
fi
echo "Updating system ..."
system_info_booted="$(${realpath} /run/booted-system/{initrd,kernel,kernel-modules})"
system_info_built="$(${realpath} "''${new_system}"/{initrd,kernel,kernel-modules})"
echo $system_info_booted
echo $system_info_built
current_time="$(${date} +%H:%M)"
lower=${cfg.rebootWindow.lower}
upper=${cfg.rebootWindow.upper}
if [[ "''${lower}" < "''${upper}" ]]; then
if [[ "''${current_time}" > "''${lower}" ]] && \
[[ "''${current_time}" < "''${upper}" ]]; then
do_reboot="true"
else else
echo $btime do_reboot="false"
fi fi
} else
# lower > upper, so we are crossing midnight (e.g. lower=23h, upper=6h)
latest_system=$(boot_system_path) # we want to reboot if cur > 23h or cur < 6h
if [[ "''${current_time}" < "''${upper}" ]] || \
[[ "''${current_time}" > "''${lower}" ]]; then
if [[ "$(${realpath} /run/booted-system)" == "$(${realpath} /run/current-system)" ]] && [[ "$(${realpath} /run/booted-system)" == "$(${realpath} "$latest_system")" ]] do_reboot="true"
then else
if [[ -f /boot/grub/grub.cfg ]] do_reboot="false"
then
if [[ $(($(${date} +%s) - $(${cut} -d. -f1 /proc/uptime))) -gt $(${stat} -c %Y /boot/grub/grub.cfg) ]]
then
echo "persisting boot system"
"$(${realpath} /run/booted-system)/bin/switch-to-configuration" "boot"
fi
fi fi
fi fi
if [[ "$new_system" == "$(${realpath} /run/current-system)" ]] && [[ "$new_system" == "$(${realpath} "$latest_system")" ]] if [[ "$system_info_booted" != "$system_info_built" ]]
then then
echo "system is up-to-date" echo "Updating system requires reboot!"
exit 0 if [ "''${do_reboot}" != true ]
fi then
echo "Outside of configured reboot window, skipping update."
system_update_time=$(last_update_time) exit 0
flake_update_time=$(last_flake_update_time "${cfg.flake}") fi
echo "last system update: $(${date} -d @"$system_update_time")" echo nix-env --profile /nix/var/nix/profiles/system --set "$new_system"
echo "last flake update: $(${date} -d @"$flake_update_time")" if [[ -f /boot/grub/grub.cfg ]]
then
if [[ "$system_update_time" -gt "$flake_update_time" ]] echo "bootloader 'GRUB' detected, configuring test-boot into new system"
then "''${latest_system}/bin/switch-to-configuration" "boot"
echo "" ${grub-reboot} "NixOS - All configurations>0"
echo "System is newer than remote!" #${grub-reboot} "NixOS - Profile '$PROFILE_NAME'>0"
echo "This happens if the system was updated manually or a system update failed." elif ${bootctl} list 2>&1 | ${grep} -v "No boot loader entries found." > /dev/null
echo "Skipping system update to prevent potential downgrade!" then
exit 0 echo "bootloader 'systemd-boot' detected, configuring oneshot-boot into new system"
fi # TODO
exit -1
echo "Updating system ..." else
echo "test-boot not supported. persisting new boot system"
system_info_booted="$(${realpath} /run/booted-system/{initrd,kernel,kernel-modules})" "''${new_system}/bin/switch-to-configuration" "boot"
system_info_built="$(${realpath} "''${new_system}"/{initrd,kernel,kernel-modules})" fi
${shutdown} -r +1
echo $system_info_booted else
echo $system_info_built nix-env --profile /nix/var/nix/profiles/system --set "$new_system"
if ! "''${new_system}/bin/switch-to-configuration" "test"
current_time="$(${date} +%H:%M)" then
echo "testing new configuration failed!"
lower=${cfg.rebootWindow.lower} echo "system was automatically rolled back to old configuration."
upper=${cfg.rebootWindow.upper} exit 1
fi
if [[ "''${lower}" < "''${upper}" ]]; then "''${new_system}/bin/switch-to-configuration" "boot"
if [[ "''${current_time}" > "''${lower}" ]] && \ fi
[[ "''${current_time}" < "''${upper}" ]]; then
do_reboot="true" if [[ "$(last_flake_update_time "${cfg.flake}")" -gt "$flake_update_time" ]]
else then
do_reboot="false" echo "flake was update after last update."
fi do_update force
else fi
# lower > upper, so we are crossing midnight (e.g. lower=23h, upper=6h) }
# we want to reboot if cur > 23h or cur < 6h do_update
if [[ "''${current_time}" < "''${upper}" ]] || \
[[ "''${current_time}" > "''${lower}" ]]; then
do_reboot="true"
else
do_reboot="false"
fi
fi
if [[ "$system_info_booted" != "$system_info_built" ]]
then
echo "Updating system requires reboot!"
if [ "''${do_reboot}" != true ]
then
echo "Outside of configured reboot window, skipping update."
exit 0
fi
echo nix-env --profile /nix/var/nix/profiles/system --set "$new_system"
if [[ -f /boot/grub/grub.cfg ]]
then
echo "bootloader 'GRUB' detected, configuring test-boot into new system"
"''${latest_system}/bin/switch-to-configuration" "boot"
${grub-reboot} "NixOS - All configurations>0"
#${grub-reboot} "NixOS - Profile '$PROFILE_NAME'>0"
elif ${bootctl} list 2>&1 | ${grep} -v "No boot loader entries found." > /dev/null
then
echo "bootloader 'systemd-boot' detected, configuring oneshot-boot into new system"
# TODO
exit -1
else
echo "test-boot not supported. persisting new boot system"
"''${new_system}/bin/switch-to-configuration" "boot"
fi
${shutdown} -r +1
else
nix-env --profile /nix/var/nix/profiles/system --set "$new_system"
if ! "''${new_system}/bin/switch-to-configuration" "test"
then
echo "testing new configuration failed!"
echo "system was automatically rolled back to old configuration."
exit 1
fi
"''${new_system}/bin/switch-to-configuration" "boot"
fi
'' ''