zioinfo-mail/scripts/setup/add_jenkins_auth_token.py
DESKTOP-TKLFCPR\ython ea51238c1d feat(cicd): complete Jenkins pipeline - plugins, triggers, E2E verified
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 20:28:45 +09:00

104 lines
4.3 KiB
Python

"""Jenkins job config.xml에 authToken 추가 + Gitea webhook URL 수정"""
import paramiko, sys, json, 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)
sftp = c.open_sftp()
J = 'http://127.0.0.1:9080'
A = 'admin:Admin@2026!'
TOKEN = 'gitea-build-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[:500])
return out
_, 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())
CH = f'{cd["crumbRequestField"]}: {cd["crumb"]}'
except:
CH = 'Jenkins-Crumb: x'
REPOS = ['guardia-itsm', 'zioinfo-web', 'guardia-manager', 'guardia-messenger', 'guardia-docs']
HOOK_IDS = {'zioinfo-web':16,'guardia-itsm':17,'guardia-manager':18,'guardia-messenger':19,'guardia-docs':20}
# 1. config.xml에 authToken + GiteaWebHookTrigger 추가
print('[config.xml authToken + Gitea trigger 설정]')
for repo in REPOS:
_, o, _ = c.exec_command(f'curl -sf -u "{A}" {J}/job/{repo}/config.xml 2>/dev/null', timeout=10)
config = o.read().decode('utf-8','replace')
if not config.startswith('<?xml'):
print(f' {repo}: config 읽기 실패'); continue
modified = config
# authToken 추가 (없으면)
if f'<authToken>{TOKEN}</authToken>' not in modified:
if '<authToken>' in modified:
import re
modified = re.sub(r'<authToken>[^<]*</authToken>', f'<authToken>{TOKEN}</authToken>', modified)
else:
modified = modified.replace('<definition ', f'<authToken>{TOKEN}</authToken>\n <definition ', 1)
if modified != config:
with sftp.open(f'/tmp/{repo}_config.xml', 'w') as f:
f.write(modified)
_, o, _ = c.exec_command(
f'curl -sf -o /dev/null -w "%{{http_code}}" -X POST -u "{A}" '
f'-H "{CH}" -H "Content-Type: text/xml" '
f'--data-binary @/tmp/{repo}_config.xml "{J}/job/{repo}/config.xml" 2>/dev/null', timeout=15)
code = o.read().decode('utf-8','replace').strip()
print(f' {repo}: HTTP {code}')
else:
print(f' {repo}: 변경 없음')
# 2. Gitea webhook URL을 token 방식으로 업데이트
print('\n[Gitea webhook URL → build?token=... 방식]')
for repo, hid in HOOK_IDS.items():
payload = json.dumps({
"config": {
"url": f"http://127.0.0.1:9080/job/{repo}/build?token={TOKEN}",
"content_type": "json"
},
"active": True, "events": ["push"]
})
with sftp.open(f'/tmp/hook_{repo}.json', 'w') as f:
f.write(payload)
_, o, _ = c.exec_command(
f"curl -sf -o /dev/null -w '%{{http_code}}' -X PATCH "
f"'http://127.0.0.1:9003/api/v1/repos/zio/{repo}/hooks/{hid}' "
"--header 'Authorization: Basic $(echo -n zio:Zio@Admin2026! | base64)' "
"--header 'Content-Type: application/json' "
f"--data @/tmp/hook_{repo}.json 2>/dev/null", timeout=15)
code = o.read().decode('utf-8','replace').strip()
print(f' {repo} hook {hid}: HTTP {code}')
# 3. Gitea webhook 직접 테스트
time.sleep(3)
run('webhook 테스트 (guardia-itsm)',
"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 '전송됨' || echo FAIL")
time.sleep(8)
run('Jenkins 빌드 확인',
f'curl -sf -u "{A}" {J}/job/guardia-itsm/api/json 2>/dev/null | '
"python3 -c \"import sys,json; d=json.load(sys.stdin); "
"lb=d.get('lastBuild',{}); print('lastBuild #'+str(lb.get('number','?')), "
"'nextBuild:', d.get('nextBuildNumber'))\" 2>/dev/null")
# 4. 최종 아키텍처 요약
print('\n[최종 CI/CD 아키텍처]')
run('webhook 서버', 'systemctl is-active zioinfo-deploy && echo "port 9999 OK"')
run('Jenkins', f'curl -sf -u "{A}" {J}/api/json 2>/dev/null | '
"python3 -c \"import sys,json; d=json.load(sys.stdin); "
"print(d.get('mode'), len(d.get('jobs',[])), 'jobs, all:', "
"all(j['color']=='blue' for j in d['jobs']))\" 2>/dev/null")
sftp.close()
c.close()
print('\n=== 완료 ===')