]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - nixops/modules/buildbot/common/build_helpers.py
Add caldance buildbot and optimize a bit the drivations
[perso/Immae/Config/Nix.git] / nixops / modules / buildbot / common / build_helpers.py
1 from buildbot.plugins import util, steps, schedulers
2 from buildbot_buildslist import BuildsList
3
4 __all__ = [
5 "force_scheduler", "deploy_scheduler", "hook_scheduler",
6 "clean_branch", "package_and_upload", "SlackStatusPush"
7 ]
8
9 # Small helpers"
10 @util.renderer
11 def clean_branch(props):
12 if props.hasProperty("branch") and len(props["branch"]) > 0:
13 return props["branch"].replace("/", "_")
14 else:
15 return "HEAD"
16
17 def package_and_upload(package, package_dest, package_url):
18 return [
19 steps.ShellCommand(name="build package",
20 logEnviron=False, haltOnFailure=True, workdir="source",
21 command=["git", "archive", "HEAD", "-o", package]),
22
23 steps.FileUpload(name="upload package", workersrc=package,
24 workdir="source", masterdest=package_dest,
25 url=package_url, mode=0o644),
26
27 steps.ShellCommand(name="cleanup package", logEnviron=False,
28 haltOnFailure=True, workdir="source", alwaysRun=True,
29 command=["rm", "-f", package]),
30 ]
31
32 # Schedulers
33 def force_scheduler(name, builders):
34 return schedulers.ForceScheduler(name=name,
35 label="Force build", buttonName="Force build",
36 reason=util.StringParameter(name="reason", label="Reason", default="Force build"),
37 codebases=[
38 util.CodebaseParameter("",
39 branch=util.StringParameter(
40 name="branch", label="Git reference (tag, branch)", required=True),
41 revision=util.FixedParameter(name="revision", default=""),
42 repository=util.FixedParameter(name="repository", default=""),
43 project=util.FixedParameter(name="project", default=""),
44 ),
45 ],
46 username=util.FixedParameter(name="username", default="Web button"),
47 builderNames=builders)
48
49 def deploy_scheduler(name, builders):
50 return schedulers.ForceScheduler(name=name,
51 builderNames=builders,
52 label="Deploy built package", buttonName="Deploy",
53 username=util.FixedParameter(name="username", default="Web button"),
54 codebases=[
55 util.CodebaseParameter(codebase="",
56 branch=util.FixedParameter(name="branch", default=""),
57 revision=util.FixedParameter(name="revision", default=""),
58 repository=util.FixedParameter(name="repository", default=""),
59 project=util.FixedParameter(name="project", default=""))],
60 reason=util.FixedParameter(name="reason", default="Deploy"),
61 properties=[
62 util.ChoiceStringParameter(label="Environment",
63 name="environment", default="integration",
64 choices=["integration", "production"]),
65 BuildsList(label="Build to deploy", name="build"),
66 ]
67 )
68
69 def hook_scheduler(project, timer=10):
70 return schedulers.AnyBranchScheduler(
71 change_filter=util.ChangeFilter(category="hooks", project=project),
72 name=project, treeStableTimer=timer, builderNames=["{}_build".format(project)])
73
74 # Slack status push
75 from buildbot.reporters.http import HttpStatusPushBase
76 from twisted.internet import defer
77 from twisted.python import log
78 from buildbot.util import httpclientservice
79 from buildbot.reporters import utils
80 from buildbot.process import results
81
82 class SlackStatusPush(HttpStatusPushBase):
83 name = "SlackStatusPush"
84
85 @defer.inlineCallbacks
86 def reconfigService(self, serverUrl, **kwargs):
87 yield HttpStatusPushBase.reconfigService(self, **kwargs)
88 self._http = yield httpclientservice.HTTPClientService.getService(
89 self.master, serverUrl)
90
91 @defer.inlineCallbacks
92 def send(self, build):
93 yield utils.getDetailsForBuild(self.master, build, wantProperties=True)
94 response = yield self._http.post("", json=self.format(build))
95 if response.code != 200:
96 log.msg("%s: unable to upload status: %s" %
97 (response.code, response.content))
98
99 def format(self, build):
100 colors = [
101 "#36A64F", # success
102 "#F1E903", # warnings
103 "#DA0505", # failure
104 "#FFFFFF", # skipped
105 "#000000", # exception
106 "#FFFFFF", # retry
107 "#D02CA9", # cancelled
108 ]
109
110 if "environment" in build["properties"]:
111 msg = "{} environment".format(build["properties"]["environment"][0])
112 if "build" in build["properties"]:
113 msg = "of archive {} in ".format(build["properties"]["build"][0]) + msg
114 elif len(build["buildset"]["sourcestamps"][0]["branch"]) > 0:
115 msg = "revision {}".format(build["buildset"]["sourcestamps"][0]["branch"])
116 else:
117 msg = "build"
118
119 if build["complete"]:
120 timedelta = int((build["complete_at"] - build["started_at"]).total_seconds())
121 hours, rest = divmod(timedelta, 3600)
122 minutes, seconds = divmod(rest, 60)
123 if hours > 0:
124 duration = "{}h {}min {}s".format(hours, minutes, seconds)
125 elif minutes > 0:
126 duration = "{}min {}s".format(minutes, seconds)
127 else:
128 duration = "{}s".format(seconds)
129
130 text = "Build <{}|{}> of {}'s {} was {} in {}.".format(
131 build["url"], build["buildid"],
132 build["builder"]["name"],
133 msg,
134 results.Results[build["results"]],
135 duration,
136 )
137 fields = [
138 {
139 "title": "Build",
140 "value": "<{}|{}>".format(build["url"], build["buildid"]),
141 "short": True,
142 },
143 {
144 "title": "Project",
145 "value": build["builder"]["name"],
146 "short": True,
147 },
148 {
149 "title": "Build status",
150 "value": results.Results[build["results"]],
151 "short": True,
152 },
153 {
154 "title": "Build duration",
155 "value": duration,
156 "short": True,
157 },
158 ]
159 if "environment" in build["properties"]:
160 fields.append({
161 "title": "Environment",
162 "value": build["properties"]["environment"][0],
163 "short": True,
164 })
165 if "build" in build["properties"]:
166 fields.append({
167 "title": "Archive",
168 "value": build["properties"]["build"][0],
169 "short": True,
170 })
171 attachments = [{
172 "fallback": "",
173 "color": colors[build["results"]],
174 "fields": fields
175 }]
176 else:
177 text = "Build <{}|{}> of {}'s {} started.".format(
178 build["url"], build["buildid"],
179 build["builder"]["name"],
180 msg,
181 )
182 attachments = []
183
184 return {
185 "username": "Buildbot",
186 "icon_url": "http://docs.buildbot.net/current/_static/icon.png",
187 "text": text,
188 "attachments": attachments,
189 }
190
191
192