singularity-forge/scripts/verify-s03.sh
ace-pm 421fccd898 refactor: rebrand gsd_ tool names and references to sf_ namespace
Updates workflow tool names, documentation references, and internal naming
conventions across MCP server, CLI, tests, and web components to complete
the singularity-forge rebrand from gsd to sf.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:51:38 +02:00

166 lines
5.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# S03 verification — first-run optional tool key wizard
FAIL=0
pass() { echo " PASS: $1"; }
fail() { echo " FAIL: $1"; FAIL=1; }
# Run node with a timeout using background kill (macOS has no GNU timeout)
run_bg() {
local secs="$1"; shift
local tmp; tmp=$(mktemp)
local exit_tmp; exit_tmp=$(mktemp)
echo "" > "$exit_tmp"
( "$@" > "$tmp" 2>&1; echo "$?" > "$exit_tmp" ) &
local pid=$!
sleep "$secs"
kill "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
local code; code=$(cat "$exit_tmp")
cat "$tmp"
rm -f "$tmp" "$exit_tmp"
# Return the actual exit code if the process finished, else 0 (still running = ok)
[ -n "$code" ] && return "$code" || return 0
}
echo "=== S03 Verification ==="
echo ""
# ----------------------------------------------------------------
# Check 1 — Build: dist outputs exist
# ----------------------------------------------------------------
echo "--- Build ---"
if [ -f "dist/wizard.js" ] && [ -f "dist/cli.js" ] && [ -f "dist/loader.js" ]; then
pass "1 — dist/wizard.js, dist/cli.js, dist/loader.js exist"
else
echo " (building...)"
npm run build --silent 2>&1
if [ -f "dist/wizard.js" ] && [ -f "dist/cli.js" ] && [ -f "dist/loader.js" ]; then
pass "1 — build succeeded"
else
fail "1 — build failed or dist files missing"
fi
fi
echo ""
echo "--- Non-TTY optional-key warning path ---"
# ----------------------------------------------------------------
# Check 2 — Non-TTY with all optional keys unset → warning on stderr, no exit 1
# Uses a clean env with only ANTHROPIC_API_KEY set so the TUI can start,
# then kills after 3s. The warning is emitted before the TUI launches.
# ----------------------------------------------------------------
tmp2=$(mktemp)
(
env -i HOME="$HOME" PATH="$PATH" ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}" \
node dist/loader.js < /dev/null > "$tmp2" 2>&1
echo "$?" >> "$tmp2"
) &
pid2=$!
sleep 3
kill "$pid2" 2>/dev/null || true
wait "$pid2" 2>/dev/null || true
if grep -q "Warning.*optional" "$tmp2" 2>/dev/null; then
pass "2 — Non-TTY missing optional keys → stderr warning emitted"
else
fail "2 — Non-TTY missing optional keys → stderr warning emitted"
echo " Output: $(head -3 "$tmp2")"
fi
# Check it does NOT exit 1 for missing optional keys (last line if process exited)
last_line=$(tail -1 "$tmp2")
if [ "$last_line" = "1" ]; then
fail "3 — Non-TTY missing optional keys → does NOT exit 1 (got exit 1)"
else
pass "3 — Non-TTY missing optional keys → does NOT exit 1"
fi
rm -f "$tmp2"
echo ""
echo "--- Wizard skip when all keys present ---"
# ----------------------------------------------------------------
# Check 4 — All optional keys in env → wizard does not fire (no prompt text)
# ----------------------------------------------------------------
tmp4=$(mktemp)
(
env -i HOME="$HOME" PATH="$PATH" \
ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}" \
BRAVE_API_KEY="test-brave" \
BRAVE_ANSWERS_KEY="test-answers" \
CONTEXT7_API_KEY="test-ctx7" \
JINA_API_KEY="test-jina" \
node dist/loader.js < /dev/null > "$tmp4" 2>&1
) &
pid4=$!
sleep 3
kill "$pid4" 2>/dev/null || true
wait "$pid4" 2>/dev/null || true
if grep -qiE "optional tool|Some optional|Press Enter to skip" "$tmp4" 2>/dev/null; then
fail "4 — All optional keys in env → wizard does not fire"
echo " Output contained wizard text: $(grep -iE 'optional|Press Enter' "$tmp4" | head -2)"
else
pass "4 — All optional keys in env → wizard does not fire"
fi
rm -f "$tmp4"
echo ""
echo "--- loadStoredEnvKeys hydration ---"
# ----------------------------------------------------------------
# Check 5 — Structural: env var names compiled into dist/wizard.js
# ----------------------------------------------------------------
if grep -q "BRAVE_API_KEY" dist/wizard.js && grep -q "BRAVE_ANSWERS_KEY" dist/wizard.js && grep -q "CONTEXT7_API_KEY" dist/wizard.js && grep -q "JINA_API_KEY" dist/wizard.js; then
pass "5 — dist/wizard.js contains all four optional key env var names"
else
fail "5 — dist/wizard.js missing one or more optional key env var names"
fi
# ----------------------------------------------------------------
# Check 6 — loadStoredEnvKeys: stored brave key is set into process.env
# Write a test auth.json with a brave key, run loader, confirm no crash
# ----------------------------------------------------------------
tmp_auth=$(mktemp)
cat > "$tmp_auth" <<'EOF'
{"brave":{"type":"api_key","key":"test-brave-stored"}}
EOF
tmp6=$(mktemp)
(
env -i HOME="$HOME" PATH="$PATH" \
ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}" \
SF_TEST_AUTH_PATH="$tmp_auth" \
SF_TEST_AUTH_PATH="$tmp_auth" \
node -e "
import('./dist/app-paths.js').then(async (paths) => {
// Override authFilePath for test
const { AuthStorage } = await import('@mariozechner/pi-coding-agent');
const { loadStoredEnvKeys } = await import('./dist/wizard.js');
const auth = AuthStorage.create('$tmp_auth');
loadStoredEnvKeys(auth);
const val = process.env.BRAVE_API_KEY;
process.stdout.write('BRAVE_API_KEY=' + (val || '') + '\n');
process.exit(0);
});
" > "$tmp6" 2>&1
) || true
if grep -q "BRAVE_API_KEY=test-brave-stored" "$tmp6" 2>/dev/null; then
pass "6 — loadStoredEnvKeys hydrates BRAVE_API_KEY from auth.json"
else
fail "6 — loadStoredEnvKeys hydrates BRAVE_API_KEY from auth.json"
echo " Output: $(cat "$tmp6")"
fi
rm -f "$tmp_auth" "$tmp6"
echo ""
echo "=== Results ==="
if [ "$FAIL" -eq 0 ]; then
echo "All checks passed."
exit 0
else
echo "One or more checks FAILED."
exit 1
fi