diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..5b7f1d6 --- /dev/null +++ b/Readme.md @@ -0,0 +1,243 @@ +1. Получение API токена в Gitea +Войдите в Gitea + +Перейдите в Настройки пользователя → Приложения (Settings → Applications) + +В разделе "Manage Access Tokens" нажмите "Generate Token" + +Укажите имя: webhook-handler + +Выберите права: read:repository (достаточно для чтения коммитов) + +Нажмите "Generate Token" и скопируйте токен (он показывается только один раз) + +2. Настройка Webhook в Gitea +Откройте репозиторий в Gitea + +Перейдите в Настройки → Вебхуки (Settings → Webhooks) + +Нажмите "Add Webhook" → выберите "Gitea" + +Заполните форму: + +Поле Значение +Target URL http://IP-вашего-сервера:5000/webhook (например, http://192.168.1.100:5000/webhook) +HTTP Method POST +POST Content Type application/json +Secret (опционально) можно оставить пустым +Trigger On Выберите "Push Events" и "Delete Events" +Branch filter Оставьте пустым (или укажите конкретные ветки) +Active ✅ Включено +Нажмите "Add Webhook" + +3. . Подготовка сервера +Установите Python и зависимости: + +bash +# Установка Python (если не установлен) +# Для Ubuntu/Debian: +sudo apt update +sudo apt install python3 python3-pip + +# Для Windows: скачайте с python.org + +# Установка зависимостей +pip install flask requests +Скачайте и настройте приложение: + +bash +# Создайте директорию +mkdir gitea-webhook +cd gitea-webhook +и скопируйте в нее файл app.py + +#Настройте переменные окружения: + +bash +# Установите переменные (для Linux/Mac) +export GITEA_URL=https://gitea.your-company.com +export GITEA_TOKEN=your_api_token_here + +# Для Windows (cmd) +set GITEA_URL=https://gitea.your-company.com +set GITEA_TOKEN=your_api_token_here + +# Для Windows (PowerShell) +$env:GITEA_URL="https://gitea.your-company.com" +$env:GITEA_TOKEN="your_api_token_here" +Запустите приложение: + +bash +python app.py + + + +Инструкция по тестированию обнаружения новых и удаленных коммитов +Подготовка +bash +# 1. Создайте тестовый репозиторий или используйте существующий +mkdir test-webhook +cd test-webhook + +# 2. Инициализируйте репозиторий +git init + +# 3. Добавьте удаленный репозиторий (Gitea) +git remote add origin https://gitea.daes.prosyst.ru/YOUR_USER/test-webhook.git + +# 4. Создайте первый коммит (базовый) +echo "Initial content" > README.md +git add README.md +git commit -m "Initial commit" +git push -u origin main +Сценарий 1: Создание ветки с несколькими коммитами +bash +# 1. Создайте ветку feature +git checkout -b feature/TSK-100 + +# 2. Создайте 3 коммита с задачами +echo "Feature 1" > feature1.txt +git add feature1.txt +git commit -m "TSK-100: Add feature 1" + +echo "Feature 2" > feature2.txt +git add feature2.txt +git commit -m "TSK-100: Add feature 2" + +echo "Feature 3" > feature3.txt +git add feature3.txt +git commit -m "TSK-100: Add feature 3" + +# 3. Push ветку +git push -u origin feature/TSK-100 +Ожидаемый вывод в консоли: + +text +====================================================================== +[PUSH] user/test-webhook:feature/TSK-100 +[NEW] 3 commits: + + abc123: TSK-100: Add feature 1 + + def456: TSK-100: Add feature 2 + + ghi789: TSK-100: Add feature 3 +[SUMMARY] Found tasks: TSK-100 +Сценарий 2: Rebase (переписывание истории) +Вариант A: Изменение сообщения коммита (reword) +bash +# 1. Сделайте rebase последних 3 коммитов +git rebase -i HEAD~3 + +# В редакторе появится: +# pick abc123 TSK-100: Add feature 1 +# pick def456 TSK-100: Add feature 2 +# pick ghi789 TSK-100: Add feature 3 + +# 2. Измените pick на reword для второго коммита: +# pick abc123 TSK-100: Add feature 1 +# reword def456 TSK-100: Add feature 2 +# pick ghi789 TSK-100: Add feature 3 + +# 3. В открывшемся редакторе измените сообщение на: +# "TSK-100: Update feature 2" + +# 4. Сохраните и выйдите + +# 5. Force push +git push --force origin feature/TSK-100 +Ожидаемый вывод в консоли: + +text +====================================================================== +[PUSH] user/test-webhook:feature/TSK-100 +[NEW] 3 commits: + + abc123: TSK-100: Add feature 1 + + def456: TSK-100: Update feature 2 + + ghi789: TSK-100: Add feature 3 + +[REMOVED] 1 commits: + - def456_old: TSK-100: Add feature 2 +Вариант B: Объединение коммитов (squash) +bash +# 1. Начните rebase +git rebase -i HEAD~3 + +# 2. Измените на squash: +# pick abc123 TSK-100: Add feature 1 +# squash def456 TSK-100: Add feature 2 +# squash ghi789 TSK-100: Add feature 3 + +# 3. В редакторе объедините сообщения: +# TSK-100: Add all features + +# 4. Сохраните и выйдите + +# 5. Force push +git push --force origin feature/TSK-100 +Ожидаемый вывод в консоли: + +text +====================================================================== +[PUSH] user/test-webhook:feature/TSK-100 +[NEW] 1 commits: + + abc123_new: TSK-100: Add all features + +[REMOVED] 2 commits: + - def456_old: TSK-100: Add feature 2 + - ghi789_old: TSK-100: Add feature 3 +Вариант C: Удаление коммита (drop) +bash +# 1. Начните rebase +git rebase -i HEAD~3 + +# 2. Удалите строку с коммитом: +# pick abc123 TSK-100: Add feature 1 +# drop def456 TSK-100: Add feature 2 +# pick ghi789 TSK-100: Add feature 3 + +# 3. Сохраните и выйдите + +# 4. Force push +git push --force origin feature/TSK-100 +Ожидаемый вывод в консоли: + +text +====================================================================== +[PUSH] user/test-webhook:feature/TSK-100 +[NEW] 2 commits: + + abc123: TSK-100: Add feature 1 + + ghi789: TSK-100: Add feature 3 + +[REMOVED] 1 commits: + - def456: TSK-100: Add feature 2 +Сценарий 3: Изменение последнего коммита (amend) +bash +# 1. Измените последний коммит +echo "Updated feature" > feature3.txt +git add feature3.txt +git commit --amend -m "TSK-100: Updated feature 3" + +# 2. Force push +git push --force origin feature/TSK-100 +Ожидаемый вывод в консоли: + +text +====================================================================== +[PUSH] user/test-webhook:feature/TSK-100 +[NEW] 1 commits: + + ghi789_new: TSK-100: Updated feature 3 + +[REMOVED] 1 commits: + - ghi789_old: TSK-100: Add feature 3 +Сценарий 4: Удаление ветки +bash +# 1. Удалите ветку локально и на сервере +git checkout main +git branch -d feature/TSK-100 +git push origin --delete feature/TSK-100 +Ожидаемый вывод в консоли: + +text +====================================================================== +[WEBHOOK] Event: delete +[BRANCH DELETED] refs/heads/feature/TSK-100 +[TASKS IN DELETED BRANCH] TSK-100 + diff --git a/app.py b/app.py new file mode 100644 index 0000000..4f2bba0 --- /dev/null +++ b/app.py @@ -0,0 +1,149 @@ +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) \ No newline at end of file diff --git a/com2.txt b/com2.txt index 898b93f..f8433b2 100644 --- a/com2.txt +++ b/com2.txt @@ -2,3 +2,4 @@ my 2 vbcvbcvbcvbcv sdfhgfhfghdf cghjhjdj dj djd dj +bb xb xb diff --git a/start_webhook.sh b/start_webhook.sh new file mode 100644 index 0000000..6d1e0d3 --- /dev/null +++ b/start_webhook.sh @@ -0,0 +1,2 @@ +#! /usr/bin/bash +GITEA_URL=https://gitea.daes.prosyst.ru GITEA_TOKEN=your_api_token_here python app.py