docs: ops-manual 배포 가이드 현행화
- 05-deployment.md: Jenkinsfile 코드블록 전체 현행화 - React/API/MNG: slackSend + tokenCredentialId 추가 - API/MNG: mkdir-p bootstrap/cache, storage/framework 추가 - MNG: npm install --production=false → --prefer-offline - 수동배포 섹션: mkdir-p 추가, 단계 번호 재정렬 - 빌드 실패 트러블슈팅: Laravel 디렉토리 누락 항목 추가 - 07-monitoring.md: Contact Point TODO → 실제 설정 완료 내용 반영 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -206,7 +206,11 @@ pipeline {
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps { checkout scm }
|
||||
steps {
|
||||
slackSend channel: '#product_infra', color: '#439FE0', tokenCredentialId: 'slack-token',
|
||||
message: "🚀 *react* 빌드 시작 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
stage('Prepare Env') {
|
||||
@@ -312,8 +316,14 @@ pipeline {
|
||||
}
|
||||
|
||||
post {
|
||||
success { echo '✅ react 배포 완료 (' + env.BRANCH_NAME + ')' }
|
||||
failure { echo '❌ react 배포 실패 (' + env.BRANCH_NAME + ')' }
|
||||
success {
|
||||
slackSend channel: '#product_infra', color: 'good', tokenCredentialId: 'slack-token',
|
||||
message: "✅ *react* 배포 성공 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
}
|
||||
failure {
|
||||
slackSend channel: '#product_infra', color: 'danger', tokenCredentialId: 'slack-token',
|
||||
message: "❌ *react* 배포 실패 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -369,7 +379,11 @@ pipeline {
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps { checkout scm }
|
||||
steps {
|
||||
slackSend channel: '#product_infra', color: '#439FE0', tokenCredentialId: 'slack-token',
|
||||
message: "🚀 *api* 빌드 시작 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
// ── main → 운영서버 Stage 배포 ──
|
||||
@@ -386,6 +400,7 @@ pipeline {
|
||||
. ${DEPLOY_USER}@211.117.60.189:/home/webservice/api-stage/releases/${RELEASE_ID}/
|
||||
ssh ${DEPLOY_USER}@211.117.60.189 '
|
||||
cd /home/webservice/api-stage/releases/${RELEASE_ID} &&
|
||||
mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs &&
|
||||
ln -sfn /home/webservice/api-stage/shared/.env .env &&
|
||||
ln -sfn /home/webservice/api-stage/shared/storage/app storage/app &&
|
||||
composer install --no-dev --optimize-autoloader --no-interaction &&
|
||||
@@ -427,6 +442,7 @@ pipeline {
|
||||
. ${DEPLOY_USER}@211.117.60.189:/home/webservice/api/releases/${RELEASE_ID}/
|
||||
ssh ${DEPLOY_USER}@211.117.60.189 '
|
||||
cd /home/webservice/api/releases/${RELEASE_ID} &&
|
||||
mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs &&
|
||||
ln -sfn /home/webservice/api/shared/.env .env &&
|
||||
ln -sfn /home/webservice/api/shared/storage/app storage/app &&
|
||||
composer install --no-dev --optimize-autoloader --no-interaction &&
|
||||
@@ -448,9 +464,13 @@ pipeline {
|
||||
}
|
||||
|
||||
post {
|
||||
success { echo "✅ api 배포 완료 (${env.BRANCH_NAME})" }
|
||||
success {
|
||||
slackSend channel: '#product_infra', color: 'good', tokenCredentialId: 'slack-token',
|
||||
message: "✅ *api* 배포 성공 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
}
|
||||
failure {
|
||||
echo "❌ api 배포 실패 (${env.BRANCH_NAME})"
|
||||
slackSend channel: '#product_infra', color: 'danger', tokenCredentialId: 'slack-token',
|
||||
message: "❌ *api* 배포 실패 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
script {
|
||||
if (env.BRANCH_NAME == 'main') {
|
||||
sshagent(credentials: ['deploy-ssh-key']) {
|
||||
@@ -490,26 +510,29 @@ git clone --depth 1 --branch main https://git.sam.it.kr/SamProject/sam-api.git $
|
||||
ln -sfn /home/webservice/api/shared/storage /home/webservice/api/releases/$RELEASE_ID/storage
|
||||
ln -sfn /home/webservice/api/shared/.env /home/webservice/api/releases/$RELEASE_ID/.env
|
||||
|
||||
# 3. 의존성 설치
|
||||
# 3. 필수 디렉토리 생성 (.gitignore에 의해 누락)
|
||||
cd /home/webservice/api/releases/$RELEASE_ID
|
||||
mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs
|
||||
|
||||
# 4. 의존성 설치
|
||||
composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# 4. 캐시 생성
|
||||
# 5. 캐시 생성
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
|
||||
# 5. 마이그레이션 (필요시)
|
||||
# 6. 마이그레이션 (필요시)
|
||||
php artisan migrate --force
|
||||
|
||||
# 6. 심링크 전환 (이 시점에 배포 적용)
|
||||
# 7. 심링크 전환 (이 시점에 배포 적용)
|
||||
ln -sfn /home/webservice/api/releases/$RELEASE_ID /home/webservice/api/current
|
||||
|
||||
# 7. 서비스 리로드
|
||||
# 8. 서비스 리로드
|
||||
sudo systemctl reload php8.4-fpm
|
||||
sudo supervisorctl restart sam-queue-worker:*
|
||||
|
||||
# 8. 오래된 릴리즈 정리 (최근 5개만 유지)
|
||||
# 9. 오래된 릴리즈 정리 (최근 5개만 유지)
|
||||
cd /home/webservice/api/releases
|
||||
ls -1dt */ | tail -n +6 | xargs rm -rf 2>/dev/null || true
|
||||
```
|
||||
@@ -527,6 +550,7 @@ ln -sfn /home/webservice/api-stage/shared/storage /home/webservice/api-stage/rel
|
||||
ln -sfn /home/webservice/api-stage/shared/.env /home/webservice/api-stage/releases/$RELEASE_ID/.env
|
||||
|
||||
cd /home/webservice/api-stage/releases/$RELEASE_ID
|
||||
mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs
|
||||
composer install --no-dev --optimize-autoloader --no-interaction
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
@@ -560,7 +584,11 @@ pipeline {
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps { checkout scm }
|
||||
steps {
|
||||
slackSend channel: '#product_infra', color: '#439FE0', tokenCredentialId: 'slack-token',
|
||||
message: "🚀 *mng* 빌드 시작 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
// ── main → 운영서버 Production ──
|
||||
@@ -578,10 +606,11 @@ pipeline {
|
||||
. ${DEPLOY_USER}@211.117.60.189:/home/webservice/mng/releases/${RELEASE_ID}/
|
||||
ssh ${DEPLOY_USER}@211.117.60.189 '
|
||||
cd /home/webservice/mng/releases/${RELEASE_ID} &&
|
||||
mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs &&
|
||||
ln -sfn /home/webservice/mng/shared/.env .env &&
|
||||
ln -sfn /home/webservice/mng/shared/storage/app storage/app &&
|
||||
composer install --no-dev --optimize-autoloader --no-interaction &&
|
||||
npm install --production=false &&
|
||||
npm install --prefer-offline &&
|
||||
npm run build &&
|
||||
php artisan config:cache &&
|
||||
php artisan route:cache &&
|
||||
@@ -600,9 +629,13 @@ pipeline {
|
||||
}
|
||||
|
||||
post {
|
||||
success { echo "✅ mng 배포 완료 (${env.BRANCH_NAME})" }
|
||||
success {
|
||||
slackSend channel: '#product_infra', color: 'good', tokenCredentialId: 'slack-token',
|
||||
message: "✅ *mng* 배포 성공 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
}
|
||||
failure {
|
||||
echo "❌ mng 배포 실패 (${env.BRANCH_NAME})"
|
||||
slackSend channel: '#product_infra', color: 'danger', tokenCredentialId: 'slack-token',
|
||||
message: "❌ *mng* 배포 실패 (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|빌드 #${env.BUILD_NUMBER}>"
|
||||
script {
|
||||
if (env.BRANCH_NAME == 'main') {
|
||||
sshagent(credentials: ['deploy-ssh-key']) {
|
||||
@@ -634,10 +667,11 @@ ln -sfn /home/webservice/mng/shared/storage /home/webservice/mng/releases/$RELEA
|
||||
ln -sfn /home/webservice/mng/shared/.env /home/webservice/mng/releases/$RELEASE_ID/.env
|
||||
|
||||
cd /home/webservice/mng/releases/$RELEASE_ID
|
||||
mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs
|
||||
composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# Vite 빌드 (Blade + Tailwind)
|
||||
npm install --production=false
|
||||
npm install --prefer-offline
|
||||
npm run build
|
||||
|
||||
php artisan config:cache
|
||||
@@ -807,6 +841,7 @@ ssh sam-prod "
|
||||
ln -sfn /home/webservice/api/shared/storage /home/webservice/api/releases/${RELEASE_ID}/storage &&
|
||||
ln -sfn /home/webservice/api/shared/.env /home/webservice/api/releases/${RELEASE_ID}/.env &&
|
||||
cd /home/webservice/api/releases/${RELEASE_ID} &&
|
||||
mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs &&
|
||||
composer install --no-dev --optimize-autoloader --no-interaction &&
|
||||
php artisan config:cache &&
|
||||
php artisan route:cache &&
|
||||
@@ -874,4 +909,10 @@ ls -la /var/lib/jenkins/workspace/
|
||||
2. npm run build 실패 -- TypeScript 오류, 환경변수 누락
|
||||
3. rsync 실패 -- SSH 키 문제, 디스크 공간 부족
|
||||
4. composer install 실패 -- 네트워크, PHP 확장 누락
|
||||
5. SSH 연결 실패 -- known_hosts 변경, 키 만료
|
||||
5. SSH 연결 실패 -- known_hosts 변경, 키 만료
|
||||
6. Laravel `package:discover` 실패 -- `bootstrap/cache/` 디렉토리 누락 (`.gitignore`에 포함)
|
||||
7. Blade view 캐시 실패 -- `storage/framework/views/` 디렉토리 누락
|
||||
8. `Target class [request] does not exist` -- CLI 컨텍스트에서 `request()` 호출 (AppServiceProvider 확인)
|
||||
|
||||
> **Laravel 배포 필수:** `mkdir -p bootstrap/cache storage/framework/{views,cache/data,sessions} storage/logs`를
|
||||
> `composer install` 전에 실행해야 함. `.gitignore`가 이 디렉토리들을 제외하므로 rsync/git clone 후 생성 필요.
|
||||
@@ -167,7 +167,7 @@ node_filefd_allocated
|
||||
|
||||
**알림 채널:** Grafana > Alerting > Contact points 에서 이메일, Slack 등 설정
|
||||
|
||||
> **TODO:** Contact Point에 실제 이메일 주소 또는 Slack Webhook 설정 필요 (현재 기본 email placeholder)
|
||||
**현재 설정:** SAM Slack Contact Point (Incoming Webhook) 연결 완료. Notification Policy에서 SAM Alerts 폴더의 알림이 Slack `#product_infra` 채널로 전송됨.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user