157 lines
6.1 KiB
Bash
Executable file
157 lines
6.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ── 경로 설정 ────────────────────────────────────────────────────────────────
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
AGENT_OPS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
PROJECT_ROOT="$(cd "$AGENT_OPS_DIR/.." && pwd)"
|
|
|
|
# ── 색상 ─────────────────────────────────────────────────────────────────────
|
|
RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; RESET='\033[0m'
|
|
|
|
# ── 대상 경로 해석 (폴더명 / 상대경로 / 절대경로) ────────────────────────────
|
|
resolve_target() {
|
|
local input="$1"
|
|
if [[ "$input" == /* ]]; then
|
|
[[ -d "$input" ]] && echo "$input" || echo ""
|
|
return
|
|
fi
|
|
if [[ "$input" == */* ]]; then
|
|
local resolved
|
|
resolved="$(cd "$input" 2>/dev/null && pwd)" || { echo ""; return; }
|
|
echo "$resolved"
|
|
return
|
|
fi
|
|
local sibling="$(dirname "$PROJECT_ROOT")/$input"
|
|
[[ -d "$sibling" ]] && echo "$sibling" || echo ""
|
|
}
|
|
|
|
# ── 버전 비교: v1 > v2 이면 0 반환 ───────────────────────────────────────────
|
|
version_gt() {
|
|
local v1="$1" v2="$2"
|
|
[[ "$v1" == "$v2" ]] && return 1
|
|
[[ "$(printf '%s\n%s' "$v1" "$v2" | sort -V | head -1)" == "$v2" ]]
|
|
}
|
|
|
|
# ── 버전 +1 ──────────────────────────────────────────────────────────────────
|
|
bump_version() {
|
|
bash "$SCRIPT_DIR/bump-version.sh" "$1"
|
|
}
|
|
|
|
# ── common 폴더 동기화 (삭제된 파일도 반영) ───────────────────────────────────
|
|
sync_common() {
|
|
local src="$1" dst="$2"
|
|
for folder in rules/common skills/common; do
|
|
rm -rf "$dst/$folder"
|
|
mkdir -p "$dst/$folder"
|
|
cp -r "$src/$folder/." "$dst/$folder/"
|
|
done
|
|
}
|
|
|
|
# ── rules.md 내용을 진입 파일들에 반영 ───────────────────────────────────────
|
|
apply_entry_files() {
|
|
local rules_md="$1"
|
|
local target_root="$2"
|
|
|
|
if [[ ! -f "$rules_md" ]]; then
|
|
echo -e "${YELLOW} rules.md 없음, 진입 파일 재적용 건너뜀${RESET}"
|
|
return
|
|
fi
|
|
|
|
# 기본 자동 생성/갱신 대상
|
|
local default_files=("CLAUDE.md" "GEMINI.md" ".cursorrules" "AGENTS.md")
|
|
# 존재할 때만 갱신
|
|
local optional_files=(".clinerules")
|
|
|
|
for f in "${default_files[@]}"; do
|
|
cp "$rules_md" "$target_root/$f"
|
|
echo " 진입 파일 적용: $f"
|
|
done
|
|
|
|
for f in "${optional_files[@]}"; do
|
|
if [[ -f "$target_root/$f" ]]; then
|
|
cp "$rules_md" "$target_root/$f"
|
|
echo " 진입 파일 적용: $f"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# ── 사용법 ────────────────────────────────────────────────────────────────────
|
|
usage() {
|
|
echo "사용법: $0 <target>"
|
|
echo ""
|
|
echo " 현재 프로젝트 → target 으로 동기화"
|
|
echo ""
|
|
echo " target: 폴더명 (동일 레벨 탐색) | 상대경로 | 절대경로"
|
|
}
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
TARGET_INPUT="${1:-}"
|
|
if [[ -z "$TARGET_INPUT" ]]; then
|
|
usage; exit 1
|
|
fi
|
|
|
|
TARGET="$(resolve_target "$TARGET_INPUT")"
|
|
if [[ -z "$TARGET" ]]; then
|
|
echo -e "${RED}Error: 대상을 찾을 수 없습니다: $TARGET_INPUT${RESET}"
|
|
exit 1
|
|
fi
|
|
|
|
SRC_AO="$AGENT_OPS_DIR"
|
|
DST_AO="$TARGET/agent-ops"
|
|
IS_FRAMEWORK="$([[ -f "$PROJECT_ROOT/.agent-ops-source" ]] && echo "1" || echo "0")"
|
|
|
|
echo "▶ $(basename "$PROJECT_ROOT") → $(basename "$TARGET")"
|
|
|
|
# ── agentic-framework에서 다른 프로젝트로 ────────────────────────────────────
|
|
if [[ "$IS_FRAMEWORK" == "1" ]]; then
|
|
RULES_MD="$SRC_AO/rules/common/rules.md"
|
|
|
|
if [[ ! -d "$DST_AO" ]]; then
|
|
echo " 최초 진행: agent-ops 전체 복사"
|
|
cp -r "$SRC_AO" "$TARGET/"
|
|
rm -f "$DST_AO/rules/common/rules.md"
|
|
else
|
|
echo " 이후 진행: common/ 동기화"
|
|
sync_common "$SRC_AO" "$DST_AO"
|
|
rm -f "$DST_AO/rules/common/rules.md"
|
|
fi
|
|
|
|
apply_entry_files "$RULES_MD" "$TARGET"
|
|
echo -e "${GREEN}✓ 완료 → $(basename "$TARGET")${RESET}"
|
|
exit 0
|
|
fi
|
|
|
|
# ── 일반 프로젝트에서 agentic-framework로 ────────────────────────────────────
|
|
if [[ ! -f "$TARGET/.agent-ops-source" ]]; then
|
|
echo -e "${RED}Error: target이 agentic-framework가 아닙니다 (.agent-ops-source 없음)${RESET}"
|
|
exit 1
|
|
fi
|
|
|
|
SRC_VER="$(cat "$SRC_AO/.version" 2>/dev/null || echo "0.0.0")"
|
|
DST_VER="$(cat "$DST_AO/.version" 2>/dev/null || echo "0.0.0")"
|
|
echo " 현재 버전: $SRC_VER | framework 버전: $DST_VER"
|
|
|
|
if version_gt "$DST_VER" "$SRC_VER"; then
|
|
sync_common "$SRC_AO" "$DST_AO"
|
|
echo -e "${RED}⚠ 버전 충돌: framework($DST_VER) > current($SRC_VER)${RESET}"
|
|
echo -e "${YELLOW} 파일은 복사됐지만 push하지 않았습니다. 수동 머지 후 재시도하세요.${RESET}"
|
|
exit 1
|
|
fi
|
|
|
|
NEW_VER="$(bump_version "$SRC_VER")"
|
|
sync_common "$SRC_AO" "$DST_AO"
|
|
echo "$NEW_VER" > "$SRC_AO/.version"
|
|
echo "$NEW_VER" > "$DST_AO/.version"
|
|
|
|
cd "$TARGET"
|
|
git add agent-ops/rules/common agent-ops/skills/common agent-ops/.version
|
|
git commit -m "sync: from $(basename "$PROJECT_ROOT") v$NEW_VER"
|
|
git push
|
|
cd "$PROJECT_ROOT"
|
|
|
|
git add agent-ops/rules/common agent-ops/skills/common agent-ops/.version
|
|
git commit -m "sync: to agentic-framework v$NEW_VER"
|
|
git push
|
|
|
|
echo -e "${GREEN}✓ 완료 (v$SRC_VER → v$NEW_VER)${RESET}"
|