Created
April 28, 2026 16:24
-
-
Save otherwiseguy/441ac95e69a7b86f04d11b2f460b4eb4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Default to 3 day warning time just to give a heads-up before a weekend | |
| WARN_HOURS=${DNEST_WARN_HOURS:-72} | |
| # For testing purposes, let a leading 0 signify minutes so we can warn almost immediately | |
| if [[ "$WARN_HOURS" == 0* ]]; then | |
| WARN_UNIT=minutes | |
| WARN_VAL=${WARN_HOURS#0} | |
| else | |
| WARN_UNIT=hours | |
| WARN_VAL=$WARN_HOURS | |
| fi | |
| # Normalise to minutes for internal scheduling | |
| WARN_MINS=$(( WARN_UNIT == "minutes" ? WARN_VAL : WARN_VAL * 60 )) | |
| ATJOB_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/dnest | |
| mkdir -p "$ATJOB_DIR" | |
| cancel_warning() { | |
| local atjob_file="$ATJOB_DIR/$1" | |
| [ -f "$atjob_file" ] && atrm "$(cat "$atjob_file")" 2>/dev/null && rm -f "$atjob_file" | |
| } | |
| # Schedule a warning at warn_minutes from now | |
| schedule_warning() { | |
| local machine="$1" | |
| local warn_minutes="$2" | |
| cancel_warning "$machine" | |
| if (( warn_minutes > 0 )); then | |
| local job_id | |
| job_id=$(echo "notify-send -u critical 'DevNest Warning' 'Reservation for $machine expires in ${WARN_VAL} ${WARN_UNIT}'" \ | |
| | at now + ${warn_minutes} minutes 2>&1 | awk '/^job/ {print $2}') | |
| [ -n "$job_id" ] && echo "$job_id" > "$ATJOB_DIR/$machine" | |
| fi | |
| } | |
| usage() { | |
| cat <<EOF | |
| Usage: dnest [SUBCOMMAND] [OPTIONS] MACHINE | |
| A wrapper around devnest that schedules a GNOME notification before your | |
| reservation expires. All unrecognised subcommands are passed through to devnest. | |
| Subcommands: | |
| reserve (default) Reserve a machine. Same as omitting the subcommand. | |
| extend Extend an existing reservation. | |
| release Release a machine and cancel any pending warning. | |
| <anything else> Passed through directly to devnest. | |
| Options (reserve): | |
| -g GROUP Node group (required by devnest) | |
| -t TIME Reservation length in hours | |
| -j Output node info as JSON | |
| -f Force reserve even if a CI job is running | |
| Options (extend): | |
| -t TIME Number of hours to extend by | |
| Warning behaviour: | |
| A persistent GNOME notification is sent DNEST_WARN_HOURS before the | |
| reservation expires (default: 72h). If you extend or release, any | |
| previously scheduled warning is cancelled and rescheduled as needed. | |
| DNEST_WARN_HOURS Override the warning lead time (default: 72). | |
| A value with a leading zero is treated as minutes, | |
| which is useful for testing, e.g.: | |
| DNEST_WARN_HOURS=059 -> warn 59 minutes before expiry | |
| Examples: | |
| dnest -g network -t 240 myhost | |
| dnest reserve -g network -t 240 myhost | |
| dnest extend -t 120 myhost | |
| dnest release myhost | |
| dnest list -g network | |
| DNEST_WARN_HOURS=059 dnest -g network -t1 myhost # test: warn in 1 min | |
| EOF | |
| } | |
| ACTION="${1}" | |
| case "$ACTION" in | |
| -h | --help) | |
| usage | |
| exit 0 | |
| ;; | |
| extend) | |
| shift | |
| while getopts ":t:" opt; do | |
| case "$opt" in | |
| t) ;; | |
| esac | |
| done | |
| machine="${@: -1}" | |
| output=$(devnest extend "$@" 2>&1) | |
| echo "$output" | |
| if echo "$output" | grep -q "reserved until"; then | |
| end_time=$(echo "$output" | grep -oP 'reserved until: \K[\d/]+, [\d:]+' | tr '/' '-' | tr -d ',') | |
| end_epoch=$(date -d "$end_time" +%s) | |
| remaining_minutes=$(( (end_epoch - $(date +%s)) / 60 )) | |
| [ -n "$machine" ] && schedule_warning "$machine" $(( remaining_minutes - WARN_MINS )) | |
| fi | |
| ;; | |
| reserve | -* | "") | |
| [ "$ACTION" = "reserve" ] && shift | |
| res_time="" | |
| while getopts ":t:g:jf" opt; do | |
| case "$opt" in | |
| t) res_time=$OPTARG ;; | |
| esac | |
| done | |
| machine="${@: -1}" | |
| if devnest reserve "$@"; then | |
| [ -n "$res_time" ] && [ -n "$machine" ] && \ | |
| schedule_warning "$machine" $(( res_time * 60 - WARN_MINS )) | |
| fi | |
| ;; | |
| release) | |
| machine="${@: -1}" | |
| if devnest "$@"; then | |
| cancel_warning "$machine" | |
| fi | |
| ;; | |
| *) | |
| devnest "$@" | |
| ;; | |
| esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment