aboutsummaryrefslogtreecommitdiff
path: root/nixops
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2019-03-27 13:13:00 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2019-03-27 13:13:19 +0100
commit256d607c2db3e56a2f481a2097ffa3ccd109d141 (patch)
tree669aa366833b7506bf66b4b7eb3319bdb547ebea /nixops
parent85817848f29f1e2c3680da216a8dfc54a2ad3932 (diff)
downloadNix-256d607c2db3e56a2f481a2097ffa3ccd109d141.tar.gz
Nix-256d607c2db3e56a2f481a2097ffa3ccd109d141.tar.zst
Nix-256d607c2db3e56a2f481a2097ffa3ccd109d141.zip
Add xmpp push notifications to buildbot and gitolite
Diffstat (limited to 'nixops')
-rw-r--r--nixops/modules/buildbot/apprise.json15
-rw-r--r--nixops/modules/buildbot/common/build_helpers.py69
-rw-r--r--nixops/modules/buildbot/default.nix28
-rw-r--r--nixops/modules/buildbot/projects/caldance/__init__.py6
-rw-r--r--nixops/modules/buildbot/projects/test/__init__.py6
-rw-r--r--nixops/modules/gitolite/default.nix1
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
75from buildbot.reporters.http import HttpStatusPushBase 76from buildbot.reporters.http import HttpStatusPushBase
76from twisted.internet import defer 77from twisted.internet import defer
77from twisted.python import log 78from twisted.python import log
78from buildbot.util import httpclientservice 79from buildbot.util import httpclientservice
79from buildbot.reporters import utils 80from buildbot.reporters import utils
80from buildbot.process import results 81from buildbot.process import results
82from twisted.words.protocols.jabber.jid import JID
83from wokkel import client, xmppim
84
81 85
82class SlackStatusPush(HttpStatusPushBase): 86class 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
195class 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
93def factory(project, ignore_fails=False): 99def 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
88def factory(): 94def 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 [