]>
git.immae.eu Git - perso/Immae/Config/Nix.git/blob - nixops/modules/buildbot/common/build_helpers.py
63733e7b31ec4b264eba8e62d46657c992940e1e
1 from buildbot
.plugins
import util
, steps
, schedulers
2 from buildbot_buildslist
import BuildsList
5 "force_scheduler", "deploy_scheduler", "hook_scheduler",
6 "clean_branch", "package_and_upload", "SlackStatusPush",
12 def clean_branch(props
):
13 if props
.hasProperty("branch") and len(props
["branch"]) > 0:
14 return props
["branch"].replace("/", "_")
18 def package_and_upload(package
, package_dest
, package_url
):
20 steps
.ShellCommand(name
="build package",
21 logEnviron
=False, haltOnFailure
=True, workdir
="source",
22 command
=["git", "archive", "HEAD", "-o", package
]),
24 steps
.FileUpload(name
="upload package", workersrc
=package
,
25 workdir
="source", masterdest
=package_dest
,
26 url
=package_url
, mode
=0o644),
28 steps
.ShellCommand(name
="cleanup package", logEnviron
=False,
29 haltOnFailure
=True, workdir
="source", alwaysRun
=True,
30 command
=["rm", "-f", package
]),
34 def force_scheduler(name
, builders
):
35 return schedulers
.ForceScheduler(name
=name
,
36 label
="Force build", buttonName
="Force build",
37 reason
=util
.StringParameter(name
="reason", label
="Reason", default
="Force build"),
39 util
.CodebaseParameter("",
40 branch
=util
.StringParameter(
41 name
="branch", label
="Git reference (tag, branch)", required
=True),
42 revision
=util
.FixedParameter(name
="revision", default
=""),
43 repository
=util
.FixedParameter(name
="repository", default
=""),
44 project
=util
.FixedParameter(name
="project", default
=""),
47 username
=util
.FixedParameter(name
="username", default
="Web button"),
48 builderNames
=builders
)
50 def deploy_scheduler(name
, builders
):
51 return schedulers
.ForceScheduler(name
=name
,
52 builderNames
=builders
,
53 label
="Deploy built package", buttonName
="Deploy",
54 username
=util
.FixedParameter(name
="username", default
="Web button"),
56 util
.CodebaseParameter(codebase
="",
57 branch
=util
.FixedParameter(name
="branch", default
=""),
58 revision
=util
.FixedParameter(name
="revision", default
=""),
59 repository
=util
.FixedParameter(name
="repository", default
=""),
60 project
=util
.FixedParameter(name
="project", default
=""))],
61 reason
=util
.FixedParameter(name
="reason", default
="Deploy"),
63 util
.ChoiceStringParameter(label
="Environment",
64 name
="environment", default
="integration",
65 choices
=["integration", "production"]),
66 BuildsList(label
="Build to deploy", name
="build"),
70 def hook_scheduler(project
, timer
=10):
71 return schedulers
.AnyBranchScheduler(
72 change_filter
=util
.ChangeFilter(category
="hooks", project
=project
),
73 name
=project
, treeStableTimer
=timer
, builderNames
=["{}_build".format(project
)])
75 # Slack/XMPP status push
76 from buildbot
.reporters
.http
import HttpStatusPushBase
77 from twisted
.internet
import defer
78 from twisted
.python
import log
79 from buildbot
.util
import httpclientservice
80 from buildbot
.reporters
import utils
81 from buildbot
.process
import results
82 from twisted
.words
.protocols
.jabber
.jid
import JID
83 from wokkel
import client
, xmppim
86 class SlackStatusPush(HttpStatusPushBase
):
87 name
= "SlackStatusPush"
89 @defer.inlineCallbacks
90 def reconfigService(self
, serverUrl
, **kwargs
):
91 yield HttpStatusPushBase
.reconfigService(self
, **kwargs
)
92 self
._http
= yield httpclientservice
.HTTPClientService
.getService(
93 self
.master
, serverUrl
)
95 @defer.inlineCallbacks
96 def send(self
, build
):
97 yield utils
.getDetailsForBuild(self
.master
, build
, wantProperties
=True)
98 response
= yield self
._http
.post("", json
=self
.format(build
))
99 if response
.code
!= 200:
100 log
.msg("%s: unable to upload status: %s" %
101 (response
.code
, response
.content
))
103 def format(self
, build
):
106 "#F1E903", # warnings
109 "#000000", # exception
111 "#D02CA9", # cancelled
114 if "environment" in build
["properties"]:
115 msg
= "{} environment".format(build
["properties"]["environment"][0])
116 if "build" in build
["properties"]:
117 msg
= "of archive {} in ".format(build
["properties"]["build"][0]) + msg
118 elif len(build
["buildset"]["sourcestamps"][0]["branch"]) > 0:
119 msg
= "revision {}".format(build
["buildset"]["sourcestamps"][0]["branch"])
123 if build
["complete"]:
124 timedelta
= int((build
["complete_at"] - build
["started_at"]).total_seconds())
125 hours
, rest
= divmod(timedelta
, 3600)
126 minutes
, seconds
= divmod(rest
, 60)
128 duration
= "{}h {}min {}s".format(hours
, minutes
, seconds
)
130 duration
= "{}min {}s".format(minutes
, seconds
)
132 duration
= "{}s".format(seconds
)
134 text
= "Build <{}|{}> of {}'s {} was {} in {}.".format(
135 build
["url"], build
["buildid"],
136 build
["builder"]["name"],
138 results
.Results
[build
["results"]],
144 "value": "<{}|{}>".format(build
["url"], build
["buildid"]),
149 "value": build
["builder"]["name"],
153 "title": "Build status",
154 "value": results
.Results
[build
["results"]],
158 "title": "Build duration",
163 if "environment" in build
["properties"]:
165 "title": "Environment",
166 "value": build
["properties"]["environment"][0],
169 if "build" in build
["properties"]:
172 "value": build
["properties"]["build"][0],
177 "color": colors
[build
["results"]],
181 text
= "Build <{}|{}> of {}'s {} started.".format(
182 build
["url"], build
["buildid"],
183 build
["builder"]["name"],
189 "username": "Buildbot",
190 "icon_url": "http://docs.buildbot.net/current/_static/icon.png",
192 "attachments": attachments
,
195 class XMPPStatusPush(HttpStatusPushBase
):
196 name
= "XMPPStatusPush"
198 @defer.inlineCallbacks
199 def reconfigService(self
, password
, recipients
, **kwargs
):
200 yield HttpStatusPushBase
.reconfigService(self
, **kwargs
)
201 self
.password
= password
202 self
.recipients
= recipients
204 @defer.inlineCallbacks
205 def send(self
, build
):
206 yield utils
.getDetailsForBuild(self
.master
, build
, wantProperties
=True)
207 body
= self
.format(build
)
208 factory
= client
.DeferredClientFactory(JID("notify_bot@immae.fr/buildbot"), self
.password
)
209 factory
.streamManager
.logTraffic
= True
210 d
= client
.clientCreator(factory
)
211 def send_message(stream
):
212 message
= xmppim
.Message(recipient
=JID(recipient
), body
=body
)
213 message
.stanzaType
= 'chat'
214 stream
.send(message
.toElement())
217 for recipient
in self
.recipients
:
218 d
.addCallback(send_message
)
219 d
.addCallback(lambda _
: factory
.streamManager
.xmlstream
.sendFooter())
220 d
.addErrback(log
.err
)
222 def format(self
, build
):
223 if "environment" in build
["properties"]:
224 msg
= "{} environment".format(build
["properties"]["environment"][0])
225 if "build" in build
["properties"]:
226 msg
= "of archive {} in ".format(build
["properties"]["build"][0]) + msg
227 elif len(build
["buildset"]["sourcestamps"][0]["branch"]) > 0:
228 msg
= "revision {}".format(build
["buildset"]["sourcestamps"][0]["branch"])
232 if build
["complete"]:
233 timedelta
= int((build
["complete_at"] - build
["started_at"]).total_seconds())
234 hours
, rest
= divmod(timedelta
, 3600)
235 minutes
, seconds
= divmod(rest
, 60)
237 duration
= "{}h {}min {}s".format(hours
, minutes
, seconds
)
239 duration
= "{}min {}s".format(minutes
, seconds
)
241 duration
= "{}s".format(seconds
)
243 text
= "Build {} ( {} ) of {}'s {} was {} in {}.".format(
244 build
["buildid"], build
["url"],
245 build
["builder"]["name"],
247 results
.Results
[build
["results"]],
251 text
= "Build {} ( {} ) of {}'s {} started.".format(
252 build
["buildid"], build
["url"],
253 build
["builder"]["name"],