feat(install): interactive environment setup (URLs + secrets)
- prompt TRACKER_URL (visible, current value as default) and JIRA_TOKEN/GITLAB_TOKEN/provider key (hidden read -rs, never echoed) via /dev/tty (works under curl|bash) - persist to ~/.config/pi-kit/env.sh (umask 077 => chmod 600), sourced from shell rc via idempotent managed block - ask provider key only if none already set; empty input keeps existing value; re-runs load stored values as defaults - non-interactive / PI_KIT_SETUP_ENV=0 falls back to printed guidance - README documents the flow, env.sh, and the skip switch Unit-tested: single-quote escaping round-trip, 600 perms, empty-value omission, rc-block idempotency.
This commit is contained in:
@@ -17,11 +17,15 @@ curl -fsSL https://git.codelab.vc/ai/pi-kit/-/raw/main/install.sh | bash
|
|||||||
```
|
```
|
||||||
|
|
||||||
Скрипт проверит Node.js (>= 20), поставит Pi (если нет), установит этот пакет, **спросит
|
Скрипт проверит Node.js (>= 20), поставит Pi (если нет), установит этот пакет, **спросит
|
||||||
твой профиль**, поставит нужные скилы и подскажет, какие переменные окружения нужны
|
твой профиль**, поставит нужные скилы и **интерактивно настроит окружение** (`TRACKER_URL`,
|
||||||
(ключ вашего LLM-провайдера, `TRACKER_URL`, `JIRA_TOKEN`).
|
`JIRA_TOKEN`, `GITLAB_TOKEN`, ключ LLM-провайдера). Секреты вводятся скрыто и сохраняются в
|
||||||
|
`~/.config/pi-kit/env.sh` (`chmod 600`), который подключается из твоего `~/.zshrc`/`~/.bashrc`.
|
||||||
Pi провайдер-агностичен — модель/провайдера пакет не навязывает, каждый выбирает свой
|
Pi провайдер-агностичен — модель/провайдера пакет не навязывает, каждый выбирает свой
|
||||||
(Anthropic, OpenAI, OpenRouter, …).
|
(Anthropic, OpenAI, OpenRouter, …).
|
||||||
|
|
||||||
|
Пропустить интерактивную настройку окружения: `PI_KIT_SETUP_ENV=0`. Значения потом можно
|
||||||
|
поменять прямо в `~/.config/pi-kit/env.sh` или перезапустив `./install.sh`.
|
||||||
|
|
||||||
Профиль можно задать заранее (для CI/неинтерактивной установки):
|
Профиль можно задать заранее (для CI/неинтерактивной установки):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
132
install.sh
132
install.sh
@@ -187,10 +187,17 @@ if [ "${#PROFILE_PUBLIC[@]}" -gt 0 ]; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- 7. Provider API keys ---------------------------------------------------
|
# --- 7. Environment (URLs + secrets) ---------------------------------------
|
||||||
# Pi is provider-agnostic: engineers use different LLM providers (Anthropic,
|
# Interactive setup: prompts (via /dev/tty so it works under curl | bash),
|
||||||
# OpenAI, OpenRouter, Google, ...). The package does NOT pin a provider/model.
|
# stores chosen values in ~/.config/pi-kit/env.sh (chmod 600) and sources it
|
||||||
# We only check that *some* provider key is present and hint if none is.
|
# from the shell rc. Secrets are read hidden and never echoed/logged.
|
||||||
|
# URLs have no package default yet (config/company.json is filled by maintainers);
|
||||||
|
# the current value is offered as the default. Skip with PI_KIT_SETUP_ENV=0.
|
||||||
|
CONFIG_DIR="$HOME/.config/pi-kit"
|
||||||
|
ENV_FILE="$CONFIG_DIR/env.sh"
|
||||||
|
RC_MARK=">>> pi-kit >>>"
|
||||||
|
|
||||||
|
# Which provider key (if any) is already present in the environment.
|
||||||
PROVIDER_KEYS=(ANTHROPIC_API_KEY OPENAI_API_KEY OPENROUTER_API_KEY GEMINI_API_KEY GOOGLE_API_KEY GROQ_API_KEY)
|
PROVIDER_KEYS=(ANTHROPIC_API_KEY OPENAI_API_KEY OPENROUTER_API_KEY GEMINI_API_KEY GOOGLE_API_KEY GROQ_API_KEY)
|
||||||
found_key=""
|
found_key=""
|
||||||
for k in "${PROVIDER_KEYS[@]}"; do
|
for k in "${PROVIDER_KEYS[@]}"; do
|
||||||
@@ -199,21 +206,109 @@ for k in "${PROVIDER_KEYS[@]}"; do
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ -n "$found_key" ]; then
|
|
||||||
info "Найден ключ LLM-провайдера: ${found_key} — ок."
|
|
||||||
else
|
|
||||||
warn "Не найден ни один ключ LLM-провайдера."
|
|
||||||
cat <<'EOF'
|
|
||||||
Pi работает с разными провайдерами — выбери свой и задай ключ, например:
|
|
||||||
export ANTHROPIC_API_KEY="..." # Anthropic
|
|
||||||
export OPENAI_API_KEY="..." # OpenAI
|
|
||||||
export OPENROUTER_API_KEY="..." # OpenRouter
|
|
||||||
Провайдер и модель выбираются флагами --provider/--model или в настройках Pi
|
|
||||||
(см. `pi --list-models`) — пакет их не навязывает.
|
|
||||||
|
|
||||||
Для скилла работы с трекером также понадобятся:
|
detect_rc() {
|
||||||
export TRACKER_URL="..." # адрес Jira (или возьмётся из корп. контекста)
|
case "$(basename "${SHELL:-}")" in
|
||||||
export JIRA_TOKEN="..." # Jira personal access token (Server/DC)
|
zsh) echo "$HOME/.zshrc" ;;
|
||||||
|
bash) echo "$HOME/.bashrc" ;;
|
||||||
|
*) echo "$HOME/.profile" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Escape a value for safe embedding inside single quotes.
|
||||||
|
esc_sq() { printf "%s" "$1" | sed "s/'/'\\\\''/g"; }
|
||||||
|
|
||||||
|
env_setup_interactive() {
|
||||||
|
info "Настройка окружения — значения сохранятся в ${ENV_FILE} (chmod 600)."
|
||||||
|
# Load previously stored values so re-runs keep them as defaults.
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
[ -f "$ENV_FILE" ] && . "$ENV_FILE" || true
|
||||||
|
|
||||||
|
local tracker="${TRACKER_URL:-}" jira="${JIRA_TOKEN:-}" gitlab="${GITLAB_TOKEN:-}" ans=""
|
||||||
|
|
||||||
|
# TRACKER_URL (not a secret): visible prompt, current value as default.
|
||||||
|
printf 'TRACKER_URL (адрес Jira)%s: ' "${tracker:+ [${tracker}]}" >/dev/tty
|
||||||
|
read -r ans </dev/tty || ans=""
|
||||||
|
[ -n "$ans" ] && tracker="$ans"
|
||||||
|
|
||||||
|
# JIRA_TOKEN (secret): hidden input; empty keeps the current value.
|
||||||
|
printf 'JIRA_TOKEN (скрытый ввод, Enter — оставить как есть): ' >/dev/tty
|
||||||
|
read -rs ans </dev/tty || ans=""
|
||||||
|
printf '\n' >/dev/tty
|
||||||
|
[ -n "$ans" ] && jira="$ans"
|
||||||
|
|
||||||
|
# GITLAB_TOKEN (secret, для create-mr.sh): hidden input.
|
||||||
|
printf 'GITLAB_TOKEN (скрытый ввод, Enter — пропустить): ' >/dev/tty
|
||||||
|
read -rs ans </dev/tty || ans=""
|
||||||
|
printf '\n' >/dev/tty
|
||||||
|
[ -n "$ans" ] && gitlab="$ans"
|
||||||
|
|
||||||
|
# LLM provider key — only ask if none is already set.
|
||||||
|
local prov_name="" prov_val=""
|
||||||
|
if [ -z "$found_key" ]; then
|
||||||
|
printf 'LLM-провайдер: 1) anthropic 2) openai 3) openrouter 4) пропустить [1-4]: ' >/dev/tty
|
||||||
|
read -r ans </dev/tty || ans=""
|
||||||
|
case "$ans" in
|
||||||
|
1 | anthropic) prov_name=ANTHROPIC_API_KEY ;;
|
||||||
|
2 | openai) prov_name=OPENAI_API_KEY ;;
|
||||||
|
3 | openrouter) prov_name=OPENROUTER_API_KEY ;;
|
||||||
|
*) prov_name="" ;;
|
||||||
|
esac
|
||||||
|
if [ -n "$prov_name" ]; then
|
||||||
|
printf '%s (скрытый ввод): ' "$prov_name" >/dev/tty
|
||||||
|
read -rs prov_val </dev/tty || prov_val=""
|
||||||
|
printf '\n' >/dev/tty
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Write env file with restrictive permissions (umask 077 => 600).
|
||||||
|
mkdir -p "$CONFIG_DIR"
|
||||||
|
(
|
||||||
|
umask 077
|
||||||
|
{
|
||||||
|
echo "# Managed by pi-kit install.sh — не коммить. chmod 600, plaintext."
|
||||||
|
[ -n "$tracker" ] && echo "export TRACKER_URL='$(esc_sq "$tracker")'"
|
||||||
|
[ -n "$jira" ] && echo "export JIRA_TOKEN='$(esc_sq "$jira")'"
|
||||||
|
[ -n "$gitlab" ] && echo "export GITLAB_TOKEN='$(esc_sq "$gitlab")'"
|
||||||
|
[ -n "$prov_name" ] && [ -n "$prov_val" ] && echo "export ${prov_name}='$(esc_sq "$prov_val")'"
|
||||||
|
} >"$ENV_FILE"
|
||||||
|
)
|
||||||
|
chmod 600 "$ENV_FILE"
|
||||||
|
info "Сохранено: ${ENV_FILE}"
|
||||||
|
|
||||||
|
# Ensure the shell rc sources the env file (managed block, idempotent).
|
||||||
|
local rc
|
||||||
|
rc="$(detect_rc)"
|
||||||
|
if [ -f "$rc" ] && grep -qF "$RC_MARK" "$rc" 2>/dev/null; then
|
||||||
|
info "Подключение уже есть в ${rc}."
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo ""
|
||||||
|
echo "# ${RC_MARK}"
|
||||||
|
echo '[ -f "$HOME/.config/pi-kit/env.sh" ] && . "$HOME/.config/pi-kit/env.sh"'
|
||||||
|
echo "# <<< pi-kit <<<"
|
||||||
|
} >>"$rc"
|
||||||
|
info "Добавил подключение в ${rc}. Применить сейчас: source ${rc}"
|
||||||
|
fi
|
||||||
|
warn "Токены лежат в ${ENV_FILE} (chmod 600, plaintext). Для строгих требований — секрет-менеджер."
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "${PI_KIT_SETUP_ENV:-1}" != 0 ] && [ -r /dev/tty ]; then
|
||||||
|
env_setup_interactive
|
||||||
|
else
|
||||||
|
# Non-interactive fallback: just check for a provider key and print guidance.
|
||||||
|
if [ -n "$found_key" ]; then
|
||||||
|
info "Найден ключ LLM-провайдера: ${found_key} — ок."
|
||||||
|
else
|
||||||
|
warn "Не найден ключ LLM-провайдера (установка неинтерактивная — пропускаю настройку)."
|
||||||
|
fi
|
||||||
|
cat <<'EOF'
|
||||||
|
Задай нужные переменные вручную (например, в ~/.config/pi-kit/env.sh):
|
||||||
|
export ANTHROPIC_API_KEY="..." # или OPENAI_API_KEY / OPENROUTER_API_KEY
|
||||||
|
export TRACKER_URL="..." # адрес Jira (Server/DC)
|
||||||
|
export JIRA_TOKEN="..." # Jira personal access token
|
||||||
|
export GITLAB_TOKEN="..." # для создания MR (scripts/create-mr.sh)
|
||||||
|
Провайдер/модель — флагами --provider/--model или в настройках Pi (пакет не навязывает).
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -225,6 +320,7 @@ cat <<EOF
|
|||||||
|
|
||||||
Запуск: pi
|
Запуск: pi
|
||||||
Обновление: pi update --extensions
|
Обновление: pi update --extensions
|
||||||
|
Окружение: ${ENV_FILE} (TRACKER_URL/JIRA_TOKEN/GITLAB_TOKEN/ключ провайдера)
|
||||||
Сменить профиль: PI_KIT_PROFILE=backend ./install.sh (или перезапусти и выбери)
|
Сменить профиль: PI_KIT_PROFILE=backend ./install.sh (или перезапусти и выбери)
|
||||||
Команды: /bugfix <тикет> /feature <тикет>
|
Команды: /bugfix <тикет> /feature <тикет>
|
||||||
/review [фокус] /rfc <тема> /kit-config
|
/review [фокус] /rfc <тема> /kit-config
|
||||||
|
|||||||
Reference in New Issue
Block a user