diff options
-rw-r--r-- | nixops/modules/buildbot/apprise.json | 15 | ||||
-rw-r--r-- | nixops/modules/buildbot/common/build_helpers.py | 69 | ||||
-rw-r--r-- | nixops/modules/buildbot/default.nix | 28 | ||||
-rw-r--r-- | nixops/modules/buildbot/projects/caldance/__init__.py | 6 | ||||
-rw-r--r-- | nixops/modules/buildbot/projects/test/__init__.py | 6 | ||||
-rw-r--r-- | nixops/modules/gitolite/default.nix | 1 |
6 files changed, 123 insertions, 2 deletions
diff --git a/nixops/modules/buildbot/apprise.json b/nixops/modules/buildbot/apprise.json new file mode 100644 index 0000000..b408ea4 --- /dev/null +++ b/nixops/modules/buildbot/apprise.json | |||
@@ -0,0 +1,15 @@ | |||
1 | { | ||
2 | "tag": "c9b957c-master", | ||
3 | "meta": { | ||
4 | "name": "apprise", | ||
5 | "url": "https://github.com/caronc/apprise", | ||
6 | "branch": "master" | ||
7 | }, | ||
8 | "github": { | ||
9 | "owner": "caronc", | ||
10 | "repo": "apprise", | ||
11 | "rev": "c9b957c4341e7d43e5be6463bd317a7401d083d9", | ||
12 | "sha256": "01zz4mh3xvplrm5xalzrcncnh0jq5y51pmdxkr4hdd6dz9wx0mbg", | ||
13 | "fetchSubmodules": true | ||
14 | } | ||
15 | } | ||
diff --git a/nixops/modules/buildbot/common/build_helpers.py b/nixops/modules/buildbot/common/build_helpers.py index f51de54..63733e7 100644 --- a/nixops/modules/buildbot/common/build_helpers.py +++ b/nixops/modules/buildbot/common/build_helpers.py | |||
@@ -3,7 +3,8 @@ from buildbot_buildslist import BuildsList | |||
3 | 3 | ||
4 | __all__ = [ | 4 | __all__ = [ |
5 | "force_scheduler", "deploy_scheduler", "hook_scheduler", | 5 | "force_scheduler", "deploy_scheduler", "hook_scheduler", |
6 | "clean_branch", "package_and_upload", "SlackStatusPush" | 6 | "clean_branch", "package_and_upload", "SlackStatusPush", |
7 | "XMPPStatusPush" | ||
7 | ] | 8 | ] |
8 | 9 | ||
9 | # Small helpers" | 10 | # Small helpers" |
@@ -71,13 +72,16 @@ def hook_scheduler(project, timer=10): | |||
71 | change_filter=util.ChangeFilter(category="hooks", project=project), | 72 | change_filter=util.ChangeFilter(category="hooks", project=project), |
72 | name=project, treeStableTimer=timer, builderNames=["{}_build".format(project)]) | 73 | name=project, treeStableTimer=timer, builderNames=["{}_build".format(project)]) |
73 | 74 | ||
74 | # Slack status push | 75 | # Slack/XMPP status push |
75 | from buildbot.reporters.http import HttpStatusPushBase | 76 | from buildbot.reporters.http import HttpStatusPushBase |
76 | from twisted.internet import defer | 77 | from twisted.internet import defer |
77 | from twisted.python import log | 78 | from twisted.python import log |
78 | from buildbot.util import httpclientservice | 79 | from buildbot.util import httpclientservice |
79 | from buildbot.reporters import utils | 80 | from buildbot.reporters import utils |
80 | from buildbot.process import results | 81 | from buildbot.process import results |
82 | from twisted.words.protocols.jabber.jid import JID | ||
83 | from wokkel import client, xmppim | ||
84 | |||
81 | 85 | ||
82 | class SlackStatusPush(HttpStatusPushBase): | 86 | class SlackStatusPush(HttpStatusPushBase): |
83 | name = "SlackStatusPush" | 87 | name = "SlackStatusPush" |
@@ -188,5 +192,66 @@ class SlackStatusPush(HttpStatusPushBase): | |||
188 | "attachments": attachments, | 192 | "attachments": attachments, |
189 | } | 193 | } |
190 | 194 | ||
195 | class XMPPStatusPush(HttpStatusPushBase): | ||
196 | name = "XMPPStatusPush" | ||
197 | |||
198 | @defer.inlineCallbacks | ||
199 | def reconfigService(self, password, recipients, **kwargs): | ||
200 | yield HttpStatusPushBase.reconfigService(self, **kwargs) | ||
201 | self.password = password | ||
202 | self.recipients = recipients | ||
203 | |||
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()) | ||
215 | # To allow chaining | ||
216 | return stream | ||
217 | for recipient in self.recipients: | ||
218 | d.addCallback(send_message) | ||
219 | d.addCallback(lambda _: factory.streamManager.xmlstream.sendFooter()) | ||
220 | d.addErrback(log.err) | ||
221 | |||
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"]) | ||
229 | else: | ||
230 | msg = "build" | ||
231 | |||
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) | ||
236 | if hours > 0: | ||
237 | duration = "{}h {}min {}s".format(hours, minutes, seconds) | ||
238 | elif minutes > 0: | ||
239 | duration = "{}min {}s".format(minutes, seconds) | ||
240 | else: | ||
241 | duration = "{}s".format(seconds) | ||
191 | 242 | ||
243 | text = "Build {} ( {} ) of {}'s {} was {} in {}.".format( | ||
244 | build["buildid"], build["url"], | ||
245 | build["builder"]["name"], | ||
246 | msg, | ||
247 | results.Results[build["results"]], | ||
248 | duration, | ||
249 | ) | ||
250 | else: | ||
251 | text = "Build {} ( {} ) of {}'s {} started.".format( | ||
252 | build["buildid"], build["url"], | ||
253 | build["builder"]["name"], | ||
254 | msg, | ||
255 | ) | ||
192 | 256 | ||
257 | return text | ||
diff --git a/nixops/modules/buildbot/default.nix b/nixops/modules/buildbot/default.nix index 21b784b..c670b7d 100644 --- a/nixops/modules/buildbot/default.nix +++ b/nixops/modules/buildbot/default.nix | |||
@@ -57,6 +57,33 @@ in | |||
57 | }; | 57 | }; |
58 | 58 | ||
59 | config = lib.mkIf config.services.buildbot.enable { | 59 | config = lib.mkIf config.services.buildbot.enable { |
60 | nixpkgs.overlays = [ (self: super: rec { | ||
61 | python3 = super.python3.override { | ||
62 | packageOverrides = python-self: python-super: { | ||
63 | wokkel = python-self.buildPythonPackage rec { | ||
64 | pname = "wokkel"; | ||
65 | version = "18.0.0"; | ||
66 | src = python-self.fetchPypi { | ||
67 | inherit pname version; | ||
68 | sha256 = "1spq44gg8gsviqx1dvlmjpgfc0wk0jpyx4ap01y2pad1ai9cw016"; | ||
69 | }; | ||
70 | propagatedBuildInputs = with python-self; [ twisted.extras.tls twisted incremental dateutil ]; | ||
71 | doChecks = false; | ||
72 | }; | ||
73 | apprise = python-self.buildPythonPackage rec { | ||
74 | pname = "apprise"; | ||
75 | version = "0.7.4"; | ||
76 | src = (mylibs.fetchedGithub ./apprise.json).src; | ||
77 | propagatedBuildInputs = with python-self; [ decorator | ||
78 | requests requests_oauthlib oauthlib urllib3 six click | ||
79 | markdown pyyaml sleekxmpp | ||
80 | ]; | ||
81 | doChecks = false; | ||
82 | }; | ||
83 | }; | ||
84 | }; | ||
85 | }) ]; | ||
86 | |||
60 | ids.uids.buildbot = myconfig.env.buildbot.user.uid; | 87 | ids.uids.buildbot = myconfig.env.buildbot.user.uid; |
61 | ids.gids.buildbot = myconfig.env.buildbot.user.gid; | 88 | ids.gids.buildbot = myconfig.env.buildbot.user.gid; |
62 | 89 | ||
@@ -171,6 +198,7 @@ in | |||
171 | }); | 198 | }); |
172 | HOME = "${varDir}/${project.name}"; | 199 | HOME = "${varDir}/${project.name}"; |
173 | PYTHONPATH = "${buildbot.pythonModule.withPackages (self: project.pythonPackages self pkgs ++ [ | 200 | PYTHONPATH = "${buildbot.pythonModule.withPackages (self: project.pythonPackages self pkgs ++ [ |
201 | pkgs.python3Packages.wokkel | ||
174 | pkgs.python3Packages.treq pkgs.python3Packages.ldap3 buildbot | 202 | pkgs.python3Packages.treq pkgs.python3Packages.ldap3 buildbot |
175 | pkgs.python3Packages.buildbot-worker | 203 | pkgs.python3Packages.buildbot-worker |
176 | buildbot_common buildbot_config | 204 | buildbot_common buildbot_config |
diff --git a/nixops/modules/buildbot/projects/caldance/__init__.py b/nixops/modules/buildbot/projects/caldance/__init__.py index 1069c35..2c0bad5 100644 --- a/nixops/modules/buildbot/projects/caldance/__init__.py +++ b/nixops/modules/buildbot/projects/caldance/__init__.py | |||
@@ -19,6 +19,7 @@ class E(): | |||
19 | LDAP_HOST = "ldap.immae.eu" | 19 | LDAP_HOST = "ldap.immae.eu" |
20 | LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" | 20 | LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" |
21 | LDAP_ROLES_BASE = "ou=roles,ou=hosts,dc=immae,dc=eu" | 21 | LDAP_ROLES_BASE = "ou=roles,ou=hosts,dc=immae,dc=eu" |
22 | XMPP_RECIPIENTS = os.environ["BUILDBOT_XMPP_RECIPIENTS"].split(" ") | ||
22 | 23 | ||
23 | PUPPET_HOST = { | 24 | PUPPET_HOST = { |
24 | "integration": "root@caldance.immae.eu", | 25 | "integration": "root@caldance.immae.eu", |
@@ -89,6 +90,11 @@ def configure(c): | |||
89 | name="slack_status_caldance", | 90 | name="slack_status_caldance", |
90 | builders=["Caldance_build", "Caldance_deploy"], | 91 | builders=["Caldance_build", "Caldance_deploy"], |
91 | serverUrl=open(E.SECRETS_FILE + "/slack_webhook", "r").read().rstrip())) | 92 | serverUrl=open(E.SECRETS_FILE + "/slack_webhook", "r").read().rstrip())) |
93 | c['services'].append(XMPPStatusPush( | ||
94 | name="xmpp_status_caldance", | ||
95 | builders=["Caldance_build", "Caldance_deploy"], | ||
96 | recipients=E.XMPP_RECIPIENTS, | ||
97 | password=open(E.SECRETS_FILE + "/notify_xmpp_password", "r").read().rstrip())) | ||
92 | 98 | ||
93 | def factory(project, ignore_fails=False): | 99 | def factory(project, ignore_fails=False): |
94 | release_file = "{1}/{0}_%(kw:clean_branch)s.tar.gz" | 100 | release_file = "{1}/{0}_%(kw:clean_branch)s.tar.gz" |
diff --git a/nixops/modules/buildbot/projects/test/__init__.py b/nixops/modules/buildbot/projects/test/__init__.py index 0644920..e6b8d51 100644 --- a/nixops/modules/buildbot/projects/test/__init__.py +++ b/nixops/modules/buildbot/projects/test/__init__.py | |||
@@ -19,6 +19,7 @@ class E(): | |||
19 | LDAP_HOST = "ldap.immae.eu" | 19 | LDAP_HOST = "ldap.immae.eu" |
20 | LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" | 20 | LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" |
21 | LDAP_ROLES_BASE = "ou=roles,ou=hosts,dc=immae,dc=eu" | 21 | LDAP_ROLES_BASE = "ou=roles,ou=hosts,dc=immae,dc=eu" |
22 | XMPP_RECIPIENTS = os.environ["BUILDBOT_XMPP_RECIPIENTS"].split(" ") | ||
22 | 23 | ||
23 | # master.cfg | 24 | # master.cfg |
24 | SECRETS_FILE = os.getcwd() + "/secrets" | 25 | SECRETS_FILE = os.getcwd() + "/secrets" |
@@ -84,6 +85,11 @@ def configure(c): | |||
84 | name="slack_status_test_project", | 85 | name="slack_status_test_project", |
85 | builders=["TestProject_build", "TestProject_deploy"], | 86 | builders=["TestProject_build", "TestProject_deploy"], |
86 | serverUrl=open(E.SECRETS_FILE + "/slack_webhook", "r").read().rstrip())) | 87 | serverUrl=open(E.SECRETS_FILE + "/slack_webhook", "r").read().rstrip())) |
88 | c['services'].append(XMPPStatusPush( | ||
89 | name="xmpp_status_test_project", | ||
90 | builders=["TestProject_build", "TestProject_deploy"], | ||
91 | recipients=E.XMPP_RECIPIENTS, | ||
92 | password=open(E.SECRETS_FILE + "/notify_xmpp_password", "r").read().rstrip())) | ||
87 | 93 | ||
88 | def factory(): | 94 | def factory(): |
89 | package = util.Interpolate("test_%(kw:clean_branch)s.tar.gz", clean_branch=clean_branch) | 95 | package = util.Interpolate("test_%(kw:clean_branch)s.tar.gz", clean_branch=clean_branch) |
diff --git a/nixops/modules/gitolite/default.nix b/nixops/modules/gitolite/default.nix index 844bd0f..8703fbb 100644 --- a/nixops/modules/gitolite/default.nix +++ b/nixops/modules/gitolite/default.nix | |||
@@ -48,6 +48,7 @@ in { | |||
48 | python-packages = python-packages: with python-packages; [ | 48 | python-packages = python-packages: with python-packages; [ |
49 | simplejson | 49 | simplejson |
50 | urllib3 | 50 | urllib3 |
51 | sleekxmpp | ||
51 | ]; | 52 | ]; |
52 | in | 53 | in |
53 | [ | 54 | [ |