Files
exAichatbot_agent/git_fetch_all.sh
T

205 lines
6.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# GitHub upstream → monorepo submodule 최신 소스 반영 (pull only, push 없음)
#
# ./git_fetch_all.sh # 4개 submodule fetch + fast-forward
# ./git_fetch_all.sh --init # submodule 미초기화 시 clone 포함
# ./git_fetch_all.sh --dry-run # 실행 없이 변경 예상만 출력
#
# 대상 (.gitmodules):
# chatbotApp-chatbot2.0-agent → KoreaExpressWayCorp/chatbotApp (chatbot2.0-agent)
# chatbotApi-chatbot2.0-agent → KoreaExpressWayCorp/chatbotApi (chatbot2.0-agent)
# exAiChatBot-chatbot2.0-agent → KoreaExpressWayCorp/exAiChatBot (chatbot2.0-agent)
# kakaoChatbotSkill-chatbot2.0-agent → KoreaExpressWayCorp/kakaoChatbotSkill (chatbot2.0-agent)
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# bare repo 배포 시 상위에서 GIT_DIR 이 export 되면 submodule git 이 깨짐
MONOREPO_GIT_DIR="${MONOREPO_GIT_DIR:-${GIT_DIR:-}}"
unset GIT_DIR GIT_WORK_TREE
INIT=false
DRY_RUN=false
for arg in "$@"; do
case "$arg" in
--init) INIT=true ;;
--dry-run) DRY_RUN=true ;;
-h|--help)
sed -n '2,14p' "$0"
exit 0
;;
*)
echo "알 수 없는 옵션: $arg (--help)"
exit 1
;;
esac
done
log() { echo "[git_fetch_all] $*"; }
warn() { echo "[git_fetch_all] ⚠️ $*" >&2; }
cd "${ROOT_DIR}"
if [[ ! -f .gitmodules ]]; then
echo "ERROR: .gitmodules 없음 — submodule 미설정"
exit 1
fi
SUBMODULE_PATHS=()
while IFS= read -r _path; do
[[ -n "${_path}" ]] && SUBMODULE_PATHS+=("${_path}")
done < <(git config -f .gitmodules --get-regexp '^submodule\..*\.path$' | awk '{print $2}')
if [[ ${#SUBMODULE_PATHS[@]} -eq 0 ]]; then
echo "ERROR: .gitmodules 에 submodule 경로 없음"
exit 1
fi
if $INIT && ! $DRY_RUN; then
log "submodule init (direct clone)..."
fi
resolve_monorepo_git_dir() {
if [[ -n "${MONOREPO_GIT_DIR}" && -d "${MONOREPO_GIT_DIR}" ]]; then
echo "${MONOREPO_GIT_DIR}"
elif git -C "${ROOT_DIR}" rev-parse --git-dir >/dev/null 2>&1; then
git -C "${ROOT_DIR}" rev-parse --git-dir
fi
}
submodule_pinned_sha() {
local path="$1"
local git_dir
git_dir="$(resolve_monorepo_git_dir || true)"
[[ -n "${git_dir}" ]] || return 0
git --git-dir="${git_dir}" ls-tree HEAD "${path}" 2>/dev/null | awk '{print $3}'
}
clone_submodule_repo() {
local path="$1" url="$2" branch="$3"
local target="${ROOT_DIR}/${path}"
local sha
sha="$(submodule_pinned_sha "${path}" || true)"
log " clone ${url} → ${path} (branch=${branch})"
rm -rf "${target}"
if ! git clone --branch "${branch}" --single-branch "${url}" "${target}"; then
warn "${path} — clone 실패 (서버 GitHub 미접속 시 sync-submodules-rsync.sh 사용)"
return 1
fi
if [[ -n "${sha}" ]]; then
git -C "${target}" checkout "${sha}" 2>/dev/null || true
fi
}
restore_monorepo_overlays() {
if [[ -f "${ROOT_DIR}/local-dev/docker-compose.rag.local.yml" ]]; then
cp "${ROOT_DIR}/local-dev/docker-compose.rag.local.yml" \
"${ROOT_DIR}/exAiChatBot-chatbot2.0-agent/docker-compose.local.yml"
log "복원: exAiChatBot/docker-compose.local.yml (monorepo overlay)"
fi
if [[ -f "${ROOT_DIR}/server-dev/docker-compose.rag.server.yml" ]]; then
cp "${ROOT_DIR}/server-dev/docker-compose.rag.server.yml" \
"${ROOT_DIR}/exAiChatBot-chatbot2.0-agent/docker-compose.server.yml"
log "복원: exAiChatBot/docker-compose.server.yml (monorepo overlay)"
fi
}
submodule_is_cloned() {
local path="$1"
[[ -e "${ROOT_DIR}/${path}/.git" ]]
}
fetch_one() {
local path="$1"
local url branch old new dirty
url="$(git config -f .gitmodules "submodule.${path}.url")"
branch="$(git config -f .gitmodules "submodule.${path}.branch" || echo main)"
branch="${branch:-main}"
log ">>> ${path}"
log " url=${url} branch=${branch}"
if ! submodule_is_cloned "${path}"; then
if $DRY_RUN; then
log " [dry-run] submodule clone 필요 — ./git_fetch_all.sh --init"
return 0
fi
if $INIT; then
clone_submodule_repo "${path}" "${url}" "${branch}" || return 1
else
warn "${path} — submodule 미초기화. --init 옵션 사용"
return 1
fi
fi
(
cd "${ROOT_DIR}/${path}"
if ! git diff --quiet || ! git diff --cached --quiet; then
dirty=yes
warn "${path} — 로컬 변경 있음 (fetch는 진행, fast-forward 실패 가능)"
else
dirty=no
fi
old="$(git rev-parse HEAD 2>/dev/null || echo none)"
if $DRY_RUN; then
git fetch origin "${branch}" 2>/dev/null || git fetch origin
new="$(git rev-parse "origin/${branch}" 2>/dev/null || echo unknown)"
if [[ "${old}" == "${new}" ]]; then
log " [dry-run] 이미 최신: ${old:0:7}"
else
log " [dry-run] ${old:0:7} → ${new:0:7}"
git log --oneline "${old}..origin/${branch}" 2>/dev/null | sed 's/^/ /' || true
fi
exit 0
fi
git fetch origin "${branch}"
git checkout "${branch}" 2>/dev/null || git checkout -B "${branch}" "origin/${branch}"
if git merge-base --is-ancestor HEAD "origin/${branch}" 2>/dev/null \
&& [[ "$(git rev-parse HEAD)" != "$(git rev-parse "origin/${branch}")" ]]; then
git merge --ff-only "origin/${branch}"
elif [[ "$(git rev-parse HEAD)" != "$(git rev-parse "origin/${branch}")" ]]; then
warn "${path} — fast-forward 불가 (로컬 커밋/변경 존재). 수동 merge 필요"
git status -sb | sed 's/^/ /'
exit 1
fi
new="$(git rev-parse HEAD)"
if [[ "${old}" == "${new}" ]]; then
log " ✅ 최신 유지 $(git log -1 --oneline)"
else
log " ✅ 갱신 ${old:0:7} → ${new:0:7} $(git log -1 --oneline)"
fi
)
}
failures=0
for path in "${SUBMODULE_PATHS[@]}"; do
if ! fetch_one "${path}"; then
failures=$((failures + 1))
fi
echo ""
done
if ! $DRY_RUN; then
restore_monorepo_overlays
fi
log "=========================================="
log "submodule 상태:"
git submodule status || true
log "=========================================="
if [[ ${failures} -gt 0 ]]; then
warn "실패 ${failures}개 — 로그 확인"
exit 1
fi
log "완료 — GitHub → 로컬 반영 (push 없음)"
log "monorepo 커밋 갱신: git add .gitmodules *-chatbot2.0-agent && git status"