release 0.1 #1
8 changed files with 143 additions and 70 deletions
|
@ -11,7 +11,7 @@ pip install -r requirements.txt
|
||||||
### rpm
|
### rpm
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
dnf install python3-flask
|
dnf install python3-flask python3-mod_wsgi
|
||||||
```
|
```
|
||||||
|
|
||||||
## run
|
## run
|
||||||
|
|
5
config.ini
Normal file
5
config.ini
Normal file
|
@ -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
|
|
@ -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)
|
|
5
koji_forgejo_webhook.conf
Normal file
5
koji_forgejo_webhook.conf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
WSGIDaemonProcess forgejo processes=2 threads=4
|
||||||
|
WSGIScriptAlias /forgejo-webhook /opt/koji-forgejo-webhook/koji_forgejo_webhook.wsgi
|
||||||
|
<Directory /opt/koji-forgejo-webhook>
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
122
koji_forgejo_webhook.py
Normal file
122
koji_forgejo_webhook.py
Normal file
|
@ -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)
|
7
koji_forgejo_webhook.wsgi
Normal file
7
koji_forgejo_webhook.wsgi
Normal file
|
@ -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
|
|
@ -1 +0,0 @@
|
||||||
flask
|
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
flask
|
||||||
|
koji
|
Loading…
Add table
Reference in a new issue