diff --git a/README.md b/README.md index e08e63b..51f5383 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,11 @@ pip install -r requirements.txt ### rpm ```shell -dnf install python3-flask +dnf install python3-flask python3-mod_wsgi ``` ## run ```shell python3 koji-forgejo-webook.py -``` \ No newline at end of file +``` diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..fc76933 --- /dev/null +++ b/config.ini @@ -0,0 +1,5 @@ +[DEFAULT] +SECRET_KEY = $3cr3tk3y +KOJI_SERVER = https://kojidev.stackwebservices.org/kojihub +KOJI_TARGET = rl9-candidate +WEBHOOK_SECRET_KEY = your_secret_key diff --git a/koji-forgejo-webook.py b/koji-forgejo-webook.py deleted file mode 100644 index 584bc50..0000000 --- a/koji-forgejo-webook.py +++ /dev/null @@ -1,67 +0,0 @@ -import json -import hashlib -import hmac -import logging -from flask import Flask, request, abort - -app = Flask(__name__) - -class ForgejoWebhookProcessor: - def __init__(self, secret_key): - self.secret_key = secret_key - - def validate_webhook(self, payload, signature): - """Validate webhook signature""" - computed_signature = hmac.new( - self.secret_key.encode('utf-8'), - payload.encode('utf-8'), - hashlib.sha256 - ).hexdigest() - - return hmac.compare_digest(computed_signature, signature) - - def process_webhook(self, payload): - """Process webhook payload""" - try: - data = json.loads(payload) - - # Extract key webhook information - repository = data.get('repository', {}) - commits = data.get('commits', []) - ref = data.get('ref', '') - - # Log basic webhook details - logging.info(f"Repository: {repository.get('full_name')}") - logging.info(f"Branch: {ref}") - logging.info(f"Number of Commits: {len(commits)}") - - # Custom processing logic here - for commit in commits: - logging.info(f"Commit: {commit.get('id')}") - logging.info(f"Message: {commit.get('message')}") - - except json.JSONDecodeError: - logging.error("Invalid JSON payload") - abort(400) - - -@app.route('/forgejo-webhook', methods=['POST']) -def webhook(): - processor = ForgejoWebhookProcessor('your_secret_key') - - # Get payload and signature - payload = request.get_data(as_text=True) - signature = request.headers.get('X-Forgejo-Signature', '') - - # Validate webhook - if not processor.validate_webhook(payload, signature): - abort(403) - - # Process webhook - processor.process_webhook(payload) - - return 'Webhook processed', 200 - -if __name__ == '__main__': - logging.basicConfig(level=logging.INFO) - app.run(host="0.0.0.0", port=5001) \ No newline at end of file diff --git a/koji_forgejo_webhook.conf b/koji_forgejo_webhook.conf new file mode 100644 index 0000000..801f543 --- /dev/null +++ b/koji_forgejo_webhook.conf @@ -0,0 +1,5 @@ +WSGIDaemonProcess forgejo processes=2 threads=4 +WSGIScriptAlias /forgejo-webhook /opt/koji-forgejo-webhook/koji_forgejo_webhook.wsgi + + Require all granted + diff --git a/koji_forgejo_webhook.py b/koji_forgejo_webhook.py new file mode 100644 index 0000000..c3ca073 --- /dev/null +++ b/koji_forgejo_webhook.py @@ -0,0 +1,122 @@ +import json +import hashlib +import hmac +import logging +import configparser +from flask import Flask, request, abort +import koji + +# Load configuration from .ini file +config = configparser.ConfigParser() +config.read('config.ini') + +app = Flask(__name__) +app.config.from_mapping(config['DEFAULT']) + + +class KojiProcessor: + def __init__(self): + pass + + def koji_build(self, server_url, build_target, source_url): + """ + Perform a Koji build + + :param server_url: Koji hub server URL + :param build_target: Target for the build (e.g., 'f40-candidate') + :param source_url: Git repository URL to build from + """ + # Create a Koji client session + session = koji.ClientSession(server_url) + + try: + # Authenticate (if required) + # Uncomment if authentication is needed + session.login() + + # Submit the build task + build_id = session.build( + source_url, # Source URL + build_target, # Build target + opts={ + 'scratch': False, # Set to True for scratch build + 'nowait': False # Wait for build completion + } + ) + + return build_id + + except Exception as e: + print(f"Build failed: {e}") + return None + + +class ForgejoWebhookProcessor: + def __init__(self, secret_key): + self.secret_key = secret_key + + def validate_webhook(self, payload, signature): + """Validate webhook signature""" + computed_signature = hmac.new( + self.secret_key.encode('utf-8'), + payload.encode('utf-8'), + hashlib.sha256 + ).hexdigest() + + return hmac.compare_digest(computed_signature, signature) + + def process_webhook(self, payload): + """Process webhook payload""" + try: + data = json.loads(payload) + + # Extract key webhook information + repository = data.get('repository', {}) + commits = data.get('commits', []) + head_commit = data.get('head_commit') + ref = data.get('ref', '') + + # Log basic webhook details + logging.info(f"Repository: {repository.get('full_name')}") + logging.info(f"Branch: {ref}") + logging.info(f"Number of Commits: {len(commits)}") + + # Custom processing logic here + # for commit in commits: + # logging.info(f"Commit: {commit.get('id')}") + # logging.info(f"Message: {commit.get('message')}") + + commit_id = head_commit.get("id") + clone_url = repository.get("clone_url") + + git_url = f"git+{clone_url}#{commit_id}" + + KojiProcessor().koji_build(app.config['KOJI_SERVER'], app.config['KOJI_TARGET'], git_url) + + except json.JSONDecodeError: + logging.error("Invalid JSON payload") + abort(400) + + +@app.route('/', methods=['POST']) +@app.route('/forgejo-webhook', methods=['POST']) +def webhook(): + processor = ForgejoWebhookProcessor(app.config['WEBHOOK_SECRET_KEY']) + + # Get payload and signature + payload = request.get_data(as_text=True) + signature = request.headers.get('X-Forgejo-Signature', '') + + # Validate webhook + if not processor.validate_webhook(payload, signature): + abort(403) + + # Process webhook + processor.process_webhook(payload) + + return 'Webhook processed', 200 + + +if __name__ == '__main__': + logging.basicConfig(level=logging.INFO) + app.run(host="0.0.0.0", port=5001) diff --git a/koji_forgejo_webhook.wsgi b/koji_forgejo_webhook.wsgi new file mode 100644 index 0000000..74515f5 --- /dev/null +++ b/koji_forgejo_webhook.wsgi @@ -0,0 +1,7 @@ +import sys +import logging + +logging.basicConfig(stream=sys.stderr) +sys.path.insert(0, "/opt/koji-forgejo-webhook") + +from koji_forgejo_webhook import app as application diff --git a/reequirements.txt b/reequirements.txt deleted file mode 100644 index 8ab6294..0000000 --- a/reequirements.txt +++ /dev/null @@ -1 +0,0 @@ -flask \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8f91ebc --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +flask +koji \ No newline at end of file