Rig up build status to lists.sr.ht tool status

This commit is contained in:
Drew DeVault 2020-07-13 16:14:59 -04:00
parent 8f14fd4776
commit 581af620f0
3 changed files with 74 additions and 6 deletions

View File

@ -3,11 +3,11 @@ import json
from datetime import datetime
from flask import Blueprint, request, current_app
from hubsrht.builds import submit_patchset
from hubsrht.services import todo
from hubsrht.services import todo, lists
from hubsrht.types import Event, EventType, MailingList, SourceRepo, RepoType
from hubsrht.types import Tracker, User, Visibility
from srht.config import get_origin
from srht.crypto import verify_request_signature
from srht.crypto import fernet, verify_request_signature
from srht.database import db
from srht.flask import csrf_bypass
from urllib.parse import quote
@ -334,3 +334,26 @@ def todo_ticket(tracker_id):
return "Thanks!"
else:
raise NotImplementedError()
@csrf_bypass
@webhooks.route("/webhooks/build-complete/<details>", methods=["POST"])
def build_complete(details):
payload = json.loads(request.data.decode())
details = fernet.decrypt(details.encode())
if not details:
return "Bad payload", 400
details = json.loads(details.decode())
ml = (MailingList.query
.filter(MailingList.id == details["mailing_list"])).one_or_none()
if not ml:
return "Unknown mailing list", 404
project = ml.project
buildsrht = get_origin("builds.sr.ht", external=True)
build_url = f"{buildsrht}/{project.owner.canonical_name}/job/{payload['id']}"
lists.patchset_set_tool(ml.owner, ml.name, details["patchset_id"],
details['key'], payload["status"],
f"[#{payload['id']}]({build_url}) {details['name']} {payload['status']}")
return "Thanks!"

View File

@ -1,12 +1,16 @@
import yaml
import email.utils
from srht.config import get_origin
from hubsrht.services import builds, git
import json
import yaml
from flask import url_for
from hubsrht.services import builds, git, lists
from hubsrht.types import SourceRepo, RepoType
from sqlalchemy import func
from srht.config import get_origin
from srht.crypto import fernet
def submit_patchset(ml, payload):
if not get_origin("builds.sr.ht", default=None):
buildsrht = get_origin("builds.sr.ht", external=True, default=None)
if not buildsrht:
return None
from buildsrht.manifest import Manifest, Task
from buildsrht.manifest import Trigger, TriggerAction, TriggerCondition
@ -36,6 +40,10 @@ def submit_patchset(ml, payload):
# TODO: Add UI to lists.sr.ht indicating build status
ids = []
for key, value in manifests.items():
tool_key = f"hub.sr.ht:builds.sr.ht:{key}"
lists.patchset_set_tool(ml.owner, ml.name, payload["id"],
tool_key, "pending", f"build pending: {key}")
manifest = Manifest(yaml.safe_load(value))
# TODO: https://todo.sr.ht/~sircmpwn/builds.sr.ht/291
task = Task({
@ -58,6 +66,19 @@ git am -3 /tmp/{payload["id"]}.patch"""
manifest.triggers.append(trigger)
trigger.condition = TriggerCondition.always
root = get_origin("hub.sr.ht", external=True)
details = fernet.encrypt(json.dumps({
"mailing_list": ml.id,
"patchset_id": payload["id"],
"key": tool_key,
"name": key,
}).encode()).decode()
manifest.triggers.append(Trigger({
"action": TriggerAction.webhook,
"condition": TriggerCondition.always,
"url": root + url_for("webhooks.build_complete", details=details),
}))
addrs = email.utils.getaddresses(trigger.attrs.get("to", ""))
submitter = email.utils.parseaddr(payload["submitter"])
if submitter not in addrs:
@ -82,4 +103,7 @@ git am -3 /tmp/{payload["id"]}.patch"""
[0]: {ml.url()}/patches/{payload["id"]}
[1]: mailto:{submitter[1]}""", tags=[repo.name, "patches", key])
ids.append(b["id"])
build_url = f"{buildsrht}/{project.owner.canonical_name}/job/{b['id']}"
lists.patchset_set_tool(ml.owner, ml.name, payload["id"],
tool_key, "waiting", f"[#{b['id']}]({build_url}) running {key}")
return ids

View File

@ -44,6 +44,19 @@ class SrhtService(ABC):
raise Exception(r.text)
return r.json()
def put(self, user, valid, url, payload):
r = self.session.put(url,
headers=get_authorization(user),
json=payload)
if r.status_code == 400:
if valid:
for error in r.json()["errors"]:
valid.error(error["reason"], field=error.get("field"))
return None
elif r.status_code not in [200, 201]:
raise Exception(r.text)
return r.json()
manifests_query = """
query Manifests($repoId: Int!) {
repository(id: $repoId) {
@ -262,6 +275,14 @@ class ListService(SrhtService):
if r.status_code != 204 and r.status_code != 404:
raise Exception(r.text)
def patchset_set_tool(self, user, list_name, patchset_id, key, icon, details):
return self.put(user, None,
f"{_listsrht}/api/lists/{list_name}/patchsets/{patchset_id}/tools", {
"key": key,
"icon": icon,
"details": details,
})
class TodoService(SrhtService):
def get_trackers(self, user):
return get_results(f"{_todosrht}/api/trackers", user)