All checks were successful
Deploy to Production / deploy (push) Successful in 1m37s
Add import, sync, and push capabilities between factoryOps and the digital-twin (BaSyx AAS) backend. Includes: - Equipment sync service with field mapping and LWW conflict resolution - Import preview modal with already-imported detection - Bidirectional sync (pull updates + push local changes) - Sync history tracking via equipment_sync_history table - Machine detail page shows sync status and change history - Docker networking for container-to-container communication - UI fixes: responsive layout (375px), touch targets, section spacing - 30 test cases for sync service
335 lines
10 KiB
Bash
Executable File
335 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# FactoryOps v2 개발 환경 시작 스크립트 (Podman)
|
|
|
|
# 색상 정의
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
# 스크립트 위치 기준으로 프로젝트 루트 이동
|
|
cd "$(dirname "$0")" || exit 1
|
|
|
|
COMPOSE_FILE="docker-compose.dev.yml"
|
|
PROJECT_NAME="factoryops-dev"
|
|
|
|
# 도움말
|
|
show_help() {
|
|
echo "사용법: $0 [OPTIONS]"
|
|
echo ""
|
|
echo "옵션:"
|
|
echo " -l, --logs 로그 표시 모드 (기본: 백그라운드)"
|
|
echo " -c, --clean 완전 초기화 (볼륨 포함 모든 리소스 삭제)"
|
|
echo " -r, --rebuild 이미지 강제 재빌드"
|
|
echo " -h, --help 도움말 표시"
|
|
echo ""
|
|
echo "실행 예시:"
|
|
echo " $0 # 빠른 시작 (기존 이미지 재사용)"
|
|
echo " $0 -l # 로그 표시 모드"
|
|
echo " $0 -r # 이미지 재빌드"
|
|
echo " $0 -c # 완전 초기화 후 시작"
|
|
echo " $0 -c -r # 완전 초기화 + 이미지 재빌드"
|
|
echo ""
|
|
echo "서비스:"
|
|
echo " PostgreSQL → localhost:5432"
|
|
echo " FastAPI → localhost:8000 (uvicorn --reload)"
|
|
echo " Next.js → localhost:3100 (npm run dev)"
|
|
}
|
|
|
|
# Podman 설치 확인
|
|
check_podman() {
|
|
if ! command -v podman &> /dev/null; then
|
|
echo -e "${RED}Podman이 설치되어 있지 않습니다.${NC}"
|
|
echo "설치: brew install podman"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Podman Machine 상태 확인 및 복구 (macOS)
|
|
check_and_fix_podman() {
|
|
echo -e "${BLUE}Podman 상태 확인 중...${NC}"
|
|
|
|
# Linux에서는 Podman Machine 불필요
|
|
if [[ "$(uname -s)" != "Darwin" ]]; then
|
|
if podman ps >/dev/null 2>&1; then
|
|
echo -e "${GREEN} Podman 정상 작동${NC}"
|
|
return 0
|
|
else
|
|
echo -e "${RED} Podman 연결 실패${NC}"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# macOS: Podman Machine 확인
|
|
if ! podman machine list 2>/dev/null | grep -q "Running"; then
|
|
echo -e "${YELLOW} Podman Machine이 실행되지 않았습니다. 시작 중...${NC}"
|
|
podman machine start 2>/dev/null || {
|
|
echo -e "${YELLOW} Podman Machine 초기화 중...${NC}"
|
|
podman machine init --cpus 4 --memory 8192
|
|
podman machine start
|
|
}
|
|
sleep 3
|
|
fi
|
|
|
|
# 연결 테스트 (최대 3회)
|
|
local max_attempts=3
|
|
local attempt=1
|
|
|
|
while [ $attempt -le $max_attempts ]; do
|
|
if podman ps >/dev/null 2>&1; then
|
|
echo -e "${GREEN} Podman 정상 작동${NC}"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${YELLOW} 연결 실패. 복구 시도 ($attempt/$max_attempts)...${NC}"
|
|
|
|
pkill -9 -f "gvproxy" 2>/dev/null || true
|
|
sleep 2
|
|
|
|
podman machine stop 2>/dev/null || true
|
|
sleep 2
|
|
podman machine start 2>/dev/null || {
|
|
echo -e "${RED} Podman Machine 재시작 실패${NC}"
|
|
podman machine rm -f podman-machine-default 2>/dev/null || true
|
|
podman machine init --cpus 4 --memory 8192
|
|
podman machine start
|
|
}
|
|
|
|
sleep 3
|
|
attempt=$((attempt + 1))
|
|
done
|
|
|
|
echo -e "${RED}Podman 복구 실패. 수동으로 확인해주세요:${NC}"
|
|
echo " podman machine stop && podman machine start"
|
|
exit 1
|
|
}
|
|
|
|
# factoryops-dev 관련 리소스만 정리 (다른 프로젝트 보존)
|
|
cleanup_project_resources() {
|
|
echo -e "${BLUE}FactoryOps 개발 리소스 정리 중...${NC}"
|
|
echo ""
|
|
|
|
# 1. 실행 중인 컨테이너 중지
|
|
echo -e "${BLUE} [1/5] 컨테이너 중지 및 제거...${NC}"
|
|
local containers=$(podman ps -aq --filter "name=factoryops-dev" 2>/dev/null || true)
|
|
if [ -n "$containers" ]; then
|
|
echo "$containers" | xargs -r podman stop -t 5 2>/dev/null || true
|
|
echo "$containers" | xargs -r podman rm -f 2>/dev/null || true
|
|
echo -e "${GREEN} 컨테이너 제거 완료${NC}"
|
|
else
|
|
echo -e "${GREEN} 제거할 컨테이너 없음${NC}"
|
|
fi
|
|
|
|
# 2. Pod 정리
|
|
echo -e "${BLUE} [2/5] Pod 정리...${NC}"
|
|
local pods=$(podman pod ls --filter "name=factoryops" --format "{{.ID}}" 2>/dev/null || true)
|
|
if [ -n "$pods" ]; then
|
|
echo "$pods" | xargs -r podman pod rm -f 2>/dev/null || true
|
|
echo -e "${GREEN} Pod 제거 완료${NC}"
|
|
else
|
|
echo -e "${GREEN} 제거할 Pod 없음${NC}"
|
|
fi
|
|
|
|
# 3. 네트워크 정리
|
|
echo -e "${BLUE} [3/5] 네트워크 정리...${NC}"
|
|
local networks=$(podman network ls --format "{{.Name}}" 2>/dev/null | grep "factoryops-dev" || true)
|
|
if [ -n "$networks" ]; then
|
|
echo "$networks" | xargs -r podman network rm -f 2>/dev/null || true
|
|
echo -e "${GREEN} 네트워크 제거 완료${NC}"
|
|
else
|
|
echo -e "${GREEN} 제거할 네트워크 없음${NC}"
|
|
fi
|
|
|
|
# 4. 볼륨 정리
|
|
echo -e "${BLUE} [4/5] 볼륨 정리...${NC}"
|
|
local volumes=$(podman volume ls --format "{{.Name}}" 2>/dev/null | grep "factoryops" || true)
|
|
if [ -n "$volumes" ]; then
|
|
echo "$volumes" | xargs -r podman volume rm -f 2>/dev/null || true
|
|
echo -e "${GREEN} 볼륨 제거 완료 (DB 데이터 포함)${NC}"
|
|
else
|
|
echo -e "${GREEN} 제거할 볼륨 없음${NC}"
|
|
fi
|
|
|
|
# 5. 이미지 정리
|
|
echo -e "${BLUE} [5/5] 이미지 정리...${NC}"
|
|
local images=$(podman images --format "{{.ID}} {{.Repository}}" 2>/dev/null | grep "factoryops" | awk '{print $1}' || true)
|
|
if [ -n "$images" ]; then
|
|
echo "$images" | xargs -r podman rmi -f 2>/dev/null || true
|
|
echo -e "${GREEN} 이미지 제거 완료${NC}"
|
|
else
|
|
echo -e "${GREEN} 제거할 이미지 없음${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${GREEN} 초기화 완료 (다른 프로젝트 리소스 보존됨)${NC}"
|
|
echo ""
|
|
}
|
|
|
|
# 포트 충돌 확인 및 해결
|
|
check_and_free_ports() {
|
|
echo -e "${BLUE}포트 사용 확인 중...${NC}"
|
|
|
|
local ports=(8000 3100)
|
|
local port_names=("FastAPI" "Next.js")
|
|
local ports_freed=false
|
|
|
|
for i in "${!ports[@]}"; do
|
|
local port=${ports[$i]}
|
|
local name=${port_names[$i]}
|
|
if lsof -ti:$port >/dev/null 2>&1; then
|
|
echo -e "${YELLOW} 포트 $port ($name) 사용 중 → 프로세스 종료${NC}"
|
|
lsof -ti:$port | xargs kill -9 2>/dev/null || true
|
|
ports_freed=true
|
|
sleep 1
|
|
fi
|
|
done
|
|
|
|
if [ "$ports_freed" = true ]; then
|
|
echo -e "${GREEN} 포트 정리 완료${NC}"
|
|
sleep 2
|
|
else
|
|
echo -e "${GREEN} 모든 포트 사용 가능${NC}"
|
|
fi
|
|
}
|
|
|
|
# 서비스 헬스체크 대기
|
|
wait_for_services() {
|
|
echo ""
|
|
echo -e "${BLUE}서비스 준비 대기 중...${NC}"
|
|
|
|
# API 대기
|
|
waited=0
|
|
echo -ne "${BLUE} FastAPI "
|
|
while [ $waited -lt $max_wait ]; do
|
|
if curl -sf http://localhost:8000/api/health >/dev/null 2>&1; then
|
|
echo -e " ${GREEN}ready${NC}"
|
|
break
|
|
fi
|
|
echo -n "."
|
|
sleep 2
|
|
waited=$((waited + 2))
|
|
done
|
|
if [ $waited -ge $max_wait ]; then
|
|
echo -e " ${YELLOW}timeout (로그를 확인하세요)${NC}"
|
|
fi
|
|
|
|
# Dashboard 대기 (npm install이 오래 걸릴 수 있음)
|
|
waited=0
|
|
max_wait=120
|
|
echo -ne "${BLUE} Next.js "
|
|
while [ $waited -lt $max_wait ]; do
|
|
if curl -sf http://localhost:3100 >/dev/null 2>&1; then
|
|
echo -e " ${GREEN}ready${NC}"
|
|
break
|
|
fi
|
|
echo -n "."
|
|
sleep 3
|
|
waited=$((waited + 3))
|
|
done
|
|
if [ $waited -ge $max_wait ]; then
|
|
echo -e " ${YELLOW}아직 준비 중 (npm install 진행 중일 수 있음)${NC}"
|
|
fi
|
|
}
|
|
|
|
# ─── 인자 파싱 ───
|
|
SHOW_LOGS=false
|
|
FULL_CLEAN=false
|
|
FORCE_REBUILD=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-l|--logs) SHOW_LOGS=true; shift ;;
|
|
-c|--clean) FULL_CLEAN=true; shift ;;
|
|
-r|--rebuild) FORCE_REBUILD=true; shift ;;
|
|
-h|--help) show_help; exit 0 ;;
|
|
*) echo "알 수 없는 옵션: $1"; show_help; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ─── 실행 시작 ───
|
|
echo -e "${CYAN}"
|
|
echo "================================================="
|
|
echo " FactoryOps v2 개발 환경 시작"
|
|
echo "================================================="
|
|
echo -e "${NC}"
|
|
|
|
check_podman
|
|
check_and_fix_podman
|
|
|
|
# 완전 초기화 또는 빠른 시작
|
|
if [ "$FULL_CLEAN" = true ]; then
|
|
echo -e "${YELLOW}완전 초기화 모드 (-c)${NC}"
|
|
echo -e "${YELLOW} factoryops 관련 리소스만 삭제됩니다 (볼륨/DB 포함)${NC}"
|
|
echo ""
|
|
cleanup_project_resources
|
|
else
|
|
echo -e "${GREEN}빠른 시작 모드 (기존 리소스 재사용)${NC}"
|
|
echo -e "${BLUE} 완전 초기화가 필요하면: $0 -c${NC}"
|
|
echo ""
|
|
|
|
# 실행 중인 컨테이너만 중지
|
|
running=$(podman ps -q --filter "name=factoryops-dev" 2>/dev/null || true)
|
|
if [ -n "$running" ]; then
|
|
echo -e "${YELLOW} 기존 컨테이너 중지 중...${NC}"
|
|
echo "$running" | xargs -r podman stop -t 5 2>/dev/null || true
|
|
echo -e "${GREEN} 기존 컨테이너 중지 완료${NC}"
|
|
fi
|
|
echo ""
|
|
fi
|
|
|
|
check_and_free_ports
|
|
|
|
# 빌드 & 실행 옵션
|
|
BUILD_OPTIONS=""
|
|
RUN_OPTIONS=""
|
|
|
|
if [ "$FORCE_REBUILD" = true ]; then
|
|
BUILD_OPTIONS="--build --no-cache"
|
|
echo -e "${BLUE}이미지 재빌드 모드 활성화 (-r)${NC}"
|
|
else
|
|
echo -e "${GREEN}기존 이미지 재사용 (재빌드: $0 -r)${NC}"
|
|
fi
|
|
|
|
if [ "$SHOW_LOGS" = false ]; then
|
|
RUN_OPTIONS="-d"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BLUE}서비스 시작 중...${NC}"
|
|
|
|
# compose 실행
|
|
podman compose -f "$COMPOSE_FILE" up $RUN_OPTIONS $BUILD_OPTIONS 2>&1 | \
|
|
grep -v "WARNING" || true
|
|
|
|
if [ "$SHOW_LOGS" = false ]; then
|
|
wait_for_services
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${CYAN}"
|
|
echo "================================================="
|
|
echo " FactoryOps v2 개발 환경 시작 완료"
|
|
echo "================================================="
|
|
echo -e "${NC}"
|
|
echo " 서비스 접속:"
|
|
echo " Frontend http://localhost:3100"
|
|
echo " Backend http://localhost:8000"
|
|
echo " API Docs http://localhost:8000/docs"
|
|
echo " Database 211.115.91.141:8200 (원격 DB)"
|
|
echo ""
|
|
|
|
if [ "$SHOW_LOGS" = false ]; then
|
|
echo " 로그 확인:"
|
|
echo " podman compose -f $COMPOSE_FILE logs -f"
|
|
echo " podman compose -f $COMPOSE_FILE logs -f api"
|
|
echo " podman compose -f $COMPOSE_FILE logs -f dashboard"
|
|
echo ""
|
|
fi
|
|
|
|
echo " 중지:"
|
|
echo " ./stop-dev.sh"
|
|
echo ""
|