G-1: 메신저 Webhook Relay + _send_to_room 실제 httpx 호출 구현 G-2: POST /api/tasks/bulk SR 대량작업 엔드포인트 (최대 100건) G-3: 라이선스 만료 알림 스케줄러 (매일 09:00 KST) G-4: 체험판 upgrade_banner 필드 + license.py 배너 로직 G-5: core/auto_rca.py + incidents/problem auto-rca 엔드포인트 G-6: core/deploy_impact.py + vibe impact-analysis 엔드포인트 G-7: core/ticket_classifier.py + SR 생성 시 AI 분류 + ai-suggestion API G-8: VulnPatchRecord 모델 + vuln_scan 패치추적 4개 엔드포인트 G-9: core/jira_sync.py + gateway Jira/Confluence 연동 엔드포인트 G-10: core/push_notify.py + routers/push.py + PushSubscription 모델 G-11: approvals 다중승인 (위임/서명/기한초과/마감연장) G-12: alembic.ini + migrations/ + cicd/migrate_to_postgres.sh 하네스: guardia-orchestrator 확장기능 Phase 반영 봇명령어: /sr /status /license /bulk 슬래시 명령어 추가 설치스크립트: setup/ (Ubuntu, CentOS, RHEL, Windows) --test 옵션 포함 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
358 lines
10 KiB
Markdown
358 lines
10 KiB
Markdown
# 파이프라인 설계 표준
|
|
|
|
> **버전**: 1.0.0
|
|
> **최종 수정**: 2026-05-25
|
|
|
|
---
|
|
|
|
## 1. 개요
|
|
|
|
GUARDiA ITSM의 모든 CI/CD 파이프라인은 아래 8단계를 표준으로 한다.
|
|
각 단계는 독립 스크립트로 분리되어 있으며, 실패 시 즉시 중단하고 ITSM에 결과를 통보한다.
|
|
|
|
```
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
│ Stage 1 │───▶│ Stage 2 │───▶│ Stage 3 │───▶│ Stage 4 │
|
|
│ Checkout │ │ Build │ │ Test │ │ Archive │
|
|
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
|
|
│
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
│ Stage 8 │◀───│ Stage 7 │◀───│ Stage 6 │◀───│ Stage 5 │
|
|
│ ITSM │ │ Health Check│ │ WAS Restart │ │ Deploy │
|
|
│ Callback │ │ │ │ │ │ │
|
|
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 2. 파이프라인 파라미터 표준
|
|
|
|
모든 파이프라인은 다음 파라미터를 공통으로 사용한다:
|
|
|
|
| 파라미터 | 타입 | 기본값 | 설명 |
|
|
|---------|------|-------|------|
|
|
| `ITSM_SESSION_ID` | String | — | GUARDiA 바이브 세션 ID |
|
|
| `ITSM_SR_ID` | String | — | 연결된 SR ID |
|
|
| `DEPLOY_ENV` | Choice | `dev` | 배포 환경 (dev/stg/prd) |
|
|
| `TARGET_SERVER` | String | — | 배포 대상 서버명 |
|
|
| `SKIP_TEST` | Boolean | `false` | 테스트 건너뜀 |
|
|
| `ROLLBACK_VERSION` | String | — | 롤백 버전 (빌드 번호) |
|
|
|
|
---
|
|
|
|
## 3. 환경별 파이프라인 정책
|
|
|
|
| 브랜치 | 환경 | 필수 단계 | 승인 게이트 | SonarQube |
|
|
|--------|------|----------|------------|-----------|
|
|
| `feature/*` | dev | Build + Test | 불필요 | 선택 |
|
|
| `develop` | dev/stg | Build + Test + Deploy | 불필요 | 선택 |
|
|
| `release/*` | stg | Full Pipeline | 불필요 | 필수 |
|
|
| `main` | prd | Full Pipeline | **필수** | 필수 |
|
|
| `hotfix/*` | prd | Full Pipeline (Fast) | **필수** | 선택 |
|
|
|
|
---
|
|
|
|
## 4. 단계별 표준 정의
|
|
|
|
### Stage 1: Checkout
|
|
|
|
```groovy
|
|
stage('Checkout') {
|
|
steps {
|
|
checkout([
|
|
$class: 'GitSCM',
|
|
branches: [[name: env.BRANCH_NAME ?: 'main']],
|
|
extensions: [
|
|
[$class: 'CleanBeforeCheckout'],
|
|
[$class: 'CloneOption', depth: 1, shallow: true]
|
|
],
|
|
userRemoteConfigs: [[
|
|
url: env.GIT_REPO_URL,
|
|
credentialsId: 'git-credentials'
|
|
]]
|
|
])
|
|
}
|
|
}
|
|
```
|
|
|
|
### Stage 2: Build
|
|
|
|
```groovy
|
|
stage('Build') {
|
|
steps {
|
|
script {
|
|
sh "bash ${WORKSPACE}/cicd/scripts/pipeline/build.sh"
|
|
}
|
|
}
|
|
post {
|
|
failure {
|
|
sh "bash ${WORKSPACE}/cicd/scripts/notify/itsm_callback.sh FAILED '빌드 실패'"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**빌드 산출물 위치**:
|
|
- Java Maven: `target/*.jar`, `target/*.war`
|
|
- Java Gradle: `build/libs/*.jar`, `build/libs/*.war`
|
|
- Node.js: `dist/`, `build/`
|
|
|
|
### Stage 3: Test
|
|
|
|
```groovy
|
|
stage('Test') {
|
|
when {
|
|
expression { params.SKIP_TEST == false }
|
|
}
|
|
parallel {
|
|
stage('Unit Test') {
|
|
steps {
|
|
sh "bash ${WORKSPACE}/cicd/scripts/pipeline/test.sh unit"
|
|
}
|
|
}
|
|
stage('SonarQube') {
|
|
when {
|
|
anyOf {
|
|
branch 'release/*'
|
|
branch 'main'
|
|
}
|
|
}
|
|
steps {
|
|
withSonarQubeEnv('sonarqube') {
|
|
sh "bash ${WORKSPACE}/cicd/scripts/pipeline/test.sh sonar"
|
|
}
|
|
timeout(time: 10, unit: 'MINUTES') {
|
|
waitForQualityGate abortPipeline: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Stage 4: Archive
|
|
|
|
```groovy
|
|
stage('Archive') {
|
|
steps {
|
|
archiveArtifacts artifacts: '**/target/*.jar,**/target/*.war,**/build/libs/*.jar',
|
|
fingerprint: true,
|
|
allowEmptyArchive: false
|
|
}
|
|
}
|
|
```
|
|
|
|
### Stage 5: Deploy
|
|
|
|
```groovy
|
|
stage('Deploy') {
|
|
steps {
|
|
withCredentials([sshUserPrivateKey(
|
|
credentialsId: "ssh-${params.TARGET_SERVER}",
|
|
keyFileVariable: 'SSH_KEY',
|
|
usernameVariable: 'SSH_USER'
|
|
)]) {
|
|
sh """
|
|
bash \${WORKSPACE}/cicd/scripts/pipeline/deploy.sh \
|
|
--server \${params.TARGET_SERVER} \
|
|
--env \${params.DEPLOY_ENV}
|
|
"""
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Stage 6: WAS Restart
|
|
|
|
```groovy
|
|
stage('WAS Restart') {
|
|
steps {
|
|
withCredentials([sshUserPrivateKey(
|
|
credentialsId: "ssh-${params.TARGET_SERVER}",
|
|
keyFileVariable: 'SSH_KEY',
|
|
usernameVariable: 'SSH_USER'
|
|
)]) {
|
|
sh """
|
|
bash \${WORKSPACE}/cicd/scripts/pipeline/was_restart.sh \
|
|
--server \${params.TARGET_SERVER} \
|
|
--was-type \${env.WAS_TYPE ?: 'tomcat'}
|
|
"""
|
|
}
|
|
}
|
|
post {
|
|
failure {
|
|
sh "bash ${WORKSPACE}/cicd/scripts/pipeline/rollback.sh --reason 'WAS 재기동 실패'"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Stage 7: Health Check
|
|
|
|
```groovy
|
|
stage('Health Check') {
|
|
steps {
|
|
retry(3) {
|
|
sh """
|
|
bash \${WORKSPACE}/cicd/scripts/pipeline/health_check.sh \
|
|
--url \${env.HEALTH_CHECK_URL} \
|
|
--timeout 60
|
|
"""
|
|
}
|
|
}
|
|
post {
|
|
failure {
|
|
sh "bash ${WORKSPACE}/cicd/scripts/pipeline/rollback.sh --reason '헬스체크 실패'"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Stage 8: ITSM Callback
|
|
|
|
```groovy
|
|
stage('ITSM Callback') {
|
|
steps {
|
|
sh """
|
|
bash \${WORKSPACE}/cicd/scripts/notify/itsm_callback.sh \
|
|
SUCCESS \
|
|
"배포 완료 (빌드 #\${env.BUILD_NUMBER})"
|
|
"""
|
|
}
|
|
post {
|
|
failure {
|
|
echo 'ITSM 콜백 실패 — 수동 확인 필요'
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 공통 post 블록
|
|
|
|
모든 파이프라인에 반드시 포함해야 하는 공통 후처리:
|
|
|
|
```groovy
|
|
post {
|
|
always {
|
|
// 워크스페이스 정리
|
|
cleanWs(
|
|
cleanWhenAborted: true,
|
|
cleanWhenFailure: true,
|
|
cleanWhenSuccess: true
|
|
)
|
|
}
|
|
success {
|
|
echo "파이프라인 성공: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
|
|
}
|
|
failure {
|
|
sh """
|
|
bash \${WORKSPACE}/cicd/scripts/notify/itsm_callback.sh \
|
|
FAILED "파이프라인 실패: \${env.STAGE_NAME}"
|
|
"""
|
|
}
|
|
unstable {
|
|
sh """
|
|
bash \${WORKSPACE}/cicd/scripts/notify/itsm_callback.sh \
|
|
UNSTABLE "테스트 불안정: \${env.STAGE_NAME}"
|
|
"""
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 승인 게이트 (운영 배포)
|
|
|
|
`main`, `hotfix/*` 브랜치의 운영 배포 시 승인 게이트를 거친다.
|
|
|
|
```groovy
|
|
stage('Production Approval') {
|
|
when {
|
|
anyOf {
|
|
branch 'main'
|
|
branch 'hotfix/*'
|
|
}
|
|
}
|
|
steps {
|
|
script {
|
|
// ITSM에 승인 요청 발송
|
|
sh "bash ${WORKSPACE}/cicd/scripts/notify/itsm_callback.sh PENDING_APPROVAL '운영 배포 승인 요청'"
|
|
|
|
// 승인 대기 (30분 타임아웃)
|
|
timeout(time: 30, unit: 'MINUTES') {
|
|
input message: "운영 배포를 승인하시겠습니까?",
|
|
ok: "배포 승인",
|
|
submitterParameter: "APPROVER"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. 롤백 정책
|
|
|
|
| 단계 | 자동 롤백 | 조건 |
|
|
|------|----------|------|
|
|
| WAS Restart | ✓ | WAS 기동 후 60초 내 응답 없음 |
|
|
| Health Check | ✓ | HTTP 상태코드 != 200 (3회 재시도 후) |
|
|
| 수동 롤백 | — | `!rollback` 봇 명령 또는 Jenkins 수동 트리거 |
|
|
|
|
롤백 파이프라인 파라미터:
|
|
- `ROLLBACK_VERSION`: 이전 빌드 번호 (빌드 번호 = 아티팩트 버전)
|
|
- `ROLLBACK_REASON`: 롤백 사유 (ITSM 등록용)
|
|
|
|
---
|
|
|
|
## 8. 파이프라인 타임아웃 표준
|
|
|
|
| 단계 | 타임아웃 | 비고 |
|
|
|------|---------|------|
|
|
| Checkout | 5분 | |
|
|
| Build | 30분 | 대형 프로젝트 60분 허용 |
|
|
| Test | 20분 | 단위 테스트 기준 |
|
|
| SonarQube | 10분 | Quality Gate 대기 포함 |
|
|
| Archive | 5분 | |
|
|
| Deploy | 10분 | rsync/SCP 전송 |
|
|
| WAS Restart | 5분 | |
|
|
| Health Check | 5분 | 3회 재시도 포함 |
|
|
| 전체 파이프라인 | 90분 | 초과 시 강제 중단 |
|
|
|
|
```groovy
|
|
options {
|
|
timeout(time: 90, unit: 'MINUTES')
|
|
buildDiscarder(logRotator(numToKeepStr: '30'))
|
|
disableConcurrentBuilds()
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. 환경변수 표준
|
|
|
|
파이프라인에서 사용하는 환경변수는 Jenkins → Manage Jenkins → System → Global properties 에 등록한다.
|
|
|
|
| 변수명 | 용도 | 예시 |
|
|
|-------|------|------|
|
|
| `ITSM_URL` | GUARDiA ITSM API URL | `http://itsm.agency.go.kr:8000` |
|
|
| `ITSM_CALLBACK_URL` | 파이프라인 결과 콜백 URL | `${ITSM_URL}/api/vibe/callback` |
|
|
| `SONAR_HOST_URL` | SonarQube 서버 URL | `http://sonar.agency.go.kr:9000` |
|
|
| `ARTIFACT_REPO` | 아티팩트 저장소 | `/opt/artifacts` |
|
|
| `SCRIPTS_ROOT` | 파이프라인 스크립트 루트 | `/var/lib/jenkins/scripts` |
|
|
|
|
---
|
|
|
|
## 10. 빌드 번호 & 아티팩트 버전
|
|
|
|
```groovy
|
|
environment {
|
|
// 아티팩트 버전 = 브랜치명 + 빌드번호 + 커밋 해시 앞 8자리
|
|
APP_VERSION = "${env.BRANCH_NAME}-${env.BUILD_NUMBER}-${env.GIT_COMMIT[0..7]}"
|
|
// 배포 대상 파일명
|
|
ARTIFACT_NAME = "${env.JOB_NAME}-${APP_VERSION}.jar"
|
|
}
|
|
```
|