2020-07-13 19:29:20 +02:00
|
|
|
import email.utils
|
2020-07-13 22:14:59 +02:00
|
|
|
import json
|
2020-08-28 18:09:20 +02:00
|
|
|
import random
|
2020-07-13 22:14:59 +02:00
|
|
|
import yaml
|
|
|
|
from flask import url_for
|
|
|
|
from hubsrht.services import builds, git, lists
|
2020-07-13 19:29:20 +02:00
|
|
|
from hubsrht.types import SourceRepo, RepoType
|
|
|
|
from sqlalchemy import func
|
2020-07-13 22:14:59 +02:00
|
|
|
from srht.config import get_origin
|
|
|
|
from srht.crypto import fernet
|
2020-07-13 19:29:20 +02:00
|
|
|
|
|
|
|
def submit_patchset(ml, payload):
|
2020-07-13 22:14:59 +02:00
|
|
|
buildsrht = get_origin("builds.sr.ht", external=True, default=None)
|
|
|
|
if not buildsrht:
|
2020-07-13 19:29:20 +02:00
|
|
|
return None
|
|
|
|
from buildsrht.manifest import Manifest, Task
|
|
|
|
from buildsrht.manifest import Trigger, TriggerAction, TriggerCondition
|
|
|
|
|
|
|
|
project = ml.project
|
|
|
|
subject = payload["subject"]
|
2020-07-13 20:16:19 +02:00
|
|
|
|
2020-07-13 19:29:20 +02:00
|
|
|
prefix = payload["prefix"]
|
2020-07-13 20:16:19 +02:00
|
|
|
if not prefix:
|
|
|
|
# TODO: More sophisticated matching is possible
|
|
|
|
# - test if patch is applicable to a repo; see the following:
|
|
|
|
# https://github.com/libgit2/pygit2/pull/1019
|
|
|
|
# Will be useful for mailing lists shared by many repositories
|
|
|
|
return None
|
|
|
|
|
2020-07-13 19:29:20 +02:00
|
|
|
repo = (SourceRepo.query
|
|
|
|
.filter(SourceRepo.project_id == project.id)
|
|
|
|
.filter(func.lower(SourceRepo.name) == prefix.lower())).one_or_none()
|
2020-07-13 19:39:26 +02:00
|
|
|
if not repo:
|
|
|
|
return None
|
2020-07-13 19:29:20 +02:00
|
|
|
if repo.repo_type != RepoType.git:
|
|
|
|
# TODO: support for hg.sr.ht
|
|
|
|
return None
|
2022-02-04 15:41:36 +01:00
|
|
|
manifests = git.get_manifests(repo.owner, repo.name)
|
2020-07-13 19:29:20 +02:00
|
|
|
if not manifests:
|
|
|
|
return None
|
2020-08-21 15:34:10 +02:00
|
|
|
if len(manifests) > 4:
|
2020-08-28 18:09:20 +02:00
|
|
|
keys = list(manifests.keys())
|
|
|
|
random.shuffle(keys)
|
|
|
|
manifests = { key: manifests[key] for key in keys[:4] }
|
2020-08-21 15:34:10 +02:00
|
|
|
|
2020-07-13 19:29:20 +02:00
|
|
|
ids = []
|
2020-07-23 18:58:38 +02:00
|
|
|
|
|
|
|
version = payload["version"]
|
|
|
|
if version == 1:
|
|
|
|
version = ""
|
|
|
|
else:
|
|
|
|
version = f" v{version}"
|
|
|
|
|
|
|
|
reply_to = payload.get("reply_to")
|
|
|
|
if reply_to:
|
|
|
|
submitter = email.utils.parseaddr(reply_to)
|
|
|
|
else:
|
|
|
|
submitter = email.utils.parseaddr(payload["submitter"])
|
|
|
|
|
|
|
|
build_note = f"""[{subject}][0]{version} from [{submitter[0]}][1]
|
|
|
|
|
|
|
|
[0]: {ml.url()}/patches/{payload["id"]}
|
|
|
|
[1]: mailto:{submitter[1]}"""
|
|
|
|
|
2020-07-13 19:29:20 +02:00
|
|
|
for key, value in manifests.items():
|
2020-07-13 22:14:59 +02:00
|
|
|
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}")
|
|
|
|
|
2020-08-26 15:42:15 +02:00
|
|
|
try:
|
|
|
|
manifest = Manifest(yaml.safe_load(value))
|
|
|
|
except:
|
|
|
|
# TODO: Maybe we should email the user with the error details?
|
|
|
|
return
|
2020-07-13 19:29:20 +02:00
|
|
|
# TODO: https://todo.sr.ht/~sircmpwn/builds.sr.ht/291
|
|
|
|
task = Task({
|
|
|
|
"_apply_patch": f"""echo Applying patch from lists.sr.ht
|
|
|
|
git config --global user.name 'builds.sr.ht'
|
|
|
|
git config --global user.email builds@sr.ht
|
|
|
|
cd {repo.name}
|
2020-10-25 11:38:28 +01:00
|
|
|
curl -sS {ml.url()}/patches/{payload["id"]}/mbox >/tmp/{payload["id"]}.patch
|
2020-07-13 19:29:20 +02:00
|
|
|
git am -3 /tmp/{payload["id"]}.patch"""
|
|
|
|
})
|
|
|
|
manifest.tasks.insert(0, task)
|
|
|
|
|
2021-02-03 20:35:03 +01:00
|
|
|
if not manifest.environment:
|
|
|
|
manifest.environment = {}
|
2021-01-30 17:41:01 +01:00
|
|
|
|
2021-02-03 20:35:03 +01:00
|
|
|
manifest.environment.setdefault("BUILD_SUBMITTER", "hub.sr.ht")
|
|
|
|
manifest.environment.setdefault("BUILD_REASON", "patchset")
|
|
|
|
manifest.environment.setdefault("PATCHSET_ID", payload["id"])
|
|
|
|
manifest.environment.setdefault("PATCHSET_URL",
|
|
|
|
f"{ml.url()}/patches/{payload['id']}")
|
2021-01-30 17:41:01 +01:00
|
|
|
|
2020-07-23 18:58:38 +02:00
|
|
|
# Add webhook trigger
|
2020-07-13 22:14:59 +02:00
|
|
|
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,
|
2021-02-20 15:23:25 +01:00
|
|
|
"user": project.owner.canonical_name,
|
2020-07-13 22:14:59 +02:00
|
|
|
}).encode()).decode()
|
|
|
|
manifest.triggers.append(Trigger({
|
|
|
|
"action": TriggerAction.webhook,
|
|
|
|
"condition": TriggerCondition.always,
|
|
|
|
"url": root + url_for("webhooks.build_complete", details=details),
|
|
|
|
}))
|
|
|
|
|
2020-07-23 18:58:38 +02:00
|
|
|
b = builds.submit_build(project.owner, manifest, build_note,
|
|
|
|
tags=[repo.name, "patches", key], execute=False)
|
2020-07-13 19:29:20 +02:00
|
|
|
ids.append(b["id"])
|
2020-07-13 22:14:59 +02:00
|
|
|
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}")
|
2020-07-23 18:58:38 +02:00
|
|
|
|
|
|
|
trigger = Trigger({
|
|
|
|
"action": TriggerAction.email,
|
|
|
|
"condition": TriggerCondition.always,
|
|
|
|
})
|
|
|
|
trigger.attrs["to"] = email.utils.formataddr(submitter)
|
|
|
|
trigger.attrs["cc"] = ml.posting_addr()
|
|
|
|
trigger.attrs["in_reply_to"] = payload["message_id"]
|
|
|
|
builds.create_group(project.owner, ids, build_note, [trigger.to_dict()])
|
2020-07-13 19:29:20 +02:00
|
|
|
return ids
|