mirror of
https://github.com/selfxyz/self.git
synced 2026-01-10 23:27:56 -05:00
* update readme * add check / install script and update readme * agent feedback * gracefully handle yarn check * change order and steps
185 lines
7.3 KiB
Bash
Executable File
185 lines
7.3 KiB
Bash
Executable File
#!/bin/bash
|
||
# Self.xyz macOS Development Environment Setup
|
||
# Usage: ./scripts/setup-macos.sh [--check-only] [--yes]
|
||
|
||
set -e
|
||
|
||
# Config
|
||
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||
APP_DIR="$REPO_ROOT/app"
|
||
RUBY_VERSION=$(cat "$APP_DIR/.ruby-version" 2>/dev/null | tr -d '[:space:]')
|
||
NODE_MAJOR=22
|
||
|
||
# Args (can be overridden interactively)
|
||
CHECK_ONLY=false; AUTO_YES=false
|
||
for arg in "$@"; do
|
||
case $arg in
|
||
--check-only) CHECK_ONLY=true ;;
|
||
--yes|-y) AUTO_YES=true ;;
|
||
--interactive|-i) ;; # default behavior
|
||
esac
|
||
done
|
||
|
||
# Colors
|
||
R='\033[31m' G='\033[32m' Y='\033[33m' B='\033[34m' C='\033[36m' NC='\033[0m' BOLD='\033[1m'
|
||
|
||
ok() { echo -e "${G}✓${NC} $1"; }
|
||
err() { echo -e "${R}✗${NC} $1"; }
|
||
warn() { echo -e "${Y}⚠${NC} $1"; }
|
||
info() { echo -e "${C}ℹ${NC} $1"; }
|
||
|
||
confirm() {
|
||
$AUTO_YES && return 0
|
||
read -p "$1 [Y/n] " -n 1 -r; echo
|
||
[[ ! $REPLY =~ ^[Nn]$ ]]
|
||
}
|
||
|
||
# Check functions - return "ok:version" or "missing" or "wrong:version"
|
||
chk_brew() { command -v brew &>/dev/null && echo "ok:$(brew --version | head -1 | cut -d' ' -f2)" || echo "missing"; }
|
||
chk_nvm() { [[ -s "$HOME/.nvm/nvm.sh" ]] && echo "ok" || echo "missing"; }
|
||
chk_node() { command -v node &>/dev/null && { v=$(node -v 2>/dev/null | tr -d 'v'); [[ -n "$v" && "${v%%.*}" -ge $NODE_MAJOR ]] && echo "ok:$v" || echo "wrong:$v"; } || echo "missing"; }
|
||
chk_watch() { command -v watchman &>/dev/null && echo "ok:$(watchman --version 2>/dev/null)" || echo "missing"; }
|
||
chk_rbenv() { command -v rbenv &>/dev/null && echo "ok" || echo "missing"; }
|
||
chk_ruby() { command -v ruby &>/dev/null && { v=$(ruby -v 2>/dev/null | cut -d' ' -f2); [[ "$v" == "$RUBY_VERSION"* ]] && echo "ok:$v" || echo "wrong:$v"; } || echo "missing"; }
|
||
chk_pods() { command -v pod &>/dev/null && echo "ok:$(pod --version 2>/dev/null)" || echo "missing"; }
|
||
chk_bundler() { command -v bundle &>/dev/null && echo "ok" || echo "missing"; }
|
||
chk_java() { command -v java &>/dev/null && { v=$(java -version 2>&1 | head -1 | cut -d'"' -f2); [[ "$v" == 17* ]] && echo "ok:$v" || echo "wrong:$v"; } || echo "missing"; }
|
||
chk_xcode() { xcode-select -p &>/dev/null && [[ "$(xcode-select -p)" == *Xcode.app* ]] && echo "ok" || echo "missing"; }
|
||
chk_studio() { [[ -d "/Applications/Android Studio.app" ]] && echo "ok" || echo "missing"; }
|
||
chk_sdk() { [[ -d "${ANDROID_HOME:-$HOME/Library/Android/sdk}" ]] && echo "ok" || echo "missing"; }
|
||
chk_ndk() { [[ -d "${ANDROID_HOME:-$HOME/Library/Android/sdk}/ndk/27.0.12077973" ]] && echo "ok" || echo "missing"; }
|
||
chk_shell() { local rc=~/.zshrc; [[ "$SHELL" == *bash* ]] && rc=~/.bashrc; grep -q "ANDROID_HOME" "$rc" 2>/dev/null && echo "ok" || echo "missing"; }
|
||
|
||
# Install functions
|
||
inst_brew() { /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; }
|
||
inst_nvm() { curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash; export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; }
|
||
inst_node() { export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; nvm install $NODE_MAJOR; }
|
||
inst_watch() { brew install watchman; }
|
||
inst_rbenv() { brew install rbenv; eval "$(rbenv init -)"; }
|
||
inst_ruby() { eval "$(rbenv init -)" 2>/dev/null; rbenv install "$RUBY_VERSION"; rbenv rehash; }
|
||
inst_pods() { gem install cocoapods; }
|
||
inst_bundler() { gem install bundler; }
|
||
inst_java() { brew install openjdk@17; sudo ln -sfn "$(brew --prefix openjdk@17)/libexec/openjdk.jdk" /Library/Java/JavaVirtualMachines/openjdk-17.jdk 2>/dev/null || true; }
|
||
|
||
inst_shell() {
|
||
local rc=~/.zshrc
|
||
[[ "$SHELL" == *bash* ]] && rc=~/.bashrc
|
||
|
||
# Check if already configured
|
||
if grep -q "# Self.xyz Dev Environment" "$rc" 2>/dev/null; then
|
||
ok "Shell already configured"
|
||
return 0
|
||
fi
|
||
|
||
info "Adding environment to $rc..."
|
||
cat >> "$rc" << 'EOF'
|
||
|
||
# Self.xyz Dev Environment
|
||
export JAVA_HOME=$(/usr/libexec/java_home -v 17 2>/dev/null || echo "")
|
||
export ANDROID_HOME=~/Library/Android/sdk
|
||
export ANDROID_SDK_ROOT=$ANDROID_HOME
|
||
export PATH=$PATH:$ANDROID_HOME/emulator:$ANDROID_HOME/platform-tools
|
||
command -v rbenv &>/dev/null && eval "$(rbenv init -)"
|
||
export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
||
EOF
|
||
ok "Shell configured. Run: source $rc"
|
||
}
|
||
|
||
# Main
|
||
echo -e "\n${C}${BOLD}═══ Self.xyz macOS Setup ═══${NC}\n"
|
||
|
||
# Interactive mode selection (if no flags provided)
|
||
if [[ "$CHECK_ONLY" == false && "$AUTO_YES" == false ]]; then
|
||
echo "How would you like to run the setup?"
|
||
echo ""
|
||
echo " 1) Check only - just show what's installed/missing"
|
||
echo " 2) Interactive setup - check and confirm before installing (recommended)"
|
||
echo " 3) Auto-install - install everything without prompts"
|
||
echo ""
|
||
read -p "Enter choice [1]: " -n 1 -r choice
|
||
echo ""
|
||
case $choice in
|
||
2) ;; # interactive setup
|
||
3) AUTO_YES=true ;;
|
||
*) CHECK_ONLY=true ;; # default: check only
|
||
esac
|
||
echo ""
|
||
fi
|
||
|
||
# Define deps: name|check_fn|install_fn|manual_msg
|
||
DEPS=(
|
||
"Homebrew|chk_brew|inst_brew|"
|
||
"nvm|chk_nvm|inst_nvm|"
|
||
"Node.js $NODE_MAJOR|chk_node|inst_node|"
|
||
"Watchman|chk_watch|inst_watch|"
|
||
"rbenv|chk_rbenv|inst_rbenv|"
|
||
"Ruby $RUBY_VERSION|chk_ruby|inst_ruby|"
|
||
"CocoaPods|chk_pods|inst_pods|"
|
||
"Bundler|chk_bundler|inst_bundler|"
|
||
"Java 17|chk_java|inst_java|"
|
||
"Xcode|chk_xcode||Install from App Store: https://apps.apple.com/app/xcode/id497799835"
|
||
"Android Studio|chk_studio||Download: https://developer.android.com/studio"
|
||
"Android SDK|chk_sdk||Open Android Studio → SDK Manager"
|
||
"Android NDK|chk_ndk||SDK Manager → SDK Tools → NDK 27.0.12077973"
|
||
"Shell Config|chk_shell|inst_shell|"
|
||
)
|
||
|
||
MISSING=()
|
||
MANUAL=()
|
||
|
||
info "Checking dependencies...\n"
|
||
for dep in "${DEPS[@]}"; do
|
||
IFS='|' read -r name chk inst manual <<< "$dep"
|
||
status=$($chk)
|
||
|
||
if [[ "$status" == ok* ]]; then
|
||
ver="${status#ok:}"; [[ -n "$ver" && "$ver" != "ok" ]] && ok "$name ($ver)" || ok "$name"
|
||
elif [[ -n "$manual" ]]; then
|
||
warn "$name - manual install required"
|
||
MANUAL+=("$name|$manual")
|
||
else
|
||
err "$name - not installed"
|
||
[[ -n "$inst" ]] && MISSING+=("$name|$inst")
|
||
fi
|
||
done
|
||
|
||
$CHECK_ONLY && {
|
||
[[ ${#MANUAL[@]} -gt 0 ]] && { echo -e "\n${Y}Manual installs:${NC}"; for m in "${MANUAL[@]}"; do IFS='|' read -r n msg <<< "$m"; echo " $n: $msg"; done; }
|
||
exit 0
|
||
}
|
||
|
||
# Install missing
|
||
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
||
echo -e "\n${B}Missing:${NC} $(printf '%s\n' "${MISSING[@]}" | cut -d'|' -f1 | tr '\n' ', ' | sed 's/, $//')"
|
||
if confirm "Install all?"; then
|
||
for m in "${MISSING[@]}"; do
|
||
IFS='|' read -r name fn <<< "$m"
|
||
info "Installing $name..."
|
||
$fn && ok "$name installed" || err "Failed: $name"
|
||
done
|
||
fi
|
||
fi
|
||
|
||
# Manual instructions
|
||
[[ ${#MANUAL[@]} -gt 0 ]] && { echo -e "\n${Y}Manual installs needed:${NC}"; for m in "${MANUAL[@]}"; do IFS='|' read -r n msg <<< "$m"; echo " $n: $msg"; done; }
|
||
|
||
# Yarn install
|
||
echo ""
|
||
if confirm "Run 'yarn install' in repo root?"; then
|
||
info "Running yarn install..."
|
||
set +e # Temporarily disable exit-on-error
|
||
cd "$REPO_ROOT" && yarn install
|
||
yarn_exit=$?
|
||
set -e # Re-enable exit-on-error
|
||
|
||
if [[ $yarn_exit -eq 0 ]]; then
|
||
ok "Done!"
|
||
else
|
||
err "Yarn install failed (exit code: $yarn_exit)"
|
||
warn "This may be due to network issues or registry timeouts"
|
||
info "Try running manually: cd $REPO_ROOT && yarn install"
|
||
fi
|
||
fi
|
||
|
||
echo -e "\n${G}${BOLD}Setup complete!${NC} Open a new terminal, then: cd $APP_DIR && yarn ios\n"
|