"""서버에서 직접 각 Gitea repo에 Jenkinsfile 추가 push""" import paramiko, sys sys.stdout.reconfigure(encoding='utf-8', errors='replace') client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect('101.79.17.164', username='root', password='1q2w3e!Q', timeout=15) sftp = client.open_sftp() def run(label, cmd, timeout=60): print(f' [{label}]') _, o, e = client.exec_command(cmd, timeout=timeout) out = o.read().decode('utf-8', 'replace').strip() err = e.read().decode('utf-8', 'replace').strip() if out: print(f' {out[:300]}') if err: bad = [l for l in err.splitlines() if not any(k in l.lower() for k in ['warn','hint','note','already'])] if bad: print(f' ERR: {bad[-1][:200]}') return out GITEA = "http://zio:Zio%40Admin2026%21@localhost:3000/zio" # Jenkinsfile 내용 정의 JENKINSFILES = { "guardia-manager": """pipeline { agent any environment { STATIC = '/var/www/manager' NOTIFY = "${ITSM_BASE_URL}/api/messenger/webhook" } options { buildDiscarder(logRotator(numToKeepStr: '5')); timeout(time: 15, unit: 'MINUTES') } stages { stage('Checkout') { steps { checkout scm } } stage('Build') { steps { dir('frontend') { sh 'npm ci 2>/dev/null || npm install' sh 'npm run build' } } } stage('Deploy') { when { branch 'main' } steps { sh \"\"\" cp -r frontend/dist/. ${STATIC}/ systemctl restart guardia-manager 2>/dev/null || true \"\"\" } } } post { success { sh "curl -sf -X POST ${NOTIFY} -H 'Content-Type:application/json' -d '{\\\"event\\\":\\\"build_result\\\",\\\"room\\\":\\\"ops\\\",\\\"success\\\":true,\\\"result_summary\\\":\\\"✅ guardia-manager 배포 완료\\\"}' 2>/dev/null || true" } failure { sh "curl -sf -X POST ${NOTIFY} -H 'Content-Type:application/json' -d '{\\\"event\\\":\\\"build_result\\\",\\\"room\\\":\\\"ops\\\",\\\"success\\\":false,\\\"result_summary\\\":\\\"❌ guardia-manager 빌드 실패\\\"}' 2>/dev/null || true" } } }""", "guardia-messenger": """pipeline { agent any environment { NOTIFY = "${ITSM_BASE_URL}/api/messenger/webhook" } options { buildDiscarder(logRotator(numToKeepStr: '5')) timeout(time: 10, unit: 'MINUTES') timestamps() } stages { stage('Checkout') { steps { checkout scm } } stage('Validate') { steps { sh 'node --version || true' sh "grep -E '\\\"expo\\\"' package.json | head -1 || true" } } stage('Install') { steps { sh 'npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps' } } stage('Type Check') { when { expression { fileExists('tsconfig.json') } } steps { sh 'npx tsc --noEmit 2>/dev/null || true' } } stage('EAS Build Trigger') { when { allOf { branch 'main' expression { return env.EXPO_TOKEN?.trim() } } } steps { sh ''' npm install -g @expo/eas-cli 2>/dev/null || true eas build --platform android --non-interactive --no-wait --profile production 2>/dev/null || echo "EAS 빌드 큐 등록됨" ''' } } } post { success { sh "curl -sf -X POST ${NOTIFY} -H 'Content-Type:application/json' -d '{\\\"event\\\":\\\"build_result\\\",\\\"room\\\":\\\"ops\\\",\\\"success\\\":true,\\\"result_summary\\\":\\\"✅ guardia-messenger 검증 완료 #${BUILD_NUMBER}\\\"}' 2>/dev/null || true" } failure { sh "curl -sf -X POST ${NOTIFY} -H 'Content-Type:application/json' -d '{\\\"event\\\":\\\"build_result\\\",\\\"room\\\":\\\"ops\\\",\\\"success\\\":false,\\\"result_summary\\\":\\\"❌ guardia-messenger 빌드 실패 #${BUILD_NUMBER}\\\"}' 2>/dev/null || true" } } }""", "guardia-docs": """pipeline { agent any environment { DOCS = '/var/www/docs' } options { buildDiscarder(logRotator(numToKeepStr: '3')) } stages { stage('Checkout') { steps { checkout scm } } stage('Deploy') { when { branch 'main' } steps { sh 'mkdir -p ${DOCS} && cp -r . ${DOCS}/' } } } }""", } print('[서버에서 Gitea repo Jenkinsfile push]') for repo, content in JENKINSFILES.items(): print(f'\n=== {repo} ===') # 임시 디렉토리에 clone tmp = f'/tmp/jf_{repo}' run(f'clone {repo}', f""" rm -rf {tmp} git clone {GITEA}/{repo}.git {tmp} 2>&1 | tail -2 """) # Jenkinsfile 작성 with sftp.open(f'{tmp}/Jenkinsfile', 'w') as f: f.write(content) print(f' Jenkinsfile 작성됨') # commit + push run(f'push {repo}', f""" cd {tmp} git config user.email "ci@zioinfo.co.kr" git config user.name "CI Bot" git add Jenkinsfile git diff --cached --stat git commit -m "ci: add Jenkinsfile for CI/CD pipeline" 2>/dev/null || echo "already committed" git push origin main 2>&1 | tail -3 rm -rf {tmp} """, timeout=30) # zioinfo-web, guardia-itsm 도 Jenkinsfile 확인 print('\n[기존 repo Jenkinsfile 존재 확인]') for repo in ['zioinfo-web', 'guardia-itsm']: run(f'{repo} Jenkinsfile', f""" curl -sf '{GITEA.replace("http://zio:Zio%40Admin2026%21@localhost", "http://localhost")}:3000/api/v1/repos/zio/{repo}/contents/Jenkinsfile' \ -u 'zio:Zio@Admin2026!' 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print('OK size:', d.get('size',0))" 2>/dev/null || echo "없음" """) sftp.close() client.close() print('\n=== 완료 ===')