#!/usr/bin/env bash # Everything Panama needs to be told, asked before anything is installed. # # sunhat's failure mode was a question -- or a failure -- twenty minutes into a # run, with a person needed at the keyboard to get past it. Walking away from an # install meant coming back to a prompt that had been waiting an hour. # # So Panama asks first and then runs untouched. Everything interactive lives # here, at the front, where the answers are cheap to change and nothing has been # installed yet. # # Answers are NOT remembered between runs. There is no state file to go stale, and # nothing personal is committed, which is what keeps this repository something # somebody else could clone. Re-answering a handful of questions costs less than # maintaining an answers file that drifts out of date. # # This asks only what a stage in this repository actually consumes. Extras, # hardware and debloat questions arrive with the stages that act on them; a prompt # whose answer nothing reads is a control that lies. set -uo pipefail # install passes the path. Refusing to guess one keeps the answers where the # caller can delete them, rather than somewhere this script invented. answers="${PANAMA_ANSWERS:-}" [[ -n "$answers" ]] || { printf 'interview: PANAMA_ANSWERS is not set; run this through ./install\n' >&2; exit 1; } : >"$answers" # %q so a value containing a space, a quote or a dollar sign survives being # sourced by install exactly as it was typed. record() { printf '%s=%q\n' "$1" "$2" >>"$answers"; } heading() { gum style --bold --foreground 4 "$1"; } ask() { gum input --header "$1" --placeholder "${2:-}"; } yes_no() { gum confirm --default=false "$1"; } # ── Machine ────────────────────────────────────────────────────────────────── heading "This machine" current_hostname="$(hostname)" printf 'Current hostname: %s\n' "$current_hostname" new_hostname="" if yes_no "Change the hostname?"; then new_hostname="$(ask "Hostname" "$current_hostname")" fi record PANAMA_HOSTNAME "$new_hostname" # ── Identity ───────────────────────────────────────────────────────────────── # # Left blank, each of these keeps whatever git already has. That matters on a # re-run: the prompts start empty every time by design, and an empty answer must # not wipe a name that was already correct. heading "Git identity" printf 'Leave any of these blank to keep the current setting.\n' git_name="$(ask "Git user.name")" git_email="$(ask "Git user.email")" git_editor="$(ask "Git editor" "nvim")" record PANAMA_GIT_NAME "$git_name" record PANAMA_GIT_EMAIL "$git_email" record PANAMA_GIT_EDITOR "$git_editor" # ── Accounts and keys ──────────────────────────────────────────────────────── # # These two are asked only when they would do something. Checking whether a # credential already exists is not the same as remembering a previous answer -- # it is refusing to ask a question whose answer is already on the machine. heading "Accounts" gh_login=no if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then printf 'GitHub CLI is already signed in.\n' elif yes_no "Sign in to GitHub after packages are installed?"; then gh_login=yes fi record PANAMA_GH_LOGIN "$gh_login" ssh_key=no if compgen -G "$HOME/.ssh/id_*.pub" >/dev/null 2>&1; then printf 'An SSH key already exists.\n' elif yes_no "Generate an SSH key?"; then ssh_key=yes fi record PANAMA_SSH_KEY "$ssh_key" # ── Confirm ────────────────────────────────────────────────────────────────── # # The last chance to catch a typo before twenty minutes of package work that # nobody is watching. shown() { [[ -n "$1" ]] && printf '%s' "$1" || printf 'unchanged'; } heading "Ready" gum style --border rounded --padding "0 1" "$( printf 'Hostname %s\n' "${new_hostname:-"$current_hostname (unchanged)"}" printf 'Git name %s\n' "$(shown "$git_name")" printf 'Git email %s\n' "$(shown "$git_email")" printf 'Git editor %s\n' "$(shown "$git_editor")" printf 'GitHub %s\n' "$([[ "$gh_login" == yes ]] && echo "sign in" || echo "no change")" printf 'SSH key %s' "$([[ "$ssh_key" == yes ]] && echo "generate" || echo "no change")" )" if ! gum confirm --default=true "Install with these answers?"; then printf 'interview: cancelled; nothing was installed.\n' >&2 exit 1 fi