From 44d43f2b42993d8f06560ff099492d6f91becab1 Mon Sep 17 00:00:00 2001 From: juvdiaz Date: Wed, 1 Jul 2026 08:34:36 -0600 Subject: [PATCH] Show compact progress for long Jeannie steps --- README.md | 5 +++ README.md.tmpl | 5 +++ docs/jeannie.1.md | 5 +++ jeannie | 88 +++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 92 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f42c0b7..1fd8ed8 100644 --- a/README.md +++ b/README.md @@ -714,6 +714,11 @@ Worker indexes are stable. Index `1` maps to VMID `9010`, node name so on. `LAB_PIMOX_SKIP_WORKER_INDEXES=1` leaves the first slot unmanaged while allowing higher indexes to be automated. +Long-running `./jeannie up` steps keep compact output by default, but +the active step line refreshes with elapsed time and the latest log line. Set +`JEANNIE_PROGRESS_INTERVAL_SECONDS=5` for faster heartbeats, or +`JEANNIE_VERBOSE=true` to stream full command output. + Run a full cluster rebuild from the Debian server with: ```bash diff --git a/README.md.tmpl b/README.md.tmpl index 9de04e8..5b567d4 100644 --- a/README.md.tmpl +++ b/README.md.tmpl @@ -714,6 +714,11 @@ Worker indexes are stable. Index `1` maps to VMID `9010`, node name so on. `LAB_PIMOX_SKIP_WORKER_INDEXES=1` leaves the first slot unmanaged while allowing higher indexes to be automated. +Long-running `./{{ main_script }} up` steps keep compact output by default, but +the active step line refreshes with elapsed time and the latest log line. Set +`JEANNIE_PROGRESS_INTERVAL_SECONDS=5` for faster heartbeats, or +`JEANNIE_VERBOSE=true` to stream full command output. + Run a full cluster rebuild from the Debian server with: ```bash diff --git a/docs/jeannie.1.md b/docs/jeannie.1.md index 3fbda33..1dab753 100644 --- a/docs/jeannie.1.md +++ b/docs/jeannie.1.md @@ -482,6 +482,11 @@ Defaults to `85`. : Print full step output as it runs. Without this, noisy commands are compact and full output is written to the log file. +`JEANNIE_PROGRESS_INTERVAL_SECONDS` +: Refresh interval for compact long-running step progress lines. Defaults to +`10`. Compact steps show elapsed time and the latest sanitized log line while +the full output continues writing to the log file. + `LAB_STATUS_DETAILS=true` : With `status --verbose`, append detailed host, Docker, Kubernetes, Pimox, RPi, Tailscale, and HTTP tables after the normal status cascade. diff --git a/jeannie b/jeannie index dac204d..588bb5c 100755 --- a/jeannie +++ b/jeannie @@ -796,6 +796,51 @@ jeannie_verbose_enabled() { truthy "${JEANNIE_VERBOSE:-false}" } +jeannie_step_prefix() { + local description="$1" + + if ((JEANNIE_STEP_TOTAL > 0)); then + printf '[%d/%d] %-42s ' "${JEANNIE_STEP_INDEX}" "${JEANNIE_STEP_TOTAL}" "${description}" + else + printf '[%d] %-46s ' "${JEANNIE_STEP_INDEX}" "${description}" + fi +} + +jeannie_compact_text() { + local text="$1" + local max_length="${2:-96}" + + text="${text//$'\r'/ }" + text="${text//$'\n'/ }" + text="$(printf '%s' "${text}" | sed -E 's/[[:space:]]+/ /g; s/^ //; s/ $//')" + if ((${#text} > max_length)); then + text="${text:0:max_length - 3}..." + fi + printf '%s' "${text}" +} + +jeannie_step_progress() { + local description="$1" + local step_log="$2" + local started_at="$3" + local elapsed=$((SECONDS - started_at)) + local last_line="" + + if [[ -s "${step_log}" ]]; then + last_line="$(tail -n 1 "${step_log}" 2>/dev/null || true)" + last_line="$(jeannie_compact_text "${last_line}" 88)" + fi + + printf '\r' + jeannie_step_prefix "${description}" + if [[ -n "${last_line}" ]]; then + printf 'running %ss | %s' "${elapsed}" "${last_line}" + else + printf 'running %ss' "${elapsed}" + fi + printf '\033[K' +} + redact_sensitive_output() { sed -E \ -e 's/(GITEA_BOOTSTRAP_PASSWORD=)["'\'']?[^"'\''[:space:]]+["'\'']?/\1[REDACTED]/g' \ @@ -812,17 +857,18 @@ redact_sensitive_output() { run_step() { local description="$1" local step_log + local status_file local status + local progress_pid + local progress_interval="${JEANNIE_PROGRESS_INTERVAL_SECONDS:-10}" + local started_at shift JEANNIE_STEP_INDEX=$((JEANNIE_STEP_INDEX + 1)) - if ((JEANNIE_STEP_TOTAL > 0)); then - printf '[%d/%d] %-42s ' "${JEANNIE_STEP_INDEX}" "${JEANNIE_STEP_TOTAL}" "${description}" - else - printf '[%d] %-46s ' "${JEANNIE_STEP_INDEX}" "${description}" - fi + jeannie_step_prefix "${description}" step_log="$(mktemp)" + status_file="$(mktemp)" { printf '\n== [%d/%d] %s ==\n' "${JEANNIE_STEP_INDEX}" "${JEANNIE_STEP_TOTAL}" "${description}" printf 'Started: %s\n' "$(date -Is)" @@ -835,8 +881,24 @@ run_step() { set -e else set +e - "$@" 2>&1 | redact_sensitive_output >"${step_log}" - status=${PIPESTATUS[0]} + ( + set +e + "$@" 2>&1 | redact_sensitive_output >"${step_log}" + printf '%s\n' "${PIPESTATUS[0]}" >"${status_file}" + ) & + progress_pid=$! + if ! [[ "${progress_interval}" =~ ^[0-9]+$ ]] || ((progress_interval < 1)); then + progress_interval=10 + fi + started_at="${SECONDS}" + while kill -0 "${progress_pid}" >/dev/null 2>&1; do + sleep "${progress_interval}" + if kill -0 "${progress_pid}" >/dev/null 2>&1; then + jeannie_step_progress "${description}" "${step_log}" "${started_at}" + fi + done + wait "${progress_pid}" || true + status="$(cat "${status_file}" 2>/dev/null || printf '1')" set -e fi @@ -844,18 +906,22 @@ run_step() { printf 'Finished: %s\n' "$(date -Is)" >>"${JEANNIE_LOG_FILE}" if ((status == 0)); then - printf 'ok\n' - rm -f "${step_log}" + printf '\r' + jeannie_step_prefix "${description}" + printf 'ok\033[K\n' + rm -f "${step_log}" "${status_file}" return 0 fi - printf 'failed\n\n' + printf '\r' + jeannie_step_prefix "${description}" + printf 'failed\033[K\n\n' printf 'Step failed: %s\n' "${description}" >&2 printf 'Exit status: %s\n' "${status}" >&2 printf 'Full step output:\n' >&2 sed 's/^/ /' "${step_log}" >&2 printf '\nFull log: %s\n' "${JEANNIE_LOG_FILE}" >&2 - rm -f "${step_log}" + rm -f "${step_log}" "${status_file}" return "${status}" }