Get back to original
This commit is contained in:
parent
77ae214d24
commit
5cc9d7b0e9
68 changed files with 83 additions and 42 deletions
294
buildbot/config/gitea/reporter.py
Normal file
294
buildbot/config/gitea/reporter.py
Normal file
|
@ -0,0 +1,294 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
# SPDX-FileCopyrightText: 2018 LAB132
|
||||
# SPDX-FileCopyrightText: 2013-2024 Blender Authors
|
||||
# <pep8 compliant>
|
||||
|
||||
# Based on the gitlab reporter from buildbot
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from twisted.internet import defer
|
||||
from twisted.python import log
|
||||
|
||||
from buildbot.process.properties import Interpolate
|
||||
from buildbot.process.properties import Properties
|
||||
from buildbot.process.results import CANCELLED
|
||||
from buildbot.process.results import EXCEPTION
|
||||
from buildbot.process.results import FAILURE
|
||||
from buildbot.process.results import RETRY
|
||||
from buildbot.process.results import SKIPPED
|
||||
from buildbot.process.results import SUCCESS
|
||||
from buildbot.process.results import WARNINGS
|
||||
from buildbot.reporters import http
|
||||
from buildbot.util import httpclientservice
|
||||
from buildbot.reporters.generators.build import BuildStartEndStatusGenerator
|
||||
from buildbot.reporters.message import MessageFormatterRenderable
|
||||
|
||||
|
||||
import re
|
||||
|
||||
|
||||
# This name has a number in it to trick buildbot into reloading it on without
|
||||
# restart. Needs to be incremented every time this file is changed. Is there
|
||||
# a better solution?
|
||||
class GiteaStatusService11(http.ReporterBase):
|
||||
name = "GiteaStatusService11"
|
||||
ssh_url_match = re.compile(
|
||||
r"(ssh://)?[\w+\-\_]+@[\w\.\-\_]+:?(\d*/)?(?P<owner>[\w_\-\.]+)/(?P<repo_name>[\w_\-\.]+?)(\.git)?$"
|
||||
)
|
||||
|
||||
def checkConfig(
|
||||
self,
|
||||
baseURL,
|
||||
token,
|
||||
context=None,
|
||||
context_pr=None,
|
||||
verbose=False,
|
||||
debug=None,
|
||||
verify=None,
|
||||
generators=None,
|
||||
warningAsSuccess=False,
|
||||
**kwargs,
|
||||
):
|
||||
if generators is None:
|
||||
generators = self._create_default_generators()
|
||||
|
||||
super().checkConfig(generators=generators, **kwargs)
|
||||
httpclientservice.HTTPClientService.checkAvailable(self.__class__.__name__)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def reconfigService(
|
||||
self,
|
||||
baseURL,
|
||||
token,
|
||||
context=None,
|
||||
context_pr=None,
|
||||
verbose=False,
|
||||
debug=None,
|
||||
verify=None,
|
||||
generators=None,
|
||||
warningAsSuccess=False,
|
||||
**kwargs,
|
||||
):
|
||||
token = yield self.renderSecrets(token)
|
||||
self.debug = debug
|
||||
self.verify = verify
|
||||
self.verbose = verbose
|
||||
if generators is None:
|
||||
generators = self._create_default_generators()
|
||||
|
||||
yield super().reconfigService(generators=generators, **kwargs)
|
||||
|
||||
self.context = context or Interpolate("buildbot/%(prop:buildername)s")
|
||||
self.context_pr = context_pr or Interpolate(
|
||||
"buildbot/pull_request/%(prop:buildername)s"
|
||||
)
|
||||
if baseURL.endswith("/"):
|
||||
baseURL = baseURL[:-1]
|
||||
self.baseURL = baseURL
|
||||
self._http = yield httpclientservice.HTTPClientService.getService(
|
||||
self.master,
|
||||
baseURL,
|
||||
headers={"Authorization": "token {}".format(token)},
|
||||
debug=self.debug,
|
||||
verify=self.verify,
|
||||
)
|
||||
self.verbose = verbose
|
||||
self.project_ids = {}
|
||||
self.warningAsSuccess = warningAsSuccess
|
||||
|
||||
def _create_default_generators(self):
|
||||
start_formatter = MessageFormatterRenderable("Build started.")
|
||||
end_formatter = MessageFormatterRenderable("Build done.")
|
||||
|
||||
return [
|
||||
BuildStartEndStatusGenerator(
|
||||
start_formatter=start_formatter, end_formatter=end_formatter
|
||||
)
|
||||
]
|
||||
|
||||
def createStatus(
|
||||
self,
|
||||
project_owner,
|
||||
repo_name,
|
||||
sha,
|
||||
state,
|
||||
target_url=None,
|
||||
description=None,
|
||||
context=None,
|
||||
):
|
||||
"""
|
||||
:param project_owner: username of the owning user or organization
|
||||
:param repo_name: name of the repository
|
||||
:param sha: Full sha to create the status for.
|
||||
:param state: one of the following 'pending', 'success', 'failed'
|
||||
or 'cancelled'.
|
||||
:param target_url: Target url to associate with this status.
|
||||
:param description: Short description of the status.
|
||||
:param context: Context of the result
|
||||
:return: A deferred with the result from GitLab.
|
||||
|
||||
"""
|
||||
payload = {"state": state}
|
||||
|
||||
if description is not None:
|
||||
payload["description"] = description
|
||||
|
||||
if target_url is not None:
|
||||
payload["target_url"] = target_url
|
||||
|
||||
if context is not None:
|
||||
payload["context"] = context
|
||||
|
||||
url = "/api/v1/repos/{owner}/{repository}/statuses/{sha}".format(
|
||||
owner=project_owner, repository=repo_name, sha=sha
|
||||
)
|
||||
log.msg(f"Sending status to {url}: {payload}")
|
||||
|
||||
return self._http.post(url, json=payload)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def sendMessage(self, reports):
|
||||
yield self._send_impl(reports)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _send_status(
|
||||
self, build, repository_owner, repository_name, sha, state, context, description
|
||||
):
|
||||
try:
|
||||
target_url = build["url"]
|
||||
res = yield self.createStatus(
|
||||
project_owner=repository_owner,
|
||||
repo_name=repository_name,
|
||||
sha=sha,
|
||||
state=state,
|
||||
target_url=target_url,
|
||||
context=context,
|
||||
description=description,
|
||||
)
|
||||
if res.code not in (200, 201, 204):
|
||||
message = yield res.json()
|
||||
message = message.get("message", "unspecified error")
|
||||
log.msg(
|
||||
'Could not send status "{state}" for '
|
||||
"{repo} at {sha}: {code} : {message}".format(
|
||||
state=state,
|
||||
repo=repository_name,
|
||||
sha=sha,
|
||||
code=res.code,
|
||||
message=message,
|
||||
)
|
||||
)
|
||||
elif self.verbose:
|
||||
log.msg(
|
||||
'Status "{state}" sent for ' "{repo} at {sha}.".format(
|
||||
state=state, repo=repository_name, sha=sha
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
log.err(
|
||||
e,
|
||||
'Failed to send status "{state}" for ' "{repo} at {sha}".format(
|
||||
state=state, repo=repository_name, sha=sha
|
||||
),
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _send_impl(self, reports):
|
||||
for report in reports:
|
||||
try:
|
||||
builds = report["builds"]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
for build in builds:
|
||||
builder_name = build["builder"]["name"]
|
||||
|
||||
props = Properties.fromDict(build["properties"])
|
||||
props.master = self.master
|
||||
|
||||
description = report.get("body", None)
|
||||
|
||||
if build["complete"]:
|
||||
state = {
|
||||
SUCCESS: "success",
|
||||
WARNINGS: "success" if self.warningAsSuccess else "warning",
|
||||
FAILURE: "failure",
|
||||
SKIPPED: "success",
|
||||
EXCEPTION: "error",
|
||||
RETRY: "pending",
|
||||
CANCELLED: "error",
|
||||
}.get(build["results"], "failure")
|
||||
else:
|
||||
state = "pending"
|
||||
|
||||
if "pr_id" in props:
|
||||
context = yield props.render(self.context_pr)
|
||||
else:
|
||||
context = yield props.render(self.context)
|
||||
|
||||
sourcestamps = build["buildset"]["sourcestamps"]
|
||||
|
||||
# BLENDER: some hardcoded logic for now.
|
||||
if (
|
||||
"-code-daily-" in builder_name
|
||||
or "-code-patch-" in builder_name
|
||||
or "-code-experimental-" in builder_name
|
||||
):
|
||||
repository_owner = "blender"
|
||||
repository_name = "blender"
|
||||
elif "-doc-manual-" in builder_name:
|
||||
repository_owner = "blender"
|
||||
repository_name = "blender-manual"
|
||||
elif "-doc-developer" in builder_name:
|
||||
repository_owner = "blender"
|
||||
repository_name = "blender-developer-docs"
|
||||
else:
|
||||
continue
|
||||
|
||||
# Source change from Git poller.
|
||||
for sourcestamp in sourcestamps:
|
||||
sha = sourcestamp["revision"]
|
||||
if sha not in {None, "", "HEAD"}:
|
||||
self._send_status(
|
||||
build,
|
||||
repository_owner,
|
||||
repository_name,
|
||||
sha,
|
||||
state,
|
||||
context,
|
||||
description,
|
||||
)
|
||||
continue
|
||||
|
||||
# Revision specified by get-revision step.
|
||||
if "revision" in props:
|
||||
sha = props["revision"]
|
||||
if sha not in {None, "", "HEAD"}:
|
||||
self._send_status(
|
||||
build,
|
||||
repository_owner,
|
||||
repository_name,
|
||||
sha,
|
||||
state,
|
||||
context,
|
||||
description,
|
||||
)
|
||||
|
||||
# Revision from blender-bot, so we can send a status before
|
||||
# the get-revision step runs.
|
||||
if "pull_revision" in props:
|
||||
sha = props["pull_revision"]
|
||||
if sha not in {None, "", "HEAD"}:
|
||||
self._send_status(
|
||||
build,
|
||||
repository_owner,
|
||||
repository_name,
|
||||
sha,
|
||||
state,
|
||||
context,
|
||||
description,
|
||||
)
|
||||
|
||||
continue
|
Loading…
Add table
Add a link
Reference in a new issue