fix: disinto init needs a system requirements preflight check (#564)

Replace validate_env() with preflight_check() that verifies all factory
requirements before init proceeds:

- Required tools: claude, tmux, git, jq, python3, curl (hard errors)
- Claude Code authentication via claude auth status
- Codeberg auth: CODEBERG_TOKEN or ~/.netrc, verified with API call
- Codeberg SSH access: verified with ssh -T git@codeberg.org
- Optional: docker (warn only)
- Clear error messages with install hints for each missing tool

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
openhands 2026-03-22 17:45:38 +00:00
parent bffb6f59b2
commit 01d780303f

View file

@ -57,18 +57,88 @@ clone_url_from_slug() {
printf 'https://codeberg.org/%s.git' "$1"
}
# Validate that required tokens and tools are available.
validate_env() {
# Preflight check — verify all factory requirements before proceeding.
preflight_check() {
local errors=0
# ── Required commands ──
local -A hints=(
[claude]="Install: https://docs.anthropic.com/en/docs/claude-code/overview"
[tmux]="Install: apt install tmux / brew install tmux"
[git]="Install: apt install git / brew install git"
[jq]="Install: apt install jq / brew install jq"
[python3]="Install: apt install python3 / brew install python3"
[curl]="Install: apt install curl / brew install curl"
)
local cmd
for cmd in claude tmux git jq python3 curl; do
if ! command -v "$cmd" &>/dev/null; then
echo "Error: ${cmd} not found" >&2
echo " ${hints[$cmd]}" >&2
errors=$((errors + 1))
fi
done
# ── Claude Code authentication ──
if command -v claude &>/dev/null && command -v jq &>/dev/null; then
local auth_json
auth_json=$(claude auth status 2>/dev/null) || auth_json=""
if [ -n "$auth_json" ]; then
local logged_in
logged_in=$(printf '%s' "$auth_json" | jq -r '.loggedIn // false' 2>/dev/null) || logged_in="false"
if [ "$logged_in" != "true" ]; then
echo "Error: Claude Code is not authenticated" >&2
echo " Run: claude auth login" >&2
errors=$((errors + 1))
fi
fi
fi
# ── Codeberg auth ──
local has_codeberg_auth=true
if [ -z "${CODEBERG_TOKEN:-}" ]; then
echo "Error: CODEBERG_TOKEN is not set" >&2
echo " Set it in ${FACTORY_ROOT}/.env or export it" >&2
errors=1
if ! grep -q codeberg.org ~/.netrc 2>/dev/null; then
echo "Error: no Codeberg auth (set CODEBERG_TOKEN or configure ~/.netrc)" >&2
echo " Set CODEBERG_TOKEN in ${FACTORY_ROOT}/.env or export it" >&2
errors=$((errors + 1))
has_codeberg_auth=false
fi
fi
if ! command -v claude &>/dev/null; then
echo "Warning: claude CLI not found in PATH" >&2
# Verify Codeberg API access actually works
if [ "$has_codeberg_auth" = true ] && command -v curl &>/dev/null; then
local curl_args=(-sf --max-time 10)
if [ -n "${CODEBERG_TOKEN:-}" ]; then
curl_args+=(-H "Authorization: token ${CODEBERG_TOKEN}")
fi
if ! curl "${curl_args[@]}" "https://codeberg.org/api/v1/user" >/dev/null 2>&1; then
echo "Error: Codeberg API auth failed" >&2
echo " Verify your CODEBERG_TOKEN or ~/.netrc credentials" >&2
errors=$((errors + 1))
fi
fi
# ── Codeberg SSH access ──
if command -v ssh &>/dev/null; then
local ssh_output
ssh_output=$(ssh -T -o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=accept-new \
git@codeberg.org 2>&1) || true
if ! printf '%s' "$ssh_output" | grep -qi "successfully authenticated"; then
echo "Error: Codeberg SSH access failed (agents push via SSH)" >&2
echo " Add your SSH key: https://codeberg.org/user/settings/keys" >&2
errors=$((errors + 1))
fi
fi
# ── Optional tools (warn only) ──
if ! command -v docker &>/dev/null; then
echo "Warning: docker not found (some projects may need it)" >&2
fi
if [ "$errors" -gt 0 ]; then
echo "" >&2
echo "${errors} preflight error(s) — fix the above before running disinto init" >&2
exit 1
fi
}
@ -317,8 +387,8 @@ p.write_text(text)
fi
fi
# Validate tokens
validate_env
# Preflight: verify factory requirements
preflight_check
# Determine repo root (for new projects)
repo_root="${repo_root:-/home/${USER}/${project_name}}"