Skip to content
This repository has been archived by the owner on Jul 1, 2020. It is now read-only.

Commit

Permalink
notify_slack: initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
trehn committed May 3, 2015
1 parent 7e2a192 commit 0e850b6
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 0 deletions.
5 changes: 5 additions & 0 deletions index.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
"desc": "Automatically send notifications to HipChat rooms with bw apply",
"version": 8
},
"notify_slack": {
"checksum": "269f1321daac1919a9ea8890e62714f5dfd7c33a",
"desc": "Automatically send notifications to Slack rooms with bw apply",
"version": 1
},
"pwget": {
"checksum": "03983b012a5c3e68cb844b1a7d1bb422cdf789b0",
"desc": "Derive passwords in your repo from a shared secret",
Expand Down
1 change: 1 addition & 0 deletions notify_slack/AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Torsten Rehn <[email protected]>
6 changes: 6 additions & 0 deletions notify_slack/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Copyright (c) 2015, Torsten Rehn <[email protected]>


Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
152 changes: 152 additions & 0 deletions notify_slack/hooks/notify_slack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
from ConfigParser import SafeConfigParser
from json import dumps
from os.path import exists, join

try:
from requests import post
from requests.exceptions import ConnectionError
REQUESTS = True
except ImportError:
REQUESTS = False

from bundlewrap.utils import LOG


def _check_allowed_groups(config, nodes):
allowed_nodes = set([])

for node in nodes:
for allowed_group in config.get("apply_notifications", "allow_groups").split(","):
if not allowed_group.strip() or node.in_group(allowed_group.strip()):
allowed_nodes.add(node)

for node in nodes:
for denied_group in config.get("apply_notifications", "deny_groups").split(","):
if node.in_group(denied_group) and node in allowed_nodes:
allowed_nodes.remove(node)

return bool(allowed_nodes)


def _create_config(path):
LOG.debug("writing initial config for Slack notifications to .slack.cfg")
config = SafeConfigParser()
config.add_section("configuration")
config.set("configuration", "enabled", "unconfigured")
config.set("configuration", "username", "your-slack-username")
config.add_section("connection")
config.set("connection", "url",
"<insert URL from https://my.slack.com/services/new/incoming-webhook>")
config.add_section("apply_notifications")
config.set("apply_notifications", "enabled", "yes")
config.set("apply_notifications", "allow_groups", "all")
config.set("apply_notifications", "deny_groups", "local")
with open(path, 'wb') as f:
config.write(f)


def _get_config(repo_path):
config_path = join(repo_path, ".slack.cfg")
if not exists(config_path):
_create_config(config_path)
config = SafeConfigParser()
config.read(config_path)
if config.get("configuration", "enabled") == "unconfigured":
LOG.error("Slack notifications not configured. Please edit .slack.cfg "
"(it has already been created) and set enabled to 'yes' "
"(or 'no' to silence this message and disable Slack notifications).")
return None
elif config.get("configuration", "enabled").lower() not in ("yes", "true", "1"):
LOG.debug("Slack notifications not enabled in .slack.cfg, skipping...")
return None
elif not REQUESTS:
LOG.error("Slack notifications need the requests library. "
"You can usually install it with `pip install requests`.")
return None
return config


def _notify(url, message=None, title=None, fallback=None, user=None, target=None, color="#000000"):
payload = {
"icon_url": "http://bundlewrap.org/img/icon.png",
"username": "bundlewrap",
}
if fallback:
payload["attachments"] = [{
"color": color,
"fallback": fallback,
}]
if message:
payload["attachments"][0]["text"] = message
if title:
payload["attachments"][0]["title"] = title
if target and user:
payload["attachments"][0]["fields"] = [
{
"short": True,
"title": "User",
"value": user,
},
{
"short": True,
"title": "Target",
"value": target,
},
]
else:
payload["text"] = message

try:
post(
url,
headers={
'content-type': 'application/json',
},
data=dumps(payload),
)
except ConnectionError as e:
LOG.error("Failed to submit Slack notification: {}".format(e))


def apply_start(repo, target, nodes, interactive=False, **kwargs):
config = _get_config(repo.path)
if config is None or \
not config.has_section("apply_notifications") or \
not config.getboolean("apply_notifications", "enabled") or \
not _check_allowed_groups(config, nodes):
return
LOG.debug("posting apply start notification to Slack")
_notify(
config.get("connection", "url"),
fallback="Starting bw apply to {target} as {user}".format(
target=target,
user=config.get("configuration", "username"),
),
target=target,
title=(
"Starting {interactive}interactive bw apply..."
).format(interactive="non-" if not interactive else ""),
user=config.get("configuration", "username"),
)


def apply_end(repo, target, nodes, duration=None, **kwargs):
config = _get_config(repo.path)
if config is None or \
not config.has_section("apply_notifications") or \
not config.getboolean("apply_notifications", "enabled") or \
not _check_allowed_groups(config, nodes):
return
LOG.debug("posting apply end notification to Slack")
_notify(
config.get("connection", "url"),
color="good",
fallback="Finished bw apply to {target} as {user} after {duration}s.".format(
duration=duration.total_seconds(),
target=target,
user=config.get("configuration", "username"),
),
target=target,
title="Finished bw apply after {}s.".format(duration.total_seconds()),
user=config.get("configuration", "username"),
)
8 changes: 8 additions & 0 deletions notify_slack/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"desc": "Automatically send notifications to Slack rooms with bw apply",
"help": "This plugin requires some additional dependencies:\n$ pip install requests\nRunning bw apply will trigger plugin configuration.\nPlease add .slack.cfg to your gitignore or equivalent.",
"provides": [
"hooks/notify_slack.py"
],
"version": 1
}

0 comments on commit 0e850b6

Please sign in to comment.