X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FConfig%2FNix.git;a=blobdiff_plain;f=modules%2Fprivate%2Fbuildbot%2Fcommon%2Fbuild_helpers.py;fp=modules%2Fprivate%2Fbuildbot%2Fcommon%2Fbuild_helpers.py;h=0000000000000000000000000000000000000000;hp=acea90591f5ca16b524e0e41b7d22087ef72cf7c;hb=1a64deeb894dc95e2645a75771732c6cc53a79ad;hpb=fa25ffd4583cc362075cd5e1b4130f33306103f0 diff --git a/modules/private/buildbot/common/build_helpers.py b/modules/private/buildbot/common/build_helpers.py deleted file mode 100644 index acea905..0000000 --- a/modules/private/buildbot/common/build_helpers.py +++ /dev/null @@ -1,277 +0,0 @@ -from buildbot.plugins import util, steps, schedulers -from buildbot_buildslist import BuildsList -from shutil import which - -__all__ = [ - "force_scheduler", "deploy_scheduler", "hook_scheduler", - "clean_branch", "package_and_upload", "SlackStatusPush", - "XMPPStatusPush", "NixShellCommand" - ] - -# Small helpers" -@util.renderer -def clean_branch(props): - if props.hasProperty("branch") and len(props["branch"]) > 0: - return props["branch"].replace("/", "_") - else: - return "HEAD" - -def package_and_upload(package, package_dest, package_url): - return [ - steps.ShellCommand(name="build package", - logEnviron=False, haltOnFailure=True, workdir="source", - command=["git", "archive", "HEAD", "-o", package]), - - steps.FileUpload(name="upload package", workersrc=package, - workdir="source", masterdest=package_dest, - url=package_url, mode=0o644), - - steps.ShellCommand(name="cleanup package", logEnviron=False, - haltOnFailure=True, workdir="source", alwaysRun=True, - command=["rm", "-f", package]), - ] - -# Steps -class NixShellCommand(steps.ShellCommand): - def __init__(self, command=None, pure=True, nixfile=None, **kwargs): - assert(isinstance(command, str)) - oldpath = kwargs.get("env", {}).get("PATH", None) - if which("nix-shell", path=oldpath) is None: - kwargs["env"] = kwargs.get("env", {}) - if isinstance(oldpath, str): - kwargs["env"]["PATH"] = "/run/current-system/sw/bin:" + oldpath - elif isinstance(oldpath, list): - kwargs["env"]["PATH"] = ["/run/current-system/sw/bin"] + oldpath - nixcommand = ["nix-shell"] - if pure: - nixcommand.append("--pure") - nixcommand.append("--run") - nixcommand.append(command) - if nixfile is not None: - nixcommand.append(nixfile) - super().__init__(command=nixcommand, **kwargs) - -# Schedulers -def force_scheduler(name, builders): - return schedulers.ForceScheduler(name=name, - label="Force build", buttonName="Force build", - reason=util.StringParameter(name="reason", label="Reason", default="Force build"), - codebases=[ - util.CodebaseParameter("", - branch=util.StringParameter( - name="branch", label="Git reference (tag, branch)", required=True), - revision=util.FixedParameter(name="revision", default=""), - repository=util.FixedParameter(name="repository", default=""), - project=util.FixedParameter(name="project", default=""), - ), - ], - username=util.FixedParameter(name="username", default="Web button"), - builderNames=builders) - -def deploy_scheduler(name, builders): - return schedulers.ForceScheduler(name=name, - builderNames=builders, - label="Deploy built package", buttonName="Deploy", - username=util.FixedParameter(name="username", default="Web button"), - codebases=[ - util.CodebaseParameter(codebase="", - branch=util.FixedParameter(name="branch", default=""), - revision=util.FixedParameter(name="revision", default=""), - repository=util.FixedParameter(name="repository", default=""), - project=util.FixedParameter(name="project", default=""))], - reason=util.FixedParameter(name="reason", default="Deploy"), - properties=[ - util.ChoiceStringParameter(label="Environment", - name="environment", default="integration", - choices=["integration", "production"]), - BuildsList(label="Build to deploy", name="build"), - ] - ) - -def hook_scheduler(project, timer=10): - return schedulers.AnyBranchScheduler( - change_filter=util.ChangeFilter(category="hooks", project=project), - name=project, treeStableTimer=timer, builderNames=["{}_build".format(project)]) - -# Slack/XMPP status push -from buildbot.reporters.http import HttpStatusPushBase -from twisted.internet import defer -from twisted.python import log -from buildbot.util import httpclientservice -from buildbot.reporters import utils -from buildbot.process import results -from twisted.words.protocols.jabber.jid import JID -from wokkel import client, xmppim -from functools import partial - -class SlackStatusPush(HttpStatusPushBase): - name = "SlackStatusPush" - - @defer.inlineCallbacks - def reconfigService(self, serverUrl, **kwargs): - yield HttpStatusPushBase.reconfigService(self, **kwargs) - self._http = yield httpclientservice.HTTPClientService.getService( - self.master, serverUrl) - - @defer.inlineCallbacks - def send(self, build): - yield utils.getDetailsForBuild(self.master, build, wantProperties=True) - response = yield self._http.post("", json=self.format(build)) - if response.code != 200: - log.msg("%s: unable to upload status: %s" % - (response.code, response.content)) - - def format(self, build): - colors = [ - "#36A64F", # success - "#F1E903", # warnings - "#DA0505", # failure - "#FFFFFF", # skipped - "#000000", # exception - "#FFFFFF", # retry - "#D02CA9", # cancelled - ] - - if "environment" in build["properties"]: - msg = "{} environment".format(build["properties"]["environment"][0]) - if "build" in build["properties"]: - msg = "of archive {} in ".format(build["properties"]["build"][0]) + msg - elif len(build["buildset"]["sourcestamps"][0]["branch"] or []) > 0: - msg = "revision {}".format(build["buildset"]["sourcestamps"][0]["branch"]) - else: - msg = "build" - - if build["complete"]: - timedelta = int((build["complete_at"] - build["started_at"]).total_seconds()) - hours, rest = divmod(timedelta, 3600) - minutes, seconds = divmod(rest, 60) - if hours > 0: - duration = "{}h {}min {}s".format(hours, minutes, seconds) - elif minutes > 0: - duration = "{}min {}s".format(minutes, seconds) - else: - duration = "{}s".format(seconds) - - text = "Build <{}|{}> of {}'s {} was {} in {}.".format( - build["url"], build["buildid"], - build["builder"]["name"], - msg, - results.Results[build["results"]], - duration, - ) - fields = [ - { - "title": "Build", - "value": "<{}|{}>".format(build["url"], build["buildid"]), - "short": True, - }, - { - "title": "Project", - "value": build["builder"]["name"], - "short": True, - }, - { - "title": "Build status", - "value": results.Results[build["results"]], - "short": True, - }, - { - "title": "Build duration", - "value": duration, - "short": True, - }, - ] - if "environment" in build["properties"]: - fields.append({ - "title": "Environment", - "value": build["properties"]["environment"][0], - "short": True, - }) - if "build" in build["properties"]: - fields.append({ - "title": "Archive", - "value": build["properties"]["build"][0], - "short": True, - }) - attachments = [{ - "fallback": "", - "color": colors[build["results"]], - "fields": fields - }] - else: - text = "Build <{}|{}> of {}'s {} started.".format( - build["url"], build["buildid"], - build["builder"]["name"], - msg, - ) - attachments = [] - - return { - "username": "Buildbot", - "icon_url": "http://docs.buildbot.net/current/_static/icon.png", - "text": text, - "attachments": attachments, - } - -class XMPPStatusPush(HttpStatusPushBase): - name = "XMPPStatusPush" - - @defer.inlineCallbacks - def reconfigService(self, password, recipients, **kwargs): - yield HttpStatusPushBase.reconfigService(self, **kwargs) - self.password = password - self.recipients = recipients - - @defer.inlineCallbacks - def send(self, build): - yield utils.getDetailsForBuild(self.master, build, wantProperties=True) - body = self.format(build) - factory = client.DeferredClientFactory(JID("notify_bot@immae.fr/buildbot"), self.password) - d = client.clientCreator(factory) - def send_message(recipient, stream): - message = xmppim.Message(recipient=JID(recipient), body=body) - message.stanzaType = 'chat' - stream.send(message.toElement()) - # To allow chaining - return stream - for recipient in self.recipients: - d.addCallback(partial(send_message, recipient)) - d.addCallback(lambda _: factory.streamManager.xmlstream.sendFooter()) - d.addErrback(log.err) - - def format(self, build): - if "environment" in build["properties"]: - msg = "{} environment".format(build["properties"]["environment"][0]) - if "build" in build["properties"]: - msg = "of archive {} in ".format(build["properties"]["build"][0]) + msg - elif len(build["buildset"]["sourcestamps"][0]["branch"] or []) > 0: - msg = "revision {}".format(build["buildset"]["sourcestamps"][0]["branch"]) - else: - msg = "build" - - if build["complete"]: - timedelta = int((build["complete_at"] - build["started_at"]).total_seconds()) - hours, rest = divmod(timedelta, 3600) - minutes, seconds = divmod(rest, 60) - if hours > 0: - duration = "{}h {}min {}s".format(hours, minutes, seconds) - elif minutes > 0: - duration = "{}min {}s".format(minutes, seconds) - else: - duration = "{}s".format(seconds) - - text = "Build {} ( {} ) of {}'s {} was {} in {}.".format( - build["buildid"], build["url"], - build["builder"]["name"], - msg, - results.Results[build["results"]], - duration, - ) - else: - text = "Build {} ( {} ) of {}'s {} started.".format( - build["buildid"], build["url"], - build["builder"]["name"], - msg, - ) - - return text