Skip to content

Instantly share code, notes, and snippets.

@WorkingRobot
Created May 1, 2022 08:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WorkingRobot/818cdae0b7e14c1a5ea0a3f1a64d54aa to your computer and use it in GitHub Desktop.
Save WorkingRobot/818cdae0b7e14c1a5ea0a3f1a64d54aa to your computer and use it in GitHub Desktop.
Link your GitHub Actions to Gitea's CI API
#!/usr/bin/python3
import hashlib, hmac
import humanize
import json
import requests
from dateutil import parser
from http.server import HTTPServer, BaseHTTPRequestHandler
BIND_IP = "127.0.0.1"
BIND_PORT = 3001
WEBHOOK_SECRET = b"github webhook secret here"
GITEA_PATH = "https://try.gitea.io"
GITEA_OWNER = "asriel"
GITEA_REPO = "L4"
GITEA_TOKEN = "gitea-access-token-here"
def job_get_context(job):
return job['name']
def job_get_description(job):
if job['status'] == 'completed':
human_state = {
'success': 'Successful',
'failure': 'Failure',
'neutral': 'Neutral',
'cancelled': 'Cancelled',
'timed_out': 'Timed Out',
'action_required': 'Action Required',
'stale': 'Stale'
}[job['conclusion']]
return "{} ({})".format(human_state, humanize.naturaldelta(parser.parse(job['completed_at']) - parser.parse(job['started_at'])))
elif job['status'] == 'in_progress':
return "In Progress"
elif job['status'] == 'queued':
return "Queued"
def job_get_state(job):
if job['status'] == 'completed':
return {
'success': 'success',
'failure': 'failure',
'neutral': 'success',
'cancelled': 'failure',
'timed_out': 'error',
'action_required': 'warning',
'stale': 'error'
}[job['conclusion']]
return 'pending'
def job_get_target_url(job):
if 'details_url' in job:
return job['details_url']
return job['html_url']
class WebHook(BaseHTTPRequestHandler):
def validate_signature(self, data):
if not WEBHOOK_SECRET:
return True
algo, signature = self.headers['X-Hub-Signature-256'].split('=')
if algo != 'sha256':
return False
return hmac.compare_digest(hmac.new(WEBHOOK_SECRET, msg=data, digestmod=hashlib.sha256).hexdigest(), signature)
def handle_event(self, event, data):
if event != 'workflow_job':
return
job = data['workflow_job']
requests.post(
"{}/api/v1/repos/{}/{}/statuses/{}".format(GITEA_PATH, GITEA_OWNER, GITEA_REPO, job['head_sha']),
headers={
'Authorization': 'token {}'.format(GITEA_TOKEN)
},
json={
'context': job_get_context(job),
'description': job_get_description(job),
'state': job_get_state(job),
'target_url': job_get_target_url(job)
}
)
def do_POST(self):
data_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(data_length)
if not self.validate_signature(post_data):
self.send_response(401)
self.end_headers()
return
self.handle_event(self.headers['X-GitHub-Event'], json.loads(post_data.decode('utf-8')))
self.send_response(200)
self.end_headers()
httpd = HTTPServer((BIND_IP, BIND_PORT), WebHook)
httpd.serve_forever()
[Unit]
Description=Gitea GitHub Actions Webhook
After=gitea.service
[Service]
RestartSec=2s
Type=simple
User=git
Group=git
ExecStart=/usr/local/bin/gitea-actions
Restart=always
[Install]
WantedBy=multi-user.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment