"""Jenkins Jenkinsfile branch 조건 수정 + Gitea→Jenkins webhook 검증""" import paramiko, sys, json, base64, time sys.stdout.reconfigure(encoding='utf-8', errors='replace') c = paramiko.SSHClient(); c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect('101.79.17.164', username='root', password='1q2w3e!Q', timeout=15) J = 'http://127.0.0.1:9080' A = 'admin:Admin@2026!' def run(label, cmd, timeout=30): print(f'\n[{label}]') _, o, _ = c.exec_command(cmd, timeout=timeout) out = o.read().decode('utf-8','replace').strip() if out: print(out[:600]) return out # crumb _, o, _ = c.exec_command(f'curl -sf -u "{A}" {J}/crumbIssuer/api/json 2>/dev/null', timeout=10) try: cd = json.loads(o.read().decode('utf-8','replace').strip()) CRUMB = f'-H "{cd["crumbRequestField"]}: {cd["crumb"]}"' except: CRUMB = '' # Gitea→Jenkins webhook 동작 확인: guardia-itsm에 직접 push 트리거 run('Gitea→Jenkins 직접 webhook 트리거 테스트', """curl -sf -X POST 'http://127.0.0.1:9003/api/v1/repos/zio/guardia-itsm/hooks/17/tests' \ --header 'Authorization: Basic '"$(echo -n 'zio:Zio@Admin2026!' | base64)" \ 2>/dev/null && echo "webhook 테스트 전송됨" || echo "FAIL" """) time.sleep(3) run('Jenkins 빌드 큐 확인', f'curl -sf -u "{A}" {J}/queue/api/json 2>/dev/null | ' 'python3 -c "import sys,json; d=json.load(sys.stdin); ' '[print(i[\'task\'][\'name\'],i.get(\'why\',\'?\')) for i in d.get(\'items\',[])]" 2>/dev/null || echo "큐 비어있음"') # Gitea webhook URL을 Gitea 플러그인 전용 URL로 업데이트 # (일반 webhook URL → /gitea-webhook/post) print('\n[Jenkins webhook URL 확인]') run('현재 webhook URL 목록', """curl -sf 'http://127.0.0.1:9003/api/v1/repos/zio/guardia-itsm/hooks' \ --header 'Authorization: Basic '"$(echo -n 'zio:Zio@Admin2026!' | base64)" \ 2>/dev/null | python3 -c " import sys,json for h in json.load(sys.stdin): print(h['id'], h['config'].get('url',''), 'active:', h['active']) " 2>/dev/null""") # Jenkins job SCM 설정에서 GIT_BRANCH 확인 run('guardia-itsm GIT_BRANCH 확인', f'curl -sf -u "{A}" {J}/job/guardia-itsm/lastBuild/consoleText 2>/dev/null | ' "grep -i 'branch\\|GIT_BRANCH\\|BRANCH_NAME' | head -5") # Jenkins 환경변수 주입: GIT_BRANCH를 통해 Deploy stage 활성화 # config.xml에서 when { branch 'main' } → when { expression { scm 관련 } } 로 변경하는 대신 # Jenkins job에 파라미터로 BRANCH=main 주입 print('\n[Jenkinsfile branch 조건 수정 - Gitea API로 업데이트]') import base64 as b64 JENKINSFILE_ITSM = """pipeline { agent any environment { APP = '/opt/guardia/app' VENV = '/opt/guardia/venv' NOTIFY = "http://127.0.0.1:9001/api/messenger/webhook" } options { buildDiscarder(logRotator(numToKeepStr: '5')) timeout(time: 15, unit: 'MINUTES') timestamps() } stages { stage('Checkout') { steps { checkout scm } } stage('Install') { steps { sh "${VENV}/bin/pip install -r requirements.txt -q" } } stage('Test') { when { expression { fileExists('tests/') } } steps { sh "${VENV}/bin/pytest tests/ -q --tb=short --junitxml=test-results.xml || true" junit allowEmptyResults: true, testResults: 'test-results.xml' } } stage('Deploy') { when { expression { return env.GIT_BRANCH == 'main' || env.GIT_BRANCH == 'origin/main' || env.BRANCH_NAME == 'main' } } steps { sh """ rsync -a --exclude=__pycache__ --exclude=.git \\ --exclude=rpa_rules.json --exclude='*.pyc' \\ . ${APP}/ systemctl restart guardia sleep 4 systemctl is-active guardia || exit 1 """ } } } post { success { sh "curl -sf -X POST ${NOTIFY} -H 'Content-Type:application/json' -d '{\\"event\\":\\"build_result\\",\\"room\\":\\"ops\\",\\"success\\":true,\\"result_summary\\":\\"✅ guardia-itsm 배포 완료 #${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-itsm 빌드 실패 #${BUILD_NUMBER}\\"}' 2>/dev/null || true" } } }""" # NOTIFY URL을 9001로 수정한 버전으로 5개 모두 업데이트 REPOS_FIX = { 'guardia-itsm': JENKINSFILE_ITSM, } sftp = c.open_sftp() for repo, content in REPOS_FIX.items(): encoded = b64.b64encode(content.encode('utf-8')).decode() # SHA 확인 _, o, _ = c.exec_command( f'curl -sf "http://127.0.0.1:9003/api/v1/repos/zio/{repo}/contents/Jenkinsfile" ' '--header "Authorization: Basic '"$(echo -n 'zio:Zio@Admin2026!' | base64)"'" 2>/dev/null | ' 'python3 -c "import sys,json; print(json.load(sys.stdin)[\'sha\'])" 2>/dev/null', timeout=10) sha = o.read().decode('utf-8','replace').strip() payload = json.dumps({ "message": "ci: fix branch condition + ITSM notify URL", "content": encoded, "sha": sha, "branch": "main" }) with sftp.open(f'/tmp/jf_{repo}_fix.json', 'w') as f: f.write(payload) run(f'Jenkinsfile 업데이트 {repo}', f'curl -sf -X PUT "http://127.0.0.1:9003/api/v1/repos/zio/{repo}/contents/Jenkinsfile" ' '--header "Authorization: Basic '"$(echo -n 'zio:Zio@Admin2026!' | base64)"'" ' '--header "Content-Type: application/json" ' f'--data @/tmp/jf_{repo}_fix.json 2>/dev/null | ' 'python3 -c "import sys,json; d=json.load(sys.stdin); print(\'OK:\', d.get(\'content\',{}).get(\'name\',\'?\'))" 2>/dev/null || echo FAIL') sftp.close() # 빌드 재트리거 time.sleep(2) run('guardia-itsm 빌드 재트리거', f'curl -sf -X POST -u "{A}" {CRUMB} {J}/job/guardia-itsm/build 2>/dev/null && echo "트리거됨"') time.sleep(15) run('빌드 #3 콘솔 로그 (Deploy 스테이지)', f'curl -sf -u "{A}" {J}/job/guardia-itsm/lastBuild/consoleText 2>/dev/null | ' "grep -A3 'Deploy\\|GIT_BRANCH\\|BRANCH\\|skipped\\|SUCCESS\\|FAILURE' | head -20") c.close() print('\n=== 완료 ===')