diff --git a/Jenkinsfile b/Jenkinsfile index a0789999..7780d3f9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,28 +8,33 @@ pipeline { stages { stage('Checkout') { - steps { checkout scm } + steps { + slackSend channel: '#product_infra', color: '#439FE0', + message: "πŸš€ *react* λΉŒλ“œ μ‹œμž‘ (`${env.BRANCH_NAME}`)\n<${env.BUILD_URL}|λΉŒλ“œ #${env.BUILD_NUMBER}>" + checkout scm + } } stage('Prepare Env') { steps { script { - def envFile = "/var/lib/jenkins/env-files/react/.env.${env.BRANCH_NAME}" - sh "cp ${envFile} .env.local" + if (env.BRANCH_NAME == 'main') { + // main: Stage λΉŒλ“œ λ¨Όμ € (승인 ν›„ Production μž¬λΉŒλ“œ) + sh "cp /var/lib/jenkins/env-files/react/.env.stage .env.local" + } else { + def envFile = "/var/lib/jenkins/env-files/react/.env.${env.BRANCH_NAME}" + sh "cp ${envFile} .env.local" + } } } } stage('Install') { - steps { - sh 'npm install --prefer-offline' - } + steps { sh 'npm install --prefer-offline' } } stage('Build') { - steps { - sh 'npm run build' - } + steps { sh 'npm run build' } } // ── develop β†’ κ°œλ°œμ„œλ²„ 배포 ── @@ -39,34 +44,27 @@ pipeline { sshagent(credentials: ['deploy-ssh-key']) { sh """ rsync -az --delete \ - --exclude='.git' \ - --exclude='.env*' \ - --exclude='ecosystem.config.*' \ + --exclude='.git' --exclude='.env*' --exclude='ecosystem.config.*' \ .next package.json next.config.ts public node_modules \ ${DEPLOY_USER}@114.203.209.83:/home/webservice/react/ - scp .env.local ${DEPLOY_USER}@114.203.209.83:/home/webservice/react/.env.local - ssh ${DEPLOY_USER}@114.203.209.83 'cd /home/webservice/react && pm2 restart sam-react' """ } } } - // ── stage β†’ μš΄μ˜μ„œλ²„ Stage 배포 ── + // ── main β†’ μš΄μ˜μ„œλ²„ Stage 배포 ── stage('Deploy Stage') { - when { branch 'stage' } + when { branch 'main' } steps { sshagent(credentials: ['deploy-ssh-key']) { sh """ ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react-stage/releases/${RELEASE_ID}' - rsync -az --delete \ .next package.json next.config.ts public node_modules \ ${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/ - scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/.env.local - ssh ${DEPLOY_USER}@211.117.60.189 ' ln -sfn /home/webservice/react-stage/releases/${RELEASE_ID} /home/webservice/react-stage/current && cd /home/webservice && pm2 reload sam-front-stage 2>/dev/null || pm2 start react-stage/current/node_modules/.bin/next --name sam-front-stage -- start -p 3100 && @@ -77,6 +75,26 @@ pipeline { } } + // ── 운영 배포 승인 ── + stage('Production Approval') { + when { branch 'main' } + steps { + timeout(time: 24, unit: 'HOURS') { + input message: 'Stage 확인 ν›„ 운영 배포λ₯Ό μ§„ν–‰ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?\nStage: https://stage.sam.it.kr', + ok: '운영 배포 μ§„ν–‰' + } + } + } + + // ── main β†’ Production μž¬λΉŒλ“œ (운영 ν™˜κ²½λ³€μˆ˜) ── + stage('Rebuild for Production') { + when { branch 'main' } + steps { + sh "cp /var/lib/jenkins/env-files/react/.env.main .env.local" + sh 'npm run build' + } + } + // ── main β†’ μš΄μ˜μ„œλ²„ Production 배포 ── stage('Deploy Production') { when { branch 'main' } @@ -84,13 +102,10 @@ pipeline { sshagent(credentials: ['deploy-ssh-key']) { sh """ ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react/releases/${RELEASE_ID}' - rsync -az --delete \ .next package.json next.config.ts public node_modules \ ${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/ - scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/.env.local - ssh ${DEPLOY_USER}@211.117.60.189 ' ln -sfn /home/webservice/react/releases/${RELEASE_ID} /home/webservice/react/current && cd /home/webservice && pm2 reload sam-front && @@ -103,7 +118,13 @@ 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}>" + } } -} +} \ No newline at end of file