Add bin/repo timers: release timer and queue status at a glance
Wraps systemctl list-timers with the things you actually want when checking on the build host: per-unit enabled state, last run and whether it succeeded, which channels have builds queued (state files), whether the release lock is held by a live process, and any failed units. Units are discovered from systemd/*.timer so the report cannot drift from what setup installs. It forwards over ssh like the other host commands, so the build box's timer state is one command away from a workstation (--local to inspect this machine).
This commit is contained in:
@@ -737,6 +737,16 @@ All channel-mutating runs share a host-wide release lock
|
||||
(`pkgs.omarchy.org/.release.lock`), so overlapping timers and manual runs
|
||||
serialize instead of interleaving.
|
||||
|
||||
Check on all of it with `bin/repo timers` — schedule, each unit's last run and
|
||||
whether it succeeded, what is queued, whether a release is running right now,
|
||||
and any failed units. Like the other host commands it forwards over ssh, so
|
||||
the build box's state is one command away from any machine:
|
||||
|
||||
```bash
|
||||
bin/repo timers # runs on the repository host when one is configured
|
||||
bin/repo timers --local # inspect this machine instead
|
||||
```
|
||||
|
||||
State files are stored in `/root/.state/`:
|
||||
- `.sync-needed-edge`
|
||||
- `.sync-needed-rc`
|
||||
|
||||
@@ -23,7 +23,7 @@ source "$BUILD_ROOT/helpers/host-helpers.sh"
|
||||
#
|
||||
# Local-machine workflows (list, push, deploy, setup) never forward: push and
|
||||
# deploy exist precisely to move local builds TO the host.
|
||||
FORWARDABLE=" release build sign promote update clean migrate advance bootstrap-rc remove sync "
|
||||
FORWARDABLE=" release build sign promote update clean migrate advance bootstrap-rc remove sync timers "
|
||||
|
||||
LOCAL_OVERRIDE=false
|
||||
STRIPPED_ARGS=()
|
||||
@@ -109,6 +109,7 @@ show_usage() {
|
||||
echo " push Upload local builds to the repository host and publish them there"
|
||||
echo " deploy Build locally, then push: one command from a build machine"
|
||||
echo " setup Install everything the repository host needs"
|
||||
echo " timers Show release timer schedule, last runs, and queued builds"
|
||||
echo ""
|
||||
echo "Typical workflows:"
|
||||
echo " $0 release # Complete release workflow"
|
||||
@@ -202,6 +203,11 @@ setup)
|
||||
"$SCRIPT_DIR/setup" "$@" 2>&1 | tee "$LOG_FILE"
|
||||
exit ${PIPESTATUS[0]}
|
||||
;;
|
||||
timers)
|
||||
# Status output, not a build step: show it, do not log it.
|
||||
"$SCRIPT_DIR/timers" "$@"
|
||||
exit $?
|
||||
;;
|
||||
-h | --help | help)
|
||||
show_usage
|
||||
;;
|
||||
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/bin/bash
|
||||
# Show the release timers: schedule, last run and its result, what is queued,
|
||||
# and what is running right now.
|
||||
#
|
||||
# Through bin/repo this forwards to the repository host, so the build box's
|
||||
# state is one command away from any machine.
|
||||
|
||||
set -e
|
||||
|
||||
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
|
||||
source "$BUILD_ROOT/helpers/message-helpers.sh"
|
||||
source "$BUILD_ROOT/helpers/paths.sh"
|
||||
|
||||
STATE_DIR="${OMARCHY_STATE_DIR:-/root/.state}"
|
||||
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
echo "Usage: $0"
|
||||
echo ""
|
||||
echo "Reports each omarchy release timer's schedule, last run and result,"
|
||||
echo "any queued builds, and whether a release is running now."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
print_header "Omarchy Release Timers"
|
||||
|
||||
if ! command -v systemctl >/dev/null 2>&1; then
|
||||
print_warning "systemctl not found — timers live on the repository host"
|
||||
echo "Run this against the host: bin/repo timers (with OMARCHY_REPO_HOST or .repo-host set)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Discover units from the repo so this never drifts from what setup installs.
|
||||
UNITS=()
|
||||
for unit in "$BUILD_ROOT"/systemd/*.timer; do
|
||||
[[ -e "$unit" ]] || continue
|
||||
UNITS+=("$(basename "$unit" .timer)")
|
||||
done
|
||||
|
||||
if [[ ${#UNITS[@]} -eq 0 ]]; then
|
||||
print_warning "No timer units found in $BUILD_ROOT/systemd"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- schedule ----------------------------------------------------------------
|
||||
|
||||
print_info "Schedule"
|
||||
if ! systemctl list-timers --all 'omarchy-*' --no-pager 2>/dev/null | sed '/^$/d;s/^/ /'; then
|
||||
echo " (could not read timers)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- per-unit state ----------------------------------------------------------
|
||||
|
||||
print_info "Units"
|
||||
for unit in "${UNITS[@]}"; do
|
||||
# systemctl prints "not-found" AND exits nonzero, so a || fallback would
|
||||
# append a second line and wreck the alignment. Take its output as-is.
|
||||
enabled=$(systemctl is-enabled "$unit.timer" 2>/dev/null || true)
|
||||
enabled=${enabled:-unknown}
|
||||
service_state=$(systemctl is-active "$unit.service" 2>/dev/null || true)
|
||||
result=$(systemctl show "$unit.service" -p Result --value 2>/dev/null || true)
|
||||
exit_status=$(systemctl show "$unit.service" -p ExecMainStatus --value 2>/dev/null || true)
|
||||
finished=$(systemctl show "$unit.service" -p ExecMainExitTimestamp --value 2>/dev/null || true)
|
||||
|
||||
case "$enabled" in
|
||||
enabled) mark="✓" ;;
|
||||
not-found | unknown) mark="✗" ;;
|
||||
*) mark="⚠" ;;
|
||||
esac
|
||||
|
||||
printf ' %s %-28s timer:%-14s' "$mark" "$unit" "$enabled"
|
||||
|
||||
if [[ "$service_state" == "activating" || "$service_state" == "active" ]]; then
|
||||
printf 'RUNNING NOW\n'
|
||||
elif [[ -z "$finished" ]]; then
|
||||
printf 'never run\n'
|
||||
elif [[ "$result" == "success" && "$exit_status" == "0" ]]; then
|
||||
printf 'last: ok (%s)\n' "$finished"
|
||||
else
|
||||
printf 'last: FAILED [%s/exit %s] (%s)\n' "${result:-unknown}" "${exit_status:-?}" "$finished"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
# --- queued work -------------------------------------------------------------
|
||||
|
||||
print_info "Queued builds (state files in $STATE_DIR)"
|
||||
queued=false
|
||||
for channel in edge rc stable; do
|
||||
state_file="$STATE_DIR/.sync-needed-$channel"
|
||||
if [[ -f "$state_file" ]]; then
|
||||
queued=true
|
||||
since=$(date -r "$state_file" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "unknown")
|
||||
printf ' • %-7s queued since %s\n' "$channel" "$since"
|
||||
fi
|
||||
done
|
||||
[[ "$queued" == false ]] && echo " (nothing queued — all channels up to date)"
|
||||
echo ""
|
||||
|
||||
# --- release lock ------------------------------------------------------------
|
||||
|
||||
print_info "Release lock"
|
||||
lock_file="$REPO_ROOT/.release.lock"
|
||||
if [[ -s "$lock_file" ]]; then
|
||||
holder=$(tail -1 "$lock_file" 2>/dev/null)
|
||||
# A recorded holder whose process is gone is a leftover, not a live release.
|
||||
pid=$(sed -n 's/^pid \([0-9]\+\).*/\1/p' <<<"$holder")
|
||||
if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
|
||||
print_warning "HELD — $holder"
|
||||
else
|
||||
echo " free (last holder: $holder)"
|
||||
fi
|
||||
else
|
||||
echo " free"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- recent failures ---------------------------------------------------------
|
||||
|
||||
failed=$(systemctl list-units --failed --no-legend 'omarchy-*' 2>/dev/null | sed 's/^/ /')
|
||||
if [[ -n "$failed" ]]; then
|
||||
print_error "Failed units"
|
||||
echo "$failed"
|
||||
echo ""
|
||||
echo " Logs: journalctl -u <unit> -n 50"
|
||||
fi
|
||||
|
||||
print_info "Full logs: journalctl -u omarchy-auto-release-<channel> -n 50"
|
||||
Reference in New Issue
Block a user