mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-04-06 21:41:42 +02:00
Align BMAD paths with new knowledge structure and automate project registry sync
This commit is contained in:
212
scripts/sync-projects-conf.sh
Executable file
212
scripts/sync-projects-conf.sh
Executable file
@@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LEADTECH_ROOT="${LEADTECH:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
||||
PROJECTS_CONF="${PROJECTS_CONF:-$LEADTECH_ROOT/_projects.conf}"
|
||||
|
||||
PROJECT_ROOT=""
|
||||
PROJECT_NAME=""
|
||||
STACK_OVERRIDE=""
|
||||
SCOPE_OVERRIDE=""
|
||||
STATE_OVERRIDE=""
|
||||
SYNC_EXISTING="false"
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
Usage: sync-projects-conf.sh [options]
|
||||
|
||||
Options:
|
||||
--project-root <path> Project root directory (default: current directory)
|
||||
--project-name <name> Project name override (default: basename project-root)
|
||||
--stack <value> Stack override
|
||||
--scope <value> Scope override (perso|mindleaf|lab|archive)
|
||||
--state <value> State override
|
||||
--sync-existing Update existing line (safe mode: preserve scope/state unless explicit override)
|
||||
-h, --help Show help
|
||||
USAGE
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--project-root)
|
||||
PROJECT_ROOT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--project-name)
|
||||
PROJECT_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--stack)
|
||||
STACK_OVERRIDE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--scope)
|
||||
SCOPE_OVERRIDE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--state)
|
||||
STATE_OVERRIDE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--sync-existing)
|
||||
SYNC_EXISTING="true"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Erreur: option inconnue: $1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
PROJECT_ROOT="${PROJECT_ROOT:-$PWD}"
|
||||
if [ ! -d "$PROJECT_ROOT" ]; then
|
||||
echo "Erreur: project-root introuvable: $PROJECT_ROOT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$PROJECTS_CONF" ]; then
|
||||
echo "Erreur: _projects.conf introuvable: $PROJECTS_CONF" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trim() {
|
||||
local s="$1"
|
||||
# shellcheck disable=SC2001
|
||||
s="$(echo "$s" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
||||
printf '%s' "$s"
|
||||
}
|
||||
|
||||
infer_stack() {
|
||||
local root="$1"
|
||||
local out=()
|
||||
|
||||
if [ -f "$root/pnpm-workspace.yaml" ]; then
|
||||
out+=("pnpm monorepo")
|
||||
fi
|
||||
|
||||
if [ -f "$root/package.json" ]; then
|
||||
if grep -Eq '"@nestjs/' "$root/package.json"; then out+=("NestJS"); fi
|
||||
if grep -Eq '"next"' "$root/package.json"; then out+=("Next.js"); fi
|
||||
if grep -Eq '"expo"' "$root/package.json"; then out+=("Expo"); fi
|
||||
if grep -Eq '"react-native"' "$root/package.json"; then out+=("React Native"); fi
|
||||
if grep -Eq '"prisma"|"@prisma/' "$root/package.json"; then out+=("Prisma"); fi
|
||||
fi
|
||||
|
||||
if [ -f "$root/prisma/schema.prisma" ] && grep -qi 'provider *= *"postgresql"' "$root/prisma/schema.prisma"; then
|
||||
out+=("PostgreSQL")
|
||||
fi
|
||||
|
||||
if [ -f "$root/CLAUDE.md" ]; then
|
||||
local from_claude
|
||||
from_claude="$(awk '
|
||||
BEGIN {in_stack=0}
|
||||
/^## Stack/ {in_stack=1; next}
|
||||
/^## / {if (in_stack) exit}
|
||||
in_stack && /^- / {sub(/^- /, ""); print}
|
||||
' "$root/CLAUDE.md" | paste -sd ' + ' -)"
|
||||
from_claude="$(trim "$from_claude")"
|
||||
if [ -n "$from_claude" ]; then
|
||||
printf '%s' "$from_claude"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ${#out[@]} -eq 0 ]; then
|
||||
printf '%s' "stack-a-completer"
|
||||
else
|
||||
local joined
|
||||
joined="$(printf '%s\n' "${out[@]}" | awk '!seen[$0]++' | paste -sd ' + ' -)"
|
||||
printf '%s' "$joined"
|
||||
fi
|
||||
}
|
||||
|
||||
infer_scope() {
|
||||
local root="$1"
|
||||
case "$root" in
|
||||
*"/__Mindleaf/"*) printf '%s' "mindleaf" ;;
|
||||
*"/Labs/"*) printf '%s' "lab" ;;
|
||||
*"/Archives_Projets/"*) printf '%s' "archive" ;;
|
||||
*) printf '%s' "perso" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
PROJECT_NAME="${PROJECT_NAME:-$(basename "$PROJECT_ROOT")}"
|
||||
STACK_INFERRED="$(infer_stack "$PROJECT_ROOT")"
|
||||
SCOPE_INFERRED="$(infer_scope "$PROJECT_ROOT")"
|
||||
STACK="${STACK_OVERRIDE:-$STACK_INFERRED}"
|
||||
SCOPE="${SCOPE_OVERRIDE:-$SCOPE_INFERRED}"
|
||||
STATE="${STATE_OVERRIDE:-dev}"
|
||||
|
||||
if ! [[ "$SCOPE" =~ ^(perso|mindleaf|lab|archive)$ ]]; then
|
||||
echo "Erreur: scope invalide '$SCOPE' (attendu: perso|mindleaf|lab|archive)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -q "^${PROJECT_NAME}|" "$PROJECTS_CONF"; then
|
||||
if [ "$SYNC_EXISTING" != "true" ]; then
|
||||
echo "OK: projet déjà présent dans _projects.conf: $PROJECT_NAME"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
existing_line="$(grep "^${PROJECT_NAME}|" "$PROJECTS_CONF" | head -n 1)"
|
||||
IFS='|' read -r _ existing_stack existing_scope existing_state <<EOF
|
||||
$existing_line
|
||||
EOF
|
||||
|
||||
# Safe sync defaults for existing entries:
|
||||
# - stack: preserve existing unless explicit override, or existing is placeholder
|
||||
# - scope/state: keep existing unless explicitly overridden
|
||||
if [ -n "$STACK_OVERRIDE" ]; then
|
||||
TARGET_STACK="$STACK_OVERRIDE"
|
||||
elif [ -z "$existing_stack" ] || [ "$existing_stack" = "stack-a-completer" ]; then
|
||||
if [ "$STACK_INFERRED" = "stack-a-completer" ] || [ -z "$STACK_INFERRED" ]; then
|
||||
TARGET_STACK="$existing_stack"
|
||||
else
|
||||
TARGET_STACK="$STACK_INFERRED"
|
||||
fi
|
||||
else
|
||||
TARGET_STACK="$existing_stack"
|
||||
fi
|
||||
|
||||
if [ -n "$SCOPE_OVERRIDE" ]; then
|
||||
TARGET_SCOPE="$SCOPE_OVERRIDE"
|
||||
else
|
||||
TARGET_SCOPE="$existing_scope"
|
||||
fi
|
||||
|
||||
if [ -n "$STATE_OVERRIDE" ]; then
|
||||
TARGET_STATE="$STATE_OVERRIDE"
|
||||
else
|
||||
TARGET_STATE="$existing_state"
|
||||
fi
|
||||
|
||||
if ! [[ "$TARGET_SCOPE" =~ ^(perso|mindleaf|lab|archive)$ ]]; then
|
||||
echo "Erreur: scope invalide '$TARGET_SCOPE' (attendu: perso|mindleaf|lab|archive)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp="$(mktemp)"
|
||||
awk -F'|' -v OFS='|' -v n="$PROJECT_NAME" -v st="$TARGET_STACK" -v sc="$TARGET_SCOPE" -v et="$TARGET_STATE" '
|
||||
$0 ~ /^#/ || NF < 4 { print; next }
|
||||
$1 == n { print $1, st, sc, et; next }
|
||||
{ print }
|
||||
' "$PROJECTS_CONF" > "$tmp"
|
||||
mv "$tmp" "$PROJECTS_CONF"
|
||||
echo "OK: projet synchronisé dans _projects.conf: $PROJECT_NAME"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
last_char="$(tail -c 1 "$PROJECTS_CONF" 2>/dev/null || true)"
|
||||
if [ -n "$last_char" ]; then
|
||||
echo >> "$PROJECTS_CONF"
|
||||
fi
|
||||
|
||||
printf '%s|%s|%s|%s\n' "$PROJECT_NAME" "$STACK" "$SCOPE" "$STATE" >> "$PROJECTS_CONF"
|
||||
echo "OK: projet ajouté à _projects.conf: $PROJECT_NAME"
|
||||
Reference in New Issue
Block a user