155 lines
6.3 KiB
Python
155 lines
6.3 KiB
Python
"""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=== 완료 ===')
|