# arko_renual — 개발서버(csv.zioinfo.co.kr) 자동 배포 파이프라인 # # ┌ 설계 배경 ─────────────────────────────────────────────────────────────┐ # │ 이 서버(zio-server)는 2코어 / 메모리 여유 1G에 40개 이상의 서비스가 │ # │ 동거한다. 실제로 구축 중 39분간 응답 불능 후 재부팅된 이력이 있다. │ # │ 그래서 Maven 빌드(힙 1G)는 서버에서 돌리지 않는다. │ # └────────────────────────────────────────────────────────────────────────┘ # # [개발자 PC] bash deploy/dev/build-and-upload.sh → 빌드 + WAR 업로드 # [개발자 PC] git push origin master → 이 워크플로 자동 실행 # [서버] ROOT 재전개 + 환경설정 주입 + 재기동 + 헬스체크(+실패 시 롤백) # # 수동 실행(workflow_dispatch)으로 재배포·롤백도 가능하다. name: deploy-dev on: push: branches: [master] paths-ignore: # 문서만 바뀐 커밋으로 재배포하지 않는다 - '**.md' - '**.docx' - '**.pptx' - 'docs/**' - '_workspace_privacy/**' workflow_dispatch: inputs: action: description: '수행할 작업' required: true default: 'deploy' type: choice options: - deploy - rollback concurrency: group: arko-dev-deploy cancel-in-progress: false # 배포 도중 취소되면 ROOT가 반쪽 상태로 남는다 env: APP_HOME: /opt/arko-dev INCOMING_WAR: /opt/arko-dev/incoming/arko.war SITE_URL: https://csv.zioinfo.co.kr/ jobs: deploy: runs-on: arko-dev timeout-minutes: 20 steps: - name: 사전 점검 run: | set -e echo "트리거: ${{ gitea.event_name }} / 작업: ${{ inputs.action || 'deploy' }}" df -h "$APP_HOME" | tail -1 free -h | head -2 uptime - name: WAR 확인 if: ${{ inputs.action != 'rollback' }} run: | set -e if [ ! -f "$INCOMING_WAR" ]; then echo "::error::업로드된 WAR이 없다: $INCOMING_WAR" echo "개발자 PC에서 'bash deploy/dev/build-and-upload.sh' 를 먼저 실행할 것." exit 1 fi ls -lh "$INCOMING_WAR" WAR_EPOCH=$(stat -c %Y "$INCOMING_WAR") echo "WAR 빌드 시각: $(date -d @$WAR_EPOCH '+%F %T')" # WAR이 이번 커밋보다 오래되었으면 옛 산출물을 배포하는 것이다. # 문서/CI 파일만 바뀐 커밋도 있으므로 실패시키지 않고 경고만 남긴다. COMMIT_EPOCH=$(git log -1 --format=%ct 2>/dev/null || echo 0) if [ "$COMMIT_EPOCH" -gt "$WAR_EPOCH" ]; then AGE_MIN=$(( (COMMIT_EPOCH - WAR_EPOCH) / 60 )) echo "::warning::업로드된 WAR이 이번 커밋보다 ${AGE_MIN}분 오래됐다. 소스 변경이 포함된 커밋이라면 build-and-upload.sh 로 다시 올릴 것." fi - name: 배포 if: ${{ inputs.action != 'rollback' }} run: | set -e bash "$APP_HOME/bin/arko-dev-deploy.sh" "$INCOMING_WAR" - name: 롤백 if: ${{ inputs.action == 'rollback' }} run: | set -e LATEST=$(ls -1t "$APP_HOME"/backup/ROOT_*.tar.gz 2>/dev/null | head -1 || true) if [ -z "$LATEST" ]; then echo "::error::롤백할 백업이 없다" exit 1 fi echo "롤백 대상: $LATEST" systemctl stop arko-dev rm -rf "$APP_HOME/tomcat/webapps/ROOT" tar -xzf "$LATEST" -C "$APP_HOME/tomcat/webapps" systemctl start arko-dev - name: 결과 확인 run: | set -e CODE=000 for i in $(seq 1 60); do CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 http://127.0.0.1:8088/ || echo 000) if [ "$CODE" = "200" ] || [ "$CODE" = "302" ]; then break; fi sleep 3 done echo "Tomcat 직접 → HTTP $CODE" EXT=$(curl -s -o /dev/null -w "%{http_code}" --max-time 20 "$SITE_URL" || echo 000) echo "$SITE_URL → HTTP $EXT" case "$CODE" in 200|302) echo "배포 정상" ;; *) echo "::error::Tomcat 응답 없음 (HTTP $CODE)"; exit 1 ;; esac