diff --git a/git_fetch_all.sh b/git_fetch_all.sh index 4fc2096..4505fac 100755 --- a/git_fetch_all.sh +++ b/git_fetch_all.sh @@ -10,9 +10,10 @@ # ./git_fetch_all.sh --no-push # commit까지, push 생략 # ./git_fetch_all.sh --no-commit # fetch/merge만 (commit·push 생략) # -# commit 시 운영 WAS/RAG 기본 주소(172.16.180.130)를 복원합니다. -# exdev 런타임 주소(127.0.0.1 / host.docker.internal)는 .env·start 스크립트·EXDEV_LOCAL 로만 사용하며 -# GitHub 에는 커밋하지 않습니다. +# ★ 운영(GitHub) push 전용 — 개발서버(exdev) 주소를 커밋/push 하지 않는다. +# start-all-server.sh 가 런타임 ENV 로만 exdev(127.0.0.1 / host.docker.internal)를 적용한다. +# 이 스크립트는 commit 직전에 운영 기본값(172.16.180.130)을 파일에 복원한 뒤 push 한다. +# (.env / EXDEV_LOCAL / server-dev 오버레이는 GitHub 대상이 아님) # # 대상 (.gitmodules) — 모두 branch=chatbot2.0-agent (main 사용 안 함): # chatbotApi-chatbot2.0-agent @@ -114,59 +115,104 @@ restore_monorepo_overlays() { fi } -# GitHub push 전: 로컬(exdev) WAS 주소를 커밋하지 않고 운영 기본값(172.16.180.130) 유지 -# - 런타임(exdev): start-all-server.sh / .env / EXDEV_LOCAL=true → 127.0.0.1·host.docker.internal -# - 커밋/push: 아래 복원으로 application.yml·env.template·chatbot_tool_client.py 기본값을 운영 IP로 고정 -PROD_WAS_API="http://172.16.180.130:8086/api" -PROD_RAG_CHAT="http://172.16.180.130:28012/agent/chat" +# GitHub push 전: exdev 런타임 주소를 커밋하지 않고 운영 기본값(172.16.180.130) 유지 +# - 런타임(exdev): start-all-server.sh ENV / .env / EXDEV_LOCAL=true → 127.0.0.1·host.docker.internal +# - 커밋/push: application.yml·env.template·chatbot_tool_client.py 기본값을 운영 IP로 고정 +PROD_WAS_HOST="172.16.180.130" +PROD_WAS_API="http://${PROD_WAS_HOST}:8086/api" +PROD_RAG_CHAT="http://${PROD_WAS_HOST}:28012/agent/chat" +PROD_MONGO_URI="mongodb://exDev:ehfhrhdtk!!@${PROD_WAS_HOST}:27017/chatbot?heartbeatFrequencyMS=30000&minPoolSize=8&maxIdleTimeMS=18000000" restore_production_endpoints_before_commit() { local path="$1" local dir="${ROOT_DIR}/${path}" case "${path}" in + chatbotApi-chatbot2.0-agent) + local yml="${dir}/src/main/resources/application.yml" + if [[ -f "${yml}" ]]; then + # 수동/임시로 바꾼 로컬 Mongo URI 를 운영 기본값으로 복원 (start-all 은 ENV 로만 오버라이드) + # URI 의 @ 는 perl 치환부 배열 보간을 피하기 위해 ENV 로 전달 + PROD_MONGO_URI="${PROD_MONGO_URI}" perl -i -pe \ + 's|uri:\s*mongodb://\S+|uri: $ENV{PROD_MONGO_URI}|g' "${yml}" + fi + ;; kakaoChatbotSkill-chatbot2.0-agent) local yml="${dir}/src/main/resources/application.yml" if [[ -f "${yml}" ]]; then # ${ENV:default} 형태의 default 만 운영 IP로 고정 (실행 시 ENV 로컬 오버라이드는 유지) - perl -i -pe "s|CHATBOT_API_BASE_URL:[^}]+}|CHATBOT_API_BASE_URL:${PROD_WAS_API}/}|g" "${yml}" - perl -i -pe "s|RAG_AGENT_CHAT_URL:[^}]+}|RAG_AGENT_CHAT_URL:${PROD_RAG_CHAT}}|g" "${yml}" - # trailing slash normalize for api default - perl -i -pe "s|CHATBOT_API_BASE_URL:http://172\.16\.180\.130:8086/api/\}|CHATBOT_API_BASE_URL:http://172.16.180.130:8086/api/}|g" "${yml}" - if grep -qE '127\.0\.0\.1:8086|host\.docker\.internal:8086|127\.0\.0\.1:28012' "${yml}"; then - warn "${path}: application.yml 에 로컬 주소가 남아 있을 수 있음 — 확인 필요" - fi + PROD_WAS_API="${PROD_WAS_API}" PROD_RAG_CHAT="${PROD_RAG_CHAT}" PROD_WAS_HOST="${PROD_WAS_HOST}" \ + perl -i -pe ' + s|CHATBOT_API_BASE_URL:[^}]+}|CHATBOT_API_BASE_URL:$ENV{PROD_WAS_API}/}|g; + s|RAG_AGENT_CHAT_URL:[^}]+}|RAG_AGENT_CHAT_URL:$ENV{PROD_RAG_CHAT}}|g; + s|base-url:\s*http://127\.0\.0\.1:8086/api/?|base-url: \${CHATBOT_API_BASE_URL:$ENV{PROD_WAS_API}/}|g; + s|base-url:\s*http://host\.docker\.internal:8086/api/?|base-url: \${CHATBOT_API_BASE_URL:$ENV{PROD_WAS_API}/}|g; + s|url:\s*http://127\.0\.0\.1:28012/agent/chat|url: \${RAG_AGENT_CHAT_URL:$ENV{PROD_RAG_CHAT}}|g; + s|url:\s*http://host\.docker\.internal:28012/agent/chat|url: \${RAG_AGENT_CHAT_URL:$ENV{PROD_RAG_CHAT}}|g; + ' "${yml}" fi ;; exAiChatBot-chatbot2.0-agent) if [[ -f "${dir}/env.template" ]]; then - perl -i -pe "s|^CHATBOT_API_BASE_URL=.*|CHATBOT_API_BASE_URL=${PROD_WAS_API}|" "${dir}/env.template" + PROD_WAS_API="${PROD_WAS_API}" perl -i -pe \ + 's|^CHATBOT_API_BASE_URL=.*|CHATBOT_API_BASE_URL=$ENV{PROD_WAS_API}|' "${dir}/env.template" # EXDEV_LOCAL 은 커밋 템플릿에 넣지 않음 (server-dev 전용) perl -i -ne 'print unless /^EXDEV_LOCAL=/' "${dir}/env.template" fi if [[ -f "${dir}/env.example" ]]; then - perl -i -pe "s|^CHATBOT_API_BASE_URL=.*|CHATBOT_API_BASE_URL=${PROD_WAS_API}|" "${dir}/env.example" 2>/dev/null || true + PROD_WAS_API="${PROD_WAS_API}" perl -i -pe \ + 's|^CHATBOT_API_BASE_URL=.*|CHATBOT_API_BASE_URL=$ENV{PROD_WAS_API}|' "${dir}/env.example" 2>/dev/null || true perl -i -ne 'print unless /^EXDEV_LOCAL=/' "${dir}/env.example" 2>/dev/null || true fi if [[ -f "${dir}/scripts/agent/chatbot_tool_client.py" ]]; then # 운영 기본값(_PROD_WAS_API / legacy getenv default)만 복원. - # _EXDEV_WAS_API(host.docker.internal) 는 exdev 차단용이라 건드리지 않는다. - perl -i -pe 's|_PROD_WAS_API = "http://[^"]+"|_PROD_WAS_API = "http://172.16.180.130:8086/api"|g' \ - "${dir}/scripts/agent/chatbot_tool_client.py" - perl -i -pe 's|os\.getenv\("TOOL_API_BASE_URL", "http://127\.0\.0\.1:8086/api"\)|os.getenv("TOOL_API_BASE_URL", "http://172.16.180.130:8086/api")|g' \ - "${dir}/scripts/agent/chatbot_tool_client.py" - perl -i -pe 's|os\.getenv\("TOOL_API_BASE_URL", "http://host\.docker\.internal:8086/api"\)|os.getenv("TOOL_API_BASE_URL", "http://172.16.180.130:8086/api")|g' \ - "${dir}/scripts/agent/chatbot_tool_client.py" - # 구형 한 줄 기본값 형태도 운영 IP로 고정 - perl -i -pe 's|os\.getenv\("TOOL_API_BASE_URL", "http://[^"]+"\)|os.getenv("TOOL_API_BASE_URL", "http://172.16.180.130:8086/api")|g' \ - "${dir}/scripts/agent/chatbot_tool_client.py" + PROD_WAS_API="${PROD_WAS_API}" perl -i -pe ' + s|_PROD_WAS_API = "http://[^"]+"|_PROD_WAS_API = "$ENV{PROD_WAS_API}"|g; + s|os\.getenv\("TOOL_API_BASE_URL", "http://[^"]+"\)|os.getenv("TOOL_API_BASE_URL", "$ENV{PROD_WAS_API}")|g; + s|os\.getenv\("CHATBOT_API_BASE_URL", "http://[^"]+"\)|os.getenv("CHATBOT_API_BASE_URL", "$ENV{PROD_WAS_API}")|g; + ' "${dir}/scripts/agent/chatbot_tool_client.py" fi # monorepo overlay compose 는 push 대상에서 제외 (로컬 exdev 전용) git -C "${dir}" checkout HEAD -- docker-compose.server.yml docker-compose.local.yml 2>/dev/null || true + # .env 는 gitignore — 스테이징 실수 방지 + git -C "${dir}" reset HEAD -- .env .env.local 2>/dev/null || true + rm -f "${dir}/.env.local" 2>/dev/null || true ;; esac } +# 복원 후에도 개발서버 전용 호스트가 커밋 대상 설정 파일에 남으면 push 중단 +assert_no_exdev_endpoints_for_push() { + local path="$1" + local dir="${ROOT_DIR}/${path}" + local hits="" + + case "${path}" in + chatbotApi-chatbot2.0-agent) + hits="$(grep -nE 'mongodb://(127\.0\.0\.1|localhost)|host\.docker\.internal' \ + "${dir}/src/main/resources/application.yml" 2>/dev/null || true)" + ;; + kakaoChatbotSkill-chatbot2.0-agent) + hits="$(grep -nE '127\.0\.0\.1:(8086|28012)|host\.docker\.internal:(8086|28012)' \ + "${dir}/src/main/resources/application.yml" 2>/dev/null || true)" + ;; + exAiChatBot-chatbot2.0-agent) + hits="$(grep -nE '^(CHATBOT_API_BASE_URL|TOOL_API_BASE_URL)=.*(127\.0\.0\.1|host\.docker\.internal)|EXDEV_LOCAL=' \ + "${dir}/env.template" "${dir}/env.example" 2>/dev/null || true)" + hits+="$(grep -nE 'getenv\(\"TOOL_API_BASE_URL\", \"http://(127\.0\.0\.1|host\.docker\.internal)' \ + "${dir}/scripts/agent/chatbot_tool_client.py" 2>/dev/null || true)" + ;; + esac + + if [[ -n "${hits}" ]]; then + warn "${path}: 개발서버(exdev) 주소가 남아 push 중단" + echo "${hits}" | sed 's/^/ /' + warn "start-all-server.sh 런타임 ENV 로만 exdev 주소를 쓰고, 소스 기본값은 운영 IP 를 유지하세요" + return 1 + fi + return 0 +} + submodule_is_cloned() { local path="$1" [[ -e "${ROOT_DIR}/${path}/.git" ]] @@ -310,16 +356,27 @@ sync_one() { fi fi - # 5) 로컬 수정사항 commit + # 5) 로컬 수정사항 commit (exdev 주소는 복원 후·검증 통과 시에만) if $DO_COMMIT && repo_is_dirty; then log " 로컬 변경 commit..." - # push 전에 운영 WAS/RAG 기본 주소 복원 (exdev 로컬 주소는 .env / start 스크립트로만 사용) + # push 전에 운영 WAS/RAG/Mongo 기본 주소 복원 (exdev 주소는 start-all-server.sh ENV 전용) restore_production_endpoints_before_commit "${path}" - log " 운영 엔드포인트 기본값 유지: ${PROD_WAS_API}" + if ! assert_no_exdev_endpoints_for_push "${path}"; then + exit 1 + fi + log " 운영 엔드포인트 기본값 유지: WAS ${PROD_WAS_API} / Mongo ${PROD_WAS_HOST}" git add -A + # .env 등 ignore 대상이 스테이징되지 않도록 한 번 더 정리 + git reset HEAD -- .env .env.local 2>/dev/null || true if git diff --cached --quiet; then log " staged 변경 없음 (ignore 된 파일만 있을 수 있음)" else + # staged diff 에 exdev 호스트가 남아 있으면 push 금지 + if git diff --cached -U0 | grep -E '^\+' | grep -qE '127\.0\.0\.1:(27017|8086|28012)|host\.docker\.internal|EXDEV_LOCAL=true'; then + warn "${path}: staged diff 에 개발서버 주소가 포함됨 — commit 중단" + git diff --cached --stat | sed 's/^/ /' + exit 1 + fi git commit -m "$(cat </dev/null || true + if ! git diff --cached --quiet; then + git commit -m "$(cat </dev/null || echo 0)" if [[ "${ahead}" != "0" ]]; then log " push origin ${branch} (ahead ${ahead})..." diff --git a/server-dev/start-all-server.sh b/server-dev/start-all-server.sh index d1b3725..df73ab1 100755 --- a/server-dev/start-all-server.sh +++ b/server-dev/start-all-server.sh @@ -11,6 +11,13 @@ # ./server-dev/start-all-server.sh --skip-oracle # TROAD Oracle 기동 생략 # ./server-dev/start-all-server.sh --local # 로컬 Mac 개발 모드 (local-dev 위임) # +# ★ 개발서버(exdev) 주소/설정은 이 스크립트가 런타임 ENV 로만 적용한다. +# - WAS Mongo → 127.0.0.1 (SPRING_DATA_MONGODB_URI) +# - Skill → 로컬 WAS/RAG (CHATBOT_API_BASE_URL, RAG_AGENT_CHAT_URL) +# - RAG .env → host.docker.internal + EXDEV_LOCAL=true +# application.yml 등 커밋 파일은 운영 기본값(172.16.180.130)을 유지한다. +# 공식 GitHub 반영은 ./git_fetch_all.sh 전용 (exdev 주소를 push 하지 않음). +# # 로컬 Mac 실행 시: Gitea(exdev) 최신 merge → 현재 소스 commit/push → 원격 배포. # 공식 GitHub(KoreaExpressWayCorp) push 는 하지 않음 — ./git_fetch_all.sh 전용. set -euo pipefail @@ -41,6 +48,8 @@ MONGO_CONTAINER="${MONGO_CONTAINER:-exaichatbot-agent-mongo}" ORACLE_CONTAINER="${ORACLE_CONTAINER:-exaichatbot-agent-oracle-troad}" INTERNAL_TOOL_API_KEY="${INTERNAL_TOOL_API_KEY:-exdev-agent-tool-key}" PUBLIC_BASE_URL="${PUBLIC_BASE_URL:-https://chatbot.exdev.co.kr}" +# exdev 전용 — 소스(application.yml)를 수정하지 않고 ENV 로만 주입 +EXDEV_MONGO_URI="${EXDEV_MONGO_URI:-mongodb://127.0.0.1:27017/chatbot?heartbeatFrequencyMS=30000&minPoolSize=8&maxIdleTimeMS=18000000}" LLM_PORT="${LLM_PORT:-16000}" EMBED_PORT="${EMBED_PORT:-16001}" @@ -551,19 +560,30 @@ start_java_service() { kakaoChatbotSkill) port="${SKILL_PORT}" ;; esac + # exdev ENV(로컬 Mongo/WAS/RAG) 재적용을 위해 기존 프로세스는 항상 재기동한다. if [[ -f "${pid_file}" ]]; then local old_pid old_pid="$(cat "${pid_file}")" if kill -0 "$old_pid" 2>/dev/null; then - if [[ -n "${port}" ]] && lsof -iTCP:"${port}" -sTCP:LISTEN >/dev/null 2>&1; then - log "${name} 이미 실행 중 (PID ${old_pid}, :${port})" - return 0 - fi - # pid 는 있으나 포트 미개방 → 좀비/실패 프로세스 정리 + log "${name} 재기동 (기존 PID ${old_pid})" kill "$old_pid" 2>/dev/null || true + sleep 2 + kill -9 "$old_pid" 2>/dev/null || true fi rm -f "${pid_file}" fi + if [[ -n "${port}" ]]; then + local pids + pids="$(lsof -tiTCP:"${port}" -sTCP:LISTEN 2>/dev/null || true)" + if [[ -n "${pids}" ]]; then + log "${name} :${port} 점유 프로세스 종료" + # shellcheck disable=SC2086 + kill ${pids} 2>/dev/null || true + sleep 1 + # shellcheck disable=SC2086 + kill -9 ${pids} 2>/dev/null || true + fi + fi [[ -n "${JAVA_HOME}" ]] || ensure_java chmod +x "${dir}/gradlew" @@ -703,6 +723,7 @@ start_rag if ! $SKIP_JAVA; then ensure_java # Skill 먼저 (WAS WEB tool 이 Skill data-portal 을 역호출) + log "exdev Java ENV: Skill→127.0.0.1 WAS/RAG, WAS Mongo→127.0.0.1 (소스 yml 미변경)" start_java_service "kakaoChatbotSkill" "${SKILL_DIR}" \ "${RUN_DIR}/kakao-skill.pid" "${LOG_DIR}/kakao-skill.log" \ "EXDEV_LOCAL=true" \ @@ -719,6 +740,7 @@ if ! $SKIP_JAVA; then "SKILL_INTERNAL_BASE_URL=http://127.0.0.1:${SKILL_PORT}" \ "RAG_SERVER_HOST=127.0.0.1" \ "RAG_SERVER_PORT=${RAG_PORT}" \ + "SPRING_DATA_MONGODB_URI=${EXDEV_MONGO_URI}" \ || warn "chatbotApi 기동 실패" fi