Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions bin/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ source "$SCRIPT_DIR/lib/manage/update.sh"
source "$SCRIPT_DIR/lib/manage/autofix.sh"

source "$SCRIPT_DIR/lib/check/all.sh"
source "$SCRIPT_DIR/lib/check/dev_environment.sh"

cleanup_all() {
stop_inline_spinner 2> /dev/null || true
Expand Down Expand Up @@ -42,6 +43,7 @@ main() {
local health_file=$(mktemp_file)
local security_file=$(mktemp_file)
local config_file=$(mktemp_file)
local dev_file=$(mktemp_file)

# Run all checks in parallel with spinner
if [[ -t 1 ]]; then
Expand All @@ -58,6 +60,7 @@ main() {
check_system_health > "$health_file" 2>&1 &
check_all_security > "$security_file" 2>&1 &
check_all_config > "$config_file" 2>&1 &
check_all_dev_environment > "$dev_file" 2>&1 &
wait
}

Expand All @@ -66,22 +69,21 @@ main() {
printf '\n'
fi

# Display results
echo -e "${BLUE}${ICON_ARROW}${NC} System updates"
# Display results (headers are printed by the check_all_* functions)
cat "$updates_file"

printf '\n'
echo -e "${BLUE}${ICON_ARROW}${NC} System health"
cat "$health_file"

printf '\n'
echo -e "${BLUE}${ICON_ARROW}${NC} Security posture"
cat "$security_file"

printf '\n'
echo -e "${BLUE}${ICON_ARROW}${NC} Configuration"
cat "$config_file"

printf '\n'
cat "$dev_file"

# Show suggestions
show_suggestions

Expand Down
3 changes: 3 additions & 0 deletions bin/optimize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ source "$SCRIPT_DIR/lib/optimize/maintenance.sh"
source "$SCRIPT_DIR/lib/optimize/tasks.sh"
source "$SCRIPT_DIR/lib/check/health_json.sh"
source "$SCRIPT_DIR/lib/check/all.sh"
source "$SCRIPT_DIR/lib/check/dev_environment.sh"
source "$SCRIPT_DIR/lib/manage/whitelist.sh"

print_header() {
Expand Down Expand Up @@ -128,6 +129,8 @@ run_system_checks() {
check_all_config
echo ""

check_all_dev_environment

show_suggestions

if ask_for_updates; then
Expand Down
154 changes: 154 additions & 0 deletions lib/check/dev_environment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/bin/bash
# Dev Environment Checks Module
# Surfaces developer-relevant system health information.

# ============================================================================
# Helper Functions
# ============================================================================

_extract_major_minor() {
printf '%s' "$1" | sed -E 's/^[^0-9]*//' | grep -oE '^[0-9]+\.[0-9]+'
}

# ============================================================================
# Dev Environment Checks
# ============================================================================

check_launch_agents() {
# Check whitelist
if command -v is_whitelisted > /dev/null && is_whitelisted "check_launch_agents"; then return; fi

local agents_dir="$HOME/Library/LaunchAgents"

if [[ ! -d "$agents_dir" ]]; then
echo -e " ${GREEN}✓${NC} Launch Agents All healthy"
return
fi

local broken_count=0
local -a broken_labels=()

for plist in "$agents_dir"/*.plist; do
[[ -f "$plist" ]] || continue

local label
label=$(basename "$plist" .plist)

local binary=""
binary=$(/usr/libexec/PlistBuddy -c "Print :ProgramArguments:0" "$plist" 2> /dev/null || true)
if [[ -z "$binary" ]]; then
binary=$(/usr/libexec/PlistBuddy -c "Print :Program" "$plist" 2> /dev/null || true)
fi

if [[ -n "$binary" && ! -e "$binary" ]]; then
broken_count=$((broken_count + 1))
broken_labels+=("$label")
fi
done

if [[ $broken_count -eq 0 ]]; then
echo -e " ${GREEN}✓${NC} Launch Agents All healthy"
else
printf " ${GRAY}%s${NC} %-14s ${YELLOW}%s${NC}\n" "$ICON_WARNING" "Launch Agents" "${broken_count} broken"

local preview_limit=3
((preview_limit > broken_count)) && preview_limit=$broken_count

local detail=""
for ((i = 0; i < preview_limit; i++)); do
if [[ $i -eq 0 ]]; then
detail="${broken_labels[$i]}"
else
detail="${detail}, ${broken_labels[$i]}"
fi
done

if ((broken_count > preview_limit)); then
local remaining=$((broken_count - preview_limit))
detail="${detail} +${remaining}"
fi

echo -e " ${GRAY}${detail}${NC}"
fi
}

check_dev_tools() {
# Check whitelist
if command -v is_whitelisted > /dev/null && is_whitelisted "check_dev_tools"; then return; fi

local -a tools=(git node python3 brew docker go xcode-select)
local -a missing=()

for tool in "${tools[@]}"; do
if ! command -v "$tool" > /dev/null 2>&1; then
missing+=("$tool")
fi
done

if [[ ${#missing[@]} -eq 0 ]]; then
echo -e " ${GREEN}✓${NC} Dev Tools All present"
else
local missing_list
missing_list=$(printf '%s, ' "${missing[@]}")
missing_list="${missing_list%, }"
printf " ${GRAY}%s${NC} %-14s ${YELLOW}%s${NC}\n" "$ICON_WARNING" "Dev Tools" "${#missing[@]} not found (${missing_list})"
fi
}

check_version_mismatches() {
# Check whitelist
if command -v is_whitelisted > /dev/null && is_whitelisted "check_version_mismatches"; then return; fi

local -a conflicts=()

# Check psql client vs postgres server
if command -v psql > /dev/null 2>&1 && command -v postgres > /dev/null 2>&1; then
local psql_ver postgres_ver
psql_ver=$(_extract_major_minor "$(psql --version 2> /dev/null || true)")
postgres_ver=$(_extract_major_minor "$(postgres --version 2> /dev/null || true)")
if [[ -n "$psql_ver" && -n "$postgres_ver" && "$psql_ver" != "$postgres_ver" ]]; then
conflicts+=("psql ${psql_ver} vs server ${postgres_ver}")
fi
fi

# Check node vs nvm default
local nvm_sh="${NVM_DIR:-$HOME/.nvm}/nvm.sh"
if command -v node > /dev/null 2>&1 && [[ -f "$nvm_sh" ]]; then
local node_ver nvm_default_ver
node_ver=$(_extract_major_minor "$(node --version 2> /dev/null || true)")
nvm_default_ver=$(bash -c "source \"$nvm_sh\" 2>/dev/null && nvm version default 2>/dev/null" || true)
nvm_default_ver=$(_extract_major_minor "$nvm_default_ver")
if [[ -n "$node_ver" && -n "$nvm_default_ver" && "$node_ver" != "$nvm_default_ver" ]]; then
conflicts+=("node ${node_ver} vs nvm default ${nvm_default_ver}")
fi
fi

# Check python3 vs pyenv
if command -v python3 > /dev/null 2>&1 && command -v pyenv > /dev/null 2>&1; then
local python_ver pyenv_ver
python_ver=$(_extract_major_minor "$(python3 --version 2> /dev/null || true)")
pyenv_ver=$(pyenv version 2> /dev/null | awk '{print $1}' || true)
if [[ -n "$pyenv_ver" && "$pyenv_ver" != "system" ]]; then
pyenv_ver=$(_extract_major_minor "$pyenv_ver")
if [[ -n "$python_ver" && -n "$pyenv_ver" && "$python_ver" != "$pyenv_ver" ]]; then
conflicts+=("python3 ${python_ver} vs pyenv ${pyenv_ver}")
fi
fi
fi

if [[ ${#conflicts[@]} -eq 0 ]]; then
echo -e " ${GREEN}✓${NC} Versions No conflicts"
else
local description
description=$(printf '%s; ' "${conflicts[@]}")
description="${description%; }"
printf " ${GRAY}%s${NC} %-14s ${YELLOW}%s${NC}\n" "$ICON_WARNING" "Versions" "$description"
fi
}

check_all_dev_environment() {
echo -e "${BLUE}${ICON_ARROW}${NC} Dev Environment"
check_launch_agents
check_dev_tools
check_version_mismatches
}
Loading
Loading