Merge pull request 'fix: feat: disinto init — prompt for disinto-admin password instead of hardcoding it (#620)' (#639) from fix/issue-620 into main
All checks were successful
ci/woodpecker/push/ci Pipeline was successful

This commit is contained in:
dev-qwen 2026-04-10 18:37:12 +00:00
commit f8bb3eea7d
2 changed files with 86 additions and 0 deletions

View file

@ -540,6 +540,86 @@ activate_woodpecker_repo() {
_activate_woodpecker_repo_impl "$@"
}
# ── Password prompt helper ────────────────────────────────────────────────────
# Prompts for FORGE_ADMIN_PASS with confirmation.
# Returns 0 on success, 1 on failure.
# Usage: prompt_admin_password [<env_file>]
prompt_admin_password() {
local env_file="${1:-${FACTORY_ROOT}/.env}"
# Check if password already exists in .env (resumable init)
if grep -q '^FORGE_ADMIN_PASS=' "$env_file" 2>/dev/null; then
echo "Forge: FORGE_ADMIN_PASS already set (resuming from .env)"
return 0
fi
# Non-interactive mode without pre-exported password
if [ "$auto_yes" = true ]; then
if [ -z "${FORGE_ADMIN_PASS:-}" ]; then
echo "Error: FORGE_ADMIN_PASS environment variable is required in non-interactive mode" >&2
echo " Export the password before running: export FORGE_ADMIN_PASS='<your-password>'" >&2
exit 1
fi
# Write the pre-exported password to .env
if grep -q '^FORGE_ADMIN_PASS=' "$env_file" 2>/dev/null; then
sed -i "s|^FORGE_ADMIN_PASS=.*|FORGE_ADMIN_PASS=${FORGE_ADMIN_PASS}|" "$env_file"
else
printf 'FORGE_ADMIN_PASS=%s\n' "$FORGE_ADMIN_PASS" >> "$env_file"
fi
echo "Forge: FORGE_ADMIN_PASS set from environment"
return 0
fi
# Interactive mode: prompt for password with confirmation
if [ -t 0 ]; then
local pass1 pass2 min_length=8 attempts=0 max_attempts=3
echo "Forge: Setting disinto-admin password"
echo " Password must be at least ${min_length} characters"
echo ""
while [ "$attempts" -lt "$max_attempts" ]; do
attempts=$((attempts + 1))
# First attempt (or retry): read password
printf "Enter password [%d/%d]: " "$attempts" "$max_attempts"
IFS= read -rs -p '' pass1
echo ""
# Read confirmation
printf "Confirm password: "
IFS= read -rs -p '' pass2
echo ""
# Validate length
if [ "${#pass1}" -lt "$min_length" ]; then
echo "Error: password must be at least ${min_length} characters (got ${#pass1})" >&2
continue
fi
# Validate match
if [ "$pass1" != "$pass2" ]; then
echo "Error: passwords do not match" >&2
continue
fi
# Success: write to .env
printf 'FORGE_ADMIN_PASS=%s\n' "$pass1" >> "$env_file"
echo "Forge: FORGE_ADMIN_PASS set (saved to .env)"
return 0
done
echo "Error: exceeded ${max_attempts} attempts — password not set" >&2
return 1
fi
# Non-interactive, no TTY, no pre-exported password
echo "Error: FORGE_ADMIN_PASS is not set and cannot prompt (no TTY)" >&2
echo " Either:" >&2
echo " 1) Export the password before running: export FORGE_ADMIN_PASS='<your-password>'" >&2
echo " 2) Run interactively (attach a TTY) to be prompted" >&2
exit 1
}
# ── init command ─────────────────────────────────────────────────────────────
disinto_init() {
@ -652,6 +732,10 @@ p.write_text(text)
touch "${FACTORY_ROOT}/.env"
fi
# Prompt for FORGE_ADMIN_PASS before setup_forge
# This ensures the password is set before Forgejo user creation
prompt_admin_password "${FACTORY_ROOT}/.env"
# Set up local Forgejo instance (provision if needed, create users/tokens/repo)
if [ "$rotate_tokens" = true ]; then
echo "Note: Forcing token rotation (tokens/passwords will be regenerated)"

View file

@ -161,6 +161,8 @@ git commit --quiet -m "Initial commit"
export SMOKE_FORGE_URL="$FORGE_URL"
export FORGE_URL
# Required for non-interactive init (issue #620)
export FORGE_ADMIN_PASS="smoke-test-password-123"
# Skip push to mock server (no git support)
export SKIP_PUSH=true