feat(dev-env): shell scripts (git-hooks, worktree, deploy, regtest, nav) and smoke test

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-28 06:48:37 +02:00
commit dbd9e76027
13 changed files with 2496 additions and 0 deletions

View file

@ -0,0 +1,142 @@
#!/usr/bin/env bash
# dev-status: show divergence and dirty state of every dev-env worktree
#
# Replaces ~/omarchy-dev-env/setup/dev-status.sh, which referenced a
# stale $PROJECTS_DIR layout. This version reads /etc/dev-env/projects.json
# and walks the actual declared worktrees.
set -euo pipefail
if [[ -r /etc/dev-env/config.sh ]]; then
# shellcheck disable=SC1091
source /etc/dev-env/config.sh
fi
PROJECTS_JSON="${DEVENV_PROJECTS_JSON:-/etc/dev-env/projects.json}"
if [[ ! -r "$PROJECTS_JSON" ]]; then
echo "projects.json not found at $PROJECTS_JSON" >&2
exit 1
fi
if ! command -v jq >/dev/null; then
echo "jq required" >&2
exit 1
fi
# Colors — shared palette (RED/GREEN/YELLOW/BLUE/CYAN/BOLD/NC …)
if [[ -r /etc/dev-env/lib-colors.sh ]]; then
# shellcheck disable=SC1091
source /etc/dev-env/lib-colors.sh
fi
issues=()
header() {
echo ""
echo -e "${BOLD}${CYAN}═══════════════════════════════════════════════════════${NC}"
echo -e "${BOLD}${CYAN} $1${NC}"
echo -e "${BOLD}${CYAN}═══════════════════════════════════════════════════════${NC}"
}
check_one() {
local label="$1" path="$2" has_upstream="${3:-false}"
if [[ ! -d "$path/.git" ]] && [[ ! -f "$path/.git" ]]; then
printf " ${YELLOW}${NC} %s: not present\n" "$label"
issues+=("$label: not present")
return
fi
git -C "$path" fetch --all --quiet 2>/dev/null || true
local branch icons="" status_str=""
branch="$(git -C "$path" branch --show-current 2>/dev/null || echo '?')"
[[ -n "$(git -C "$path" status --porcelain)" ]] && {
icons+="${YELLOW}${NC} "
status_str+="dirty "
}
local behind ahead
behind=$(git -C "$path" rev-list --count "HEAD..origin/$branch" 2>/dev/null || echo 0)
ahead=$(git -C "$path" rev-list --count "origin/$branch..HEAD" 2>/dev/null || echo 0)
(( behind > 0 )) && icons+="${RED}${NC}$behind "
(( ahead > 0 )) && icons+="${GREEN}${NC}$ahead "
if [[ "$has_upstream" == "true" ]] && git -C "$path" remote get-url upstream &>/dev/null; then
local ub="main"
git -C "$path" rev-parse upstream/main &>/dev/null || ub="master"
local ub_behind
ub_behind=$(git -C "$path" rev-list --count "HEAD..upstream/$ub" 2>/dev/null || echo 0)
if (( ub_behind > 0 )); then
icons+="${CYAN}${NC}$ub_behind "
issues+=("$label: $ub_behind behind upstream/$ub")
fi
fi
[[ -z "$icons" ]] && icons="${GREEN}${NC}"
printf " %-45s %s (%s)\n" "$label" "$icons" "$branch"
}
header "Development Environment Status"
echo -e " ${BLUE}Date:${NC} $(date '+%Y-%m-%d %H:%M')"
echo -e " ${BLUE}Host:${NC} $(hostname)"
echo -e " ${BLUE}Root:${NC} ${DEV_ROOT:-?}"
# Walk every project and worktree from the JSON.
mapfile -t PROJECTS < <(jq -r 'keys[]' "$PROJECTS_JSON")
for proj in "${PROJECTS[@]}"; do
echo ""
echo -e "${BLUE}─── $proj ───${NC}"
is_clone="$(jq -r --arg p "$proj" '.[$p].isClone' "$PROJECTS_JSON")"
has_upstream_decl="$(jq -r --arg p "$proj" '.[$p].remotes.upstream != null' "$PROJECTS_JSON")"
if [[ "$is_clone" == "true" ]]; then
clone_path="$(jq -r --arg p "$proj" '.[$p].clonePath' "$PROJECTS_JSON")"
check_one "$proj" "$clone_path" "$has_upstream_decl"
else
while IFS=$'\t' read -r wt_name wt_path; do
[[ -z "$wt_name" || "$wt_path" == "null" ]] && continue
check_one "$proj/$wt_name" "$wt_path" "$has_upstream_decl"
done < <(jq -r --arg p "$proj" '
.[$p].worktrees
| to_entries[]
| "\(.key)\t\(.value.path)"
' "$PROJECTS_JSON")
fi
done
# Docker
echo ""
echo -e "${BLUE}─── Docker ───${NC}"
if command -v docker &>/dev/null; then
running="$(docker ps --format '{{.Names}}' 2>/dev/null | wc -l)"
echo -e " ${BLUE}Containers running:${NC} $running"
fi
header "Summary"
if (( ${#issues[@]} == 0 )); then
echo -e " ${GREEN}✓ All worktrees are clean and in sync!${NC}"
else
echo -e " ${YELLOW}Issues found:${NC}"
for issue in "${issues[@]}"; do
echo -e " ${YELLOW}${NC} $issue"
done
fi
cat <<EOF
${BLUE}Legend:${NC}
${GREEN}${NC} clean ${YELLOW}${NC} dirty ${GREEN}${NC} ahead origin
${RED}${NC} behind origin ${CYAN}${NC} behind upstream
${BLUE}Quick actions:${NC}
wts sync all worktrees with origin
wtu <repo> fetch upstream + show divergence
rebase status which forks need rebasing onto upstream
dev-env-bootstrap materialize missing worktrees
EOF