Put a blank line between a prompt and the text explaining it
tests / runner-env (confined) (pull_request) Failing after 1m47s
tests / tests (pull_request) Successful in 1m51s
tests / compose-schema (pull_request) Successful in 1m35s
tests / runner-env (privileged) (pull_request) Successful in 1m23s

Several prompts ran straight on from the paragraph describing them, so the
question arrived as the last line of a wall of prose rather than as something
being asked. The upstream resolver was the worst of them - four lines of
explanation and then the prompt, with nothing between - and the token entry,
the two list confirmations and the firewall unit were the same shape.

They are separated now. Eight in install.sh, five in dejima-ci-runners where
the label, count, volumes and both token prompts had the same problem, and one
in dejima-ci-static-ip where three prompts followed a paragraph with no break.

Left alone: prompts already preceded by a blank, and the per-item prompts in
the repository and domain entry loops, where a blank line between each entry
would break up a list rather than set it off.

The three trailing settings - allowlist path, ref, reload command - had no
description at all, which is its own version of the problem: three questions
with no indication that the defaults are the answer. They get a line saying so.

Checked by driving the real prompts on a pty rather than reading the source.
76 ok, 0 failed.
This commit is contained in:
Brad Anderson
2026-08-08 17:41:50 -07:00
parent d850719043
commit b7e9ed156d
3 changed files with 16 additions and 0 deletions
+5
View File
@@ -216,6 +216,7 @@ say
say "The runner label. A workflow reaches these runners by naming it in"
say "runs-on:, and no other runner on the instance may carry it - if one does,"
say "a job naming it can land there instead, on a host nothing here hardened."
say
ask label "Runner label" "${OPT_LABEL:-$default_label}"
[ -n "$label" ] || die "a label is required"
case "$label" in
@@ -235,6 +236,7 @@ if [ "$ROLE" = confined ]; then
say "of them share this label and this job network, so they are a pool: a"
say "job naming $label lands on whichever is free."
while :; do
say
ask count "Number of runners" "${OPT_COUNT:-3}"
[[ "$count" =~ ^[0-9]+$ ]] && [ "$count" -ge 1 ] && [ "$count" -le 32 ] && break
say " a whole number between 1 and 32"
@@ -262,6 +264,7 @@ if [ "$ROLE" = privileged ]; then
say
say "Type 'none' to allow no host paths at all. Pressing Enter takes the"
say "default shown, which is not the same thing."
say
ask valid_volumes "Allowed volume paths (space-separated, or none)" "${OPT_VOLUMES:-/tmp/dejima-ci}"
[ "${valid_volumes,,}" != none ] || valid_volumes=""
fi
@@ -389,6 +392,7 @@ fi
if [ -n "$existing_token" ]; then
say
say "A registration token is already in $ENV_FILE."
say
ask replace_token "Replace it? (y/N)" "n"
else
replace_token=y
@@ -422,6 +426,7 @@ fi
if [ "${replace_token,,}" = y ] || [ "${replace_token,,}" = yes ]; then
token=""
if [ "$NONINTERACTIVE" -eq 0 ]; then
say
printf 'Registration token (not echoed, Enter to skip): ' >&2
IFS= read -rs token </dev/tty || true
printf '\n' >&2
+1
View File
@@ -141,6 +141,7 @@ say "this host is reachable. What changes is that they stop depending on a DHCP"
say "lease being renewed."
say
say
ask ADDRESS "Address and prefix" "$ADDRESS"
ask GATEWAY "Gateway" "$GATEWAY"
ask NAMESERVERS "Nameserver(s)" "$NAMESERVERS"
+10
View File
@@ -341,6 +341,7 @@ probe_name="${instance#*://}"; probe_name="${probe_name%%/*}"; probe_name="${pro
: "${probe_name:=deb.debian.org}"
while :; do
say
ask upstream "Upstream resolver address" "${existing_upstream:-$(detect_upstream)}"
[ -n "$upstream" ] || die "an upstream resolver is required"
if ! command -v python3 >/dev/null 2>&1; then
@@ -405,6 +406,7 @@ say
# --- token ------------------------------------------------------------------
if [ -s "$TOKEN_FILE" ]; then
say "A forge token is already installed at $TOKEN_FILE."
say
ask replace_token "Replace it? (y/N)" "n"
else
replace_token=y
@@ -427,6 +429,7 @@ fi
if [ "${replace_token,,}" = y ] || [ "${replace_token,,}" = yes ]; then
token=""
if [ "$NONINTERACTIVE" -eq 0 ]; then
say
printf 'Forge token (not echoed): ' >&2
IFS= read -rs token </dev/tty || true
printf '\n' >&2
@@ -454,6 +457,7 @@ existing_repos=""
[ -r "$REPOS_FILE" ] && existing_repos="$(grep -vE '^\s*(#|$)' "$REPOS_FILE" || true)"
if [ -n "$existing_repos" ]; then
say "Currently:"; sed 's/^/ /' <<< "$existing_repos" >&2
say
ask keep_repos "Keep this list? (Y/n)" "y"
else
keep_repos=n
@@ -561,9 +565,11 @@ existing_base=""
default_base="${existing_base:-$forge_host$'\n'deb.debian.org}"
if [ -n "$existing_base" ]; then
say "Currently:"; sed 's/^/ /' <<< "$existing_base" >&2
say
ask keep_base "Keep this list? (Y/n)" "y"
else
say "Suggested:"; sed 's/^/ /' <<< "$default_base" >&2
say
ask keep_base "Use this list? (Y/n)" "y"
fi
if [ "${keep_base,,}" = n ] || [ "${keep_base,,}" = no ]; then
@@ -585,6 +591,9 @@ say
# --- remaining settings -----------------------------------------------------
ipset="$(cfg_get ipset)"; : "${ipset:=ci-allow}"
say "Where the generated allowlist goes, which branch is trusted, and how the"
say "resolver is reloaded. The defaults are right unless you have a reason."
say
ask_cfg out "Generated allowlist path" out /etc/dnsmasq.d/ci-allow.conf
ask_cfg ref "Branch treated as operator-approved" ref main
ask_cfg reload "Command that reloads the resolver" reload "systemctl reload dnsmasq"
@@ -671,6 +680,7 @@ if [ "$INSTALL_UNITS" -eq 1 ] && command -v systemctl >/dev/null 2>&1; then
# Docker starts. Docker recreates its own chains on every start and
# DOCKER-USER comes back empty, so "apply them once" is not an
# instruction that stays true.
say
ask enable_fw "Enable the firewall unit (reapplies rules on every Docker start)? (Y/n)" "y"
if [ "${enable_fw,,}" != n ] && [ "${enable_fw,,}" != no ]; then
systemctl enable --now dejima-ci-firewall.service