import re import os import sys import logging import requests from flask import Flask, request, jsonify # Настройка логирования logging.basicConfig(level=logging.INFO, format='%(message)s', handlers=[logging.StreamHandler(sys.stdout)]) logger = logging.getLogger(__name__) app = Flask(__name__) # Конфигурация GITEA_URL = os.getenv('GITEA_URL', 'https://gitea-copy.teamlead.online') GITEA_TOKEN = os.getenv('GITEA_TOKEN', '68dbda863bb4c51cb3ef1f8c4e8a69f7221240f5') # Поиск задач вида ABC-123 TASK_PATTERN = re.compile(r'([A-Z]+-\d+)', re.IGNORECASE) def find_tasks(text): """Находит ключи задач в тексте""" return set(TASK_PATTERN.findall(text or '')) def get_compare(owner, repo, base, head): """Запрашивает сравнение двух коммитов через API""" url = f"{GITEA_URL}/api/v1/repos/{owner}/{repo}/compare/{base}...{head}" headers = {'Authorization': f'token {GITEA_TOKEN}'} if GITEA_TOKEN else {} try: resp = requests.get(url, headers=headers) resp.raise_for_status() data = resp.json() logger.info(f"[API] Found {data.get('total_commits', 0)} commits") return data.get('commits', []) except Exception as e: logger.info(f"[API] Error: {e}") return None @app.route('/webhook', methods=['POST']) def webhook(): event = request.headers.get('X-Gitea-Event') logger.info(f"\n{'='*70}\n[WEBHOOK] Event: {event}") if event not in ['push', 'delete']: return jsonify({'status': 'ignored'}), 200 data = request.get_json() if not data: return jsonify({'error': 'No data'}), 400 ref = data.get('ref', '') logger.info(f"[WEBHOOK] Ref: {ref}") # Удаление ветки if event == 'delete': branch = ref.replace('refs/heads/', '') logger.info(f"[BRANCH DELETED] {branch}") tasks = find_tasks(branch) if tasks: logger.info(f" [TASKS IN DELETED BRANCH] {', '.join(tasks)}") return jsonify({'status': 'deleted'}), 200 # Только ветки if not ref.startswith('refs/heads/'): return jsonify({'status': 'ignored'}), 200 branch = ref.replace('refs/heads/', '') before, after = data.get('before'), data.get('after') repo = data.get('repository', {}) owner = repo.get('owner', {}).get('username') repo_name = repo.get('name') logger.info(f"[PUSH] {owner}/{repo_name}:{branch}") logger.info(f" before: {before[:8]}, after: {after[:8]}") # Создание ветки if before == '0'*40: logger.info(f"[BRANCH CREATED] {branch}") tasks = find_tasks(branch) if tasks: logger.info(f" [TASKS IN BRANCH] {', '.join(tasks)}") process_commits(data.get('commits', []), branch) return jsonify({'status': 'created'}), 200 # Удаление ветки (через push с after=000) if after == '0'*40: logger.info(f"[BRANCH DELETED] {branch}") return jsonify({'status': 'deleted'}), 200 # Обычный push - ищем новые и удаленные коммиты logger.info("-"*70) # Новые коммиты new_commits = get_compare(owner, repo_name, before, after) if new_commits: logger.info(f"[NEW] {len(new_commits)} commits:") for c in new_commits[:10]: sha = c.get('sha', '')[:8] msg = c.get('commit', {}).get('message', '')[:50] logger.info(f" + {sha}: {msg}") # Удаленные коммиты removed_commits = get_compare(owner, repo_name, after, before) if removed_commits: logger.info(f"[REMOVED] {len(removed_commits)} commits:") for c in removed_commits[:10]: sha = c.get('sha', '')[:8] msg = c.get('commit', {}).get('message', '')[:50] tasks = find_tasks(msg) task_info = f" [TASKS: {', '.join(tasks)}]" if tasks else "" logger.info(f" - {sha}: {msg}{task_info}") return jsonify({'status': 'ok'}), 200 def process_commits(commits, branch): """Обрабатывает коммиты и ищет задачи""" if not commits: return logger.info(f"\n[COMMITS] {len(commits)} commits:") all_tasks = find_tasks(branch) for i, c in enumerate(commits, 1): sha = c.get('id', '')[:8] msg = c.get('message', '') tasks = find_tasks(msg) all_tasks.update(tasks) logger.info(f" {i}. {sha}: {msg[:60]}" + (f" [TASKS: {', '.join(tasks)}]" if tasks else "")) if all_tasks: logger.info(f"\n[SUMMARY] Found tasks: {', '.join(sorted(all_tasks))}") @app.route('/', methods=['GET']) def index(): return f"""
Webhook URL: /webhook
Gitea API: {GITEA_URL}
Token: {'[SET]' if GITEA_TOKEN else '[NOT SET]'}
""" if __name__ == '__main__': logger.info(f"\n{'='*70}\nGITEA WEBHOOK HANDLER\n{'='*70}") logger.info(f"Server: http://0.0.0.0:5000") logger.info(f"Webhook: https://gitea-copy.teamlead.online:5000/webhook") logger.info(f"Gitea API: {GITEA_URL}") logger.info(f"{'='*70}\n") app.run(host='0.0.0.0', port=5000, debug=False)