Compare commits

...

4 commits

Author SHA1 Message Date
3532fccead WIP add build execution with shell 2025-01-26 03:00:50 +03:00
2df80f6d41 WIP add trailing EOL 2025-01-25 22:41:37 +03:00
e6ab985c12 WIP add apache wsgi configuration 2025-01-25 22:07:39 +03:00
viacheslav anzhiganov
27b342623a add koji call 2025-01-25 05:56:19 +03:00
8 changed files with 169 additions and 70 deletions

View file

@ -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
```
```

6
config.ini Normal file
View file

@ -0,0 +1,6 @@
[DEFAULT]
SECRET_KEY = $3cr3tk3y
KOJI_SERVER = https://kojidev.stackwebservices.com/kojihub
KOJI_TARGET = rl9-candidate
KOJI_USE_SHELL = true
WEBHOOK_SECRET_KEY = your_secret_key

View file

@ -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)

View 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>

147
koji_forgejo_webhook.py Normal file
View file

@ -0,0 +1,147 @@
import json
import hashlib
import hmac
import logging
import configparser
import subprocess
from flask import Flask, request, abort, current_app
import koji
# Load configuration from .ini file
config = configparser.ConfigParser()
config.read('config.ini')
app = Flask(__name__, instance_relative_config=True)
# app.config.from_mapping(config['DEFAULT'])
app.config['SECRET_KEY'] = config.get('DEFAULT', 'SECRET_KEY')
app.config['KOJI_SERVER'] = config.get('DEFAULT', 'KOJI_SERVER')
app.config['KOJI_TARGET'] = config.get('DEFAULT', 'KOJI_TARGET')
app.config['KOJI_USE_SHELL'] = config.getboolean('DEFAULT', 'KOJI_USE_SHELL')
app.config['WEBHOOK_SECRET_KEY'] = config.get('DEFAULT', 'WEBHOOK_SECRET_KEY')
class KojiProcessor:
def __init__(self):
pass
def koji_build_shell(self, build_target, git_url):
try:
# Construct the koji build command
command = ['koji', 'build', build_target, git_url]
# Start the build process
result = subprocess.run(command, check=True, capture_output=True, text=True)
# Print output from the command
logging.info(f"Build started successfully!")
logging.info(result.stdout)
except subprocess.CalledProcessError as e:
logging.error("Error starting build:")
logging.error(e.stderr)
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}"
if int(app.config.get('KOJI_USE_SHELL')) == 1:
KojiProcessor().koji_build_shell(app.config['KOJI_TARGET'], git_url)
else:
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'])
@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)

View 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

View file

@ -1 +0,0 @@
flask

2
requirements.txt Normal file
View file

@ -0,0 +1,2 @@
flask
koji