| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- #!/usr/bin/env bash
- #
- # A wizard — walks a human through a manual procedure step by step.
- # Generated by the /wizard skill.
- #
- # Everything above the "STAGES" marker is the wizard library: do not hand-edit
- # it. Author the per-step stages below the marker.
- set -euo pipefail
- # ──────────────────────────────────────────────────────────────────────────
- # Wizard library — delightful, consistent UX. Identical across every wizard.
- # ──────────────────────────────────────────────────────────────────────────
- if [[ -t 1 ]] && command -v tput >/dev/null 2>&1 && [[ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]]; then
- BOLD=$(tput bold); DIM=$(tput dim); RESET=$(tput sgr0)
- BLUE=$(tput setaf 4); GREEN=$(tput setaf 2); YELLOW=$(tput setaf 3); RED=$(tput setaf 1)
- else
- BOLD=""; DIM=""; RESET=""; BLUE=""; GREEN=""; YELLOW=""; RED=""
- fi
- # Author sets this at the top of the stages section.
- TOTAL_STAGES=0
- _STAGE_INDEX=0
- ENV_FILE="${ENV_FILE:-.env}"
- WRITTEN_ENV=() # KEYs written to ENV_FILE this run
- WRITTEN_SECRET=() # secret NAMEs set this run
- SKIPPED=() # things we couldn't do (e.g. gh missing)
- # _clear — wipe the terminal so only the current step is on screen. No-op when
- # output isn't a terminal, so piped logs stay readable.
- _clear() {
- [[ -t 1 ]] || return 0
- if command -v tput >/dev/null 2>&1; then tput clear; else printf '\033[2J\033[3J\033[H'; fi
- }
- # banner "Title" — opening frame: what this wizard does.
- banner() {
- _clear
- printf '\n%s%s %s%s\n' "$BOLD" "$BLUE" "$1" "$RESET"
- printf '%s %s stages%s\n\n' "$DIM" "$TOTAL_STAGES" "$RESET"
- printf '%s You drive the browser; this wizard tells you exactly what to do and\n' "$DIM"
- printf ' captures the values you copy back. Stop any time with Ctrl-C and re-run\n'
- printf ' later — it remembers values already saved.%s\n' "$RESET"
- pause "Ready to start?"
- }
- # stage "Name" — clear the screen, then announce a stage and show progress.
- # Clearing keeps only the current step on screen.
- stage() {
- _clear
- _STAGE_INDEX=$((_STAGE_INDEX + 1))
- printf '\n%s%s▸ Stage %s/%s · %s%s\n' \
- "$BOLD" "$BLUE" "$_STAGE_INDEX" "$TOTAL_STAGES" "$1" "$RESET"
- }
- # say "..." — a plain instruction line.
- say() { printf ' %s\n' "$1"; }
- # step "..." — a numbered-feeling action the human takes in the browser.
- step() { printf ' %s•%s %s\n' "$BLUE" "$RESET" "$1"; }
- note() { printf ' %s%s%s\n' "$DIM" "$1" "$RESET"; }
- warn() { printf ' %s⚠ %s%s\n' "$YELLOW" "$1" "$RESET"; }
- # open_url URL — open in the human's browser, cross-platform incl. WSL.
- open_url() {
- local url="$1"
- printf ' %s↗ opening%s %s\n' "$GREEN" "$RESET" "$url"
- { if command -v wslview >/dev/null 2>&1; then wslview "$url"
- elif command -v explorer.exe >/dev/null 2>&1; then explorer.exe "$url"
- elif command -v xdg-open >/dev/null 2>&1; then xdg-open "$url"
- elif command -v open >/dev/null 2>&1; then open "$url"
- else warn "couldn't open a browser — visit it manually: $url"; fi
- } >/dev/null 2>&1 || warn "couldn't open a browser — visit it manually: $url"
- }
- # pause "msg" — wait for the human to confirm they've done the manual part.
- pause() {
- printf ' %s%s%s ' "$DIM" "${1:-Press Enter to continue}" "$RESET"
- read -r _ || true
- }
- # confirm "question" — y/N gate; returns success on yes.
- confirm() {
- local reply=""
- printf ' %s? %s [y/N] ' "$YELLOW" "$1"
- read -r reply || true
- [[ "$reply" =~ ^[Yy] ]]
- }
- # _existing KEY — current value of KEY in ENV_FILE, if any.
- _existing() {
- [[ -f "$ENV_FILE" ]] || return 1
- local line; line=$(grep -E "^${1}=" "$ENV_FILE" | tail -n1) || return 1
- printf '%s' "${line#*=}"
- }
- # ask KEY "Prompt" — read a value into $KEY. Offers the existing .env value as
- # a default on re-runs (Enter keeps it). Visible input (non-secret).
- ask() {
- local key="$1" prompt="$2" current input
- current=$(_existing "$key" || true)
- if [[ -n "$current" ]]; then
- printf ' %s%s%s %s[Enter keeps current]%s ' "$BOLD" "$prompt" "$RESET" "$DIM" "$RESET"
- else
- printf ' %s%s%s ' "$BOLD" "$prompt" "$RESET"
- fi
- read -r input || true
- [[ -z "$input" && -n "$current" ]] && input="$current"
- printf -v "$key" '%s' "$input"
- }
- # ask_secret KEY "Prompt" — like ask, but input is hidden.
- ask_secret() {
- local key="$1" prompt="$2" current input
- current=$(_existing "$key" || true)
- if [[ -n "$current" ]]; then
- printf ' %s%s%s %s[Enter keeps current]%s ' "$BOLD" "$prompt" "$RESET" "$DIM" "$RESET"
- else
- printf ' %s%s%s ' "$BOLD" "$prompt" "$RESET"
- fi
- read -rs input || true
- printf '\n'
- [[ -z "$input" && -n "$current" ]] && input="$current"
- printf -v "$key" '%s' "$input"
- }
- # write_env KEY VALUE — upsert KEY=VALUE into ENV_FILE (creates it; replaces
- # any existing line). Idempotent.
- write_env() {
- local key="$1" value="$2" tmp
- touch "$ENV_FILE"
- tmp=$(mktemp)
- grep -vE "^${key}=" "$ENV_FILE" > "$tmp" || true
- printf '%s=%s\n' "$key" "$value" >> "$tmp"
- mv "$tmp" "$ENV_FILE"
- WRITTEN_ENV+=("$key")
- printf ' %s✓ wrote%s %s → %s\n' "$GREEN" "$RESET" "$key" "$ENV_FILE"
- }
- # set_secret NAME VALUE — set a GitHub Actions repo secret via gh. Falls back
- # to a warning (and records it) if gh is unavailable or unauthenticated.
- set_secret() {
- local name="$1" value="$2"
- if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
- if printf '%s' "$value" | gh secret set "$name" >/dev/null 2>&1; then
- WRITTEN_SECRET+=("$name")
- printf ' %s✓ set%s GitHub secret %s\n' "$GREEN" "$RESET" "$name"
- return
- fi
- fi
- SKIPPED+=("GitHub secret $name (set it manually: gh secret set $name)")
- warn "skipped GitHub secret $name — gh not ready; set it later"
- }
- # set_var NAME VALUE — set a GitHub Actions repo variable (non-secret).
- set_var() {
- local name="$1" value="$2"
- if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
- if gh variable set "$name" --body "$value" >/dev/null 2>&1; then
- printf ' %s✓ set%s GitHub variable %s\n' "$GREEN" "$RESET" "$name"
- return
- fi
- fi
- SKIPPED+=("GitHub variable $name")
- warn "skipped GitHub variable $name — gh not ready; set it later"
- }
- # finish — clear, then a closing summary of everything configured.
- finish() {
- _clear
- printf '\n%s%s ✓ Setup complete%s\n' "$BOLD" "$GREEN" "$RESET"
- (( ${#WRITTEN_ENV[@]} )) && note "wrote ${#WRITTEN_ENV[@]} value(s) to $ENV_FILE: ${WRITTEN_ENV[*]}"
- (( ${#WRITTEN_SECRET[@]} )) && note "set ${#WRITTEN_SECRET[@]} GitHub secret(s): ${WRITTEN_SECRET[*]}"
- if (( ${#SKIPPED[@]} )); then
- printf '\n'; warn "still to do by hand:"
- for s in "${SKIPPED[@]}"; do note " - $s"; done
- fi
- printf '\n'
- }
- # ──────────────────────────────────────────────────────────────────────────
- # STAGES — author this section. One stage() per step the human takes.
- # Replace the example below. Set TOTAL_STAGES to match the stages you write.
- # ──────────────────────────────────────────────────────────────────────────
- TOTAL_STAGES=1
- banner "Stripe setup"
- # ── Example stage: replace with your real steps ───────────────────────────
- stage "Stripe — API keys"
- say "We'll grab your Stripe test keys and store them for local dev + CI."
- open_url "https://dashboard.stripe.com/test/apikeys"
- step "On the API keys page, copy the Publishable key (starts pk_test_)."
- ask STRIPE_PUBLISHABLE_KEY "Paste the publishable key:"
- step "Click 'Reveal test key' on the Secret key row, then copy it."
- ask_secret STRIPE_SECRET_KEY "Paste the secret key:"
- write_env STRIPE_PUBLISHABLE_KEY "$STRIPE_PUBLISHABLE_KEY"
- write_env STRIPE_SECRET_KEY "$STRIPE_SECRET_KEY"
- set_secret STRIPE_SECRET_KEY "$STRIPE_SECRET_KEY" # CI needs this one
- # ──────────────────────────────────────────────────────────────────────────
- finish
|