281 lines
7.0 KiB
Bash
Executable File
281 lines
7.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# setup-dev-environment.sh
|
|
# Idempotent bootstrap for local Period Vault development.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
INSTALL_MISSING=0
|
|
RUN_CHECKS=0
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: ./scripts/setup-dev-environment.sh [--install] [--verify] [--help]
|
|
|
|
Options:
|
|
--install Attempt safe auto-install for supported tools (Homebrew on macOS).
|
|
--verify Run post-setup verification commands.
|
|
--help Show this help.
|
|
|
|
Notes:
|
|
- Script is idempotent and safe to re-run.
|
|
- Without --install, the script reports actionable install commands.
|
|
- It never writes credentials/tokens and does not run privileged commands automatically.
|
|
EOF
|
|
}
|
|
|
|
log() { printf "${BLUE}[%s]${NC} %s\n" "setup" "$*"; }
|
|
ok() { printf "${GREEN}[ok]${NC} %s\n" "$*"; }
|
|
warn() { printf "${YELLOW}[warn]${NC} %s\n" "$*"; }
|
|
fail() { printf "${RED}[error]${NC} %s\n" "$*" >&2; }
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--install) INSTALL_MISSING=1 ;;
|
|
--verify) RUN_CHECKS=1 ;;
|
|
--help|-h) usage; exit 0 ;;
|
|
*)
|
|
fail "Unknown option: $arg"
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ ! -x "$PROJECT_ROOT/gradlew" ]]; then
|
|
fail "Missing executable Gradle wrapper at ./gradlew."
|
|
exit 1
|
|
fi
|
|
|
|
OS="$(uname -s)"
|
|
IS_MAC=0
|
|
IS_LINUX=0
|
|
case "$OS" in
|
|
Darwin) IS_MAC=1 ;;
|
|
Linux) IS_LINUX=1 ;;
|
|
*)
|
|
warn "Unsupported OS: $OS. Script will run checks but skip auto-install."
|
|
;;
|
|
esac
|
|
|
|
declare -a REQUIRED_TOOLS
|
|
declare -a OPTIONAL_TOOLS
|
|
declare -a MISSING_REQUIRED
|
|
declare -a MISSING_OPTIONAL
|
|
declare -a REMEDIATION_HINTS
|
|
|
|
REQUIRED_TOOLS=(git java)
|
|
OPTIONAL_TOOLS=(gh act adb emulator avdmanager sdkmanager)
|
|
|
|
if [[ $IS_MAC -eq 1 ]]; then
|
|
REQUIRED_TOOLS+=(xcodebuild xcrun)
|
|
fi
|
|
|
|
have_cmd() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
append_unique_hint() {
|
|
local hint="$1"
|
|
local existing
|
|
for existing in "${REMEDIATION_HINTS[@]:-}"; do
|
|
if [[ "$existing" == "$hint" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
REMEDIATION_HINTS+=("$hint")
|
|
}
|
|
|
|
detect_java_major() {
|
|
local raw version major
|
|
raw="$(java -version 2>&1 | head -n 1 || true)"
|
|
version="$(echo "$raw" | sed -E 's/.*"([0-9]+)(\.[0-9]+.*)?".*/\1/' || true)"
|
|
if [[ -z "$version" ]]; then
|
|
echo "0"
|
|
return 0
|
|
fi
|
|
major="$version"
|
|
echo "$major"
|
|
}
|
|
|
|
install_with_brew() {
|
|
local formula="$1"
|
|
if ! have_cmd brew; then
|
|
append_unique_hint "Install Homebrew first: https://brew.sh/"
|
|
return 1
|
|
fi
|
|
|
|
if brew list --formula "$formula" >/dev/null 2>&1; then
|
|
ok "brew formula '$formula' already installed"
|
|
return 0
|
|
fi
|
|
|
|
log "Installing '$formula' via Homebrew..."
|
|
if brew install "$formula"; then
|
|
ok "Installed '$formula'"
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
try_install_tool() {
|
|
local tool="$1"
|
|
if [[ $INSTALL_MISSING -ne 1 ]]; then
|
|
return 1
|
|
fi
|
|
|
|
if [[ $IS_MAC -eq 1 ]]; then
|
|
case "$tool" in
|
|
git) install_with_brew git ;;
|
|
gh) install_with_brew gh ;;
|
|
act) install_with_brew act ;;
|
|
java)
|
|
install_with_brew openjdk@17
|
|
append_unique_hint "If needed, configure JAVA_HOME for JDK 17+: export JAVA_HOME=\$(/usr/libexec/java_home -v 17)"
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
return $?
|
|
fi
|
|
|
|
if [[ $IS_LINUX -eq 1 ]]; then
|
|
append_unique_hint "Install '$tool' using your distro package manager and re-run this script."
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
tool_hint() {
|
|
local tool="$1"
|
|
if [[ $IS_MAC -eq 1 ]]; then
|
|
case "$tool" in
|
|
git|gh|act) echo "brew install $tool" ;;
|
|
java) echo "brew install openjdk@17 && export JAVA_HOME=\$(/usr/libexec/java_home -v 17)" ;;
|
|
xcodebuild|xcrun) echo "Install Xcode from the App Store and run: sudo xcodebuild -runFirstLaunch" ;;
|
|
adb|emulator|avdmanager|sdkmanager) echo "Install Android Studio + Android SDK command-line tools, then add platform-tools/emulator/cmdline-tools/latest/bin to PATH." ;;
|
|
*) echo "Install '$tool' and ensure it is on PATH." ;;
|
|
esac
|
|
return 0
|
|
fi
|
|
|
|
if [[ $IS_LINUX -eq 1 ]]; then
|
|
case "$tool" in
|
|
git) echo "sudo apt-get install -y git" ;;
|
|
java) echo "sudo apt-get install -y openjdk-17-jdk" ;;
|
|
gh) echo "Install GitHub CLI from https://cli.github.com/" ;;
|
|
act) echo "Install act from https://github.com/nektos/act" ;;
|
|
*) echo "Install '$tool' using your package manager and add it to PATH." ;;
|
|
esac
|
|
return 0
|
|
fi
|
|
|
|
echo "Install '$tool' and ensure it is on PATH."
|
|
}
|
|
|
|
log "Checking local development prerequisites..."
|
|
|
|
for tool in "${REQUIRED_TOOLS[@]}"; do
|
|
if have_cmd "$tool"; then
|
|
ok "Found required tool: $tool"
|
|
else
|
|
warn "Missing required tool: $tool"
|
|
if try_install_tool "$tool" && have_cmd "$tool"; then
|
|
ok "Auto-installed required tool: $tool"
|
|
else
|
|
MISSING_REQUIRED+=("$tool")
|
|
append_unique_hint "$(tool_hint "$tool")"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
for tool in "${OPTIONAL_TOOLS[@]}"; do
|
|
if have_cmd "$tool"; then
|
|
ok "Found optional tool: $tool"
|
|
else
|
|
warn "Missing optional tool: $tool"
|
|
if try_install_tool "$tool" && have_cmd "$tool"; then
|
|
ok "Auto-installed optional tool: $tool"
|
|
else
|
|
MISSING_OPTIONAL+=("$tool")
|
|
append_unique_hint "$(tool_hint "$tool")"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if have_cmd java; then
|
|
JAVA_MAJOR="$(detect_java_major)"
|
|
if [[ "$JAVA_MAJOR" =~ ^[0-9]+$ ]] && [[ "$JAVA_MAJOR" -ge 17 ]]; then
|
|
ok "Java version is compatible (major=$JAVA_MAJOR)"
|
|
else
|
|
fail "Java 17+ is required (detected major=$JAVA_MAJOR)."
|
|
append_unique_hint "$(tool_hint "java")"
|
|
if [[ ! " ${MISSING_REQUIRED[*]} " =~ " java " ]]; then
|
|
MISSING_REQUIRED+=("java")
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
log "Installing git hooks (idempotent)..."
|
|
"$SCRIPT_DIR/install-hooks.sh"
|
|
ok "Git hooks configured"
|
|
|
|
echo ""
|
|
echo "================================================"
|
|
echo "Setup Summary"
|
|
echo "================================================"
|
|
if [[ ${#MISSING_REQUIRED[@]} -eq 0 ]]; then
|
|
ok "All required prerequisites are available."
|
|
else
|
|
fail "Missing required prerequisites: ${MISSING_REQUIRED[*]}"
|
|
fi
|
|
|
|
if [[ ${#MISSING_OPTIONAL[@]} -eq 0 ]]; then
|
|
ok "All optional developer tools are available."
|
|
else
|
|
warn "Missing optional tools: ${MISSING_OPTIONAL[*]}"
|
|
fi
|
|
|
|
if [[ ${#REMEDIATION_HINTS[@]} -gt 0 ]]; then
|
|
echo ""
|
|
echo "Suggested remediation:"
|
|
for hint in "${REMEDIATION_HINTS[@]}"; do
|
|
echo " - $hint"
|
|
done
|
|
fi
|
|
|
|
echo ""
|
|
echo "Verification commands:"
|
|
echo " - ./gradlew shared:jvmTest"
|
|
echo " - ./scripts/run-emulator-tests.sh android"
|
|
echo " - ./scripts/run-emulator-tests.sh ios"
|
|
echo " - ./scripts/verify.sh"
|
|
|
|
if [[ $RUN_CHECKS -eq 1 ]]; then
|
|
echo ""
|
|
log "Running lightweight verification commands..."
|
|
"$PROJECT_ROOT/gradlew" --version >/dev/null
|
|
ok "Gradle wrapper check passed"
|
|
if have_cmd gh; then
|
|
gh --version >/dev/null
|
|
ok "GitHub CLI check passed"
|
|
fi
|
|
if have_cmd xcrun; then
|
|
xcrun simctl list devices available >/dev/null
|
|
ok "iOS simulator listing check passed"
|
|
fi
|
|
fi
|
|
|
|
if [[ ${#MISSING_REQUIRED[@]} -gt 0 ]]; then
|
|
exit 1
|
|
fi
|
|
|
|
ok "Developer environment bootstrap completed."
|