Skip to content
Permalink
Browse files

Add a Slack posting resource (#1280)

This PR adds a resource that enables posting messages to Slack channels via the `chat.postMessage()` API.
  • Loading branch information...
natekupp committed Apr 24, 2019
1 parent 959c3c4 commit a4b2f66ea06381edfb11d9f36793930599af8085
@@ -26,3 +26,7 @@
# R0205 py3-only inherit from object warning
# C0330 bad-continuation (we let black take care of this)
disable=C0111,C0330,C0103,duplicate-code,R0201,R0903,R0913,W0511,W1201,W1202,R1705,R0902,R1710,C0102,C0302,R0911,R0901,R0205

# See: https://github.com/getsentry/responses/issues/74
[TYPECHECK]
ignored-classes= responses
@@ -0,0 +1,6 @@
from .version import __version__

from .resources import slack_resource


__all__ = ['slack_resource']
@@ -0,0 +1,62 @@
from slackclient import SlackClient

from dagster import resource, seven, Dict, Field, String


class SlackConnection:
def __init__(self, token):
self.token = token
self.sc = SlackClient(self.token)

class _Chat:
@classmethod
def post_message(
cls,
channel='#noise',
username='dagsterbot',
text='https://www.youtube.com/watch?v=dQw4w9WgXcQ',
# pylint: disable=line-too-long
icon_url='https://user-images.githubusercontent.com/609349/56463858-9d2eab80-6391-11e9-8288-e606fdf674b5.png',
attachments=None,
):
'''slack_resource.chat.post_message() : chat.postMessage
See https://api.slack.com/methods/chat.postMessage
'''
api_params = {
'channel': channel,
'username': username,
'text': text,
'icon_url': icon_url,
'attachments': seven.json.dumps(attachments),
}
return self.sc.api_call('chat.postMessage', **api_params)

self.chat = _Chat

def api_call(self, method, timeout=None, **kwargs):
return self.sc.api_call(method, timeout, **kwargs)


@resource(
config_field=Field(
Dict(
{
'token': Field(
String,
description='''To configure access to the Slack API, you'll need an access
token provisioned with access to your Slack workspace.
Tokens are typically either user tokens or bot tokens. For programmatic posting
to Slack from this resource, you probably want to provision and use a bot token.
More in the Slack API documentation here: https://api.slack.com/docs/token-types
''',
)
}
)
),
description='This resource is for connecting to Slack',
)
def slack_resource(context):
return SlackConnection(context.resource_config.get('token'))
@@ -0,0 +1 @@
__version__ = '0.4.0'
@@ -0,0 +1,47 @@
import responses

from dagster import execute_pipeline, solid, PipelineContextDefinition, PipelineDefinition

from dagster_slack import slack_resource


@responses.activate
def test_slack_resource():
@solid
def slack_solid(context):
assert context.resources.slack
with responses.RequestsMock() as rsps:
rsps.add(
rsps.POST,
'https://slack.com/api/chat.postMessage',
status=200,
json={
'ok': True,
'channel': 'SOME_CHANNEL',
'ts': '1555993892.000300',
'headers': {'Content-Type': 'application/json; charset=utf-8'},
},
)
context.resources.slack.chat.post_message()

pipeline = PipelineDefinition(
name='test_slack_resource',
solids=[slack_solid],
context_definitions={
'default': PipelineContextDefinition(resources={'slack': slack_resource})
},
)

result = execute_pipeline(
pipeline,
{
'context': {
'default': {
'resources': {
'slack': {'config': {'token': 'xoxp-1234123412341234-12341234-1234'}}
}
}
}
},
)
assert result.success
@@ -0,0 +1,5 @@
from dagster_slack.version import __version__


def test_version():
assert __version__
@@ -0,0 +1 @@
responses==0.10.6
No changes.
@@ -0,0 +1,58 @@
import argparse
import sys

from setuptools import find_packages, setup

# pylint: disable=E0401, W0611
if sys.version_info[0] < 3:
import __builtin__ as builtins
else:
import builtins


def get_version(name):
version = {}
with open("dagster_slack/version.py") as fp:
exec(fp.read(), version) # pylint: disable=W0122

if name == 'dagster-slack':
return version['__version__']
elif name == 'dagster-slack-nightly':
return version['__nightly__']
else:
raise Exception('Shouldn\'t be here: bad package name {name}'.format(name=name))


parser = argparse.ArgumentParser()
parser.add_argument('--nightly', action='store_true')


def _do_setup(name='dagster-slack'):
setup(
name='dagster_slack',
version=get_version(name),
author='Elementl',
license='Apache-2.0',
description='A Slack client resource for posting to Slack',
url='https://github.com/dagster-io/dagster/tree/master/python_modules/libraries/dagster-slack',
classifiers=[
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent',
],
packages=find_packages(exclude=['test']),
install_requires=['dagster'],
tests_require=['responses==0.10.*'],
zip_safe=False,
)


if __name__ == '__main__':
parsed, unparsed = parser.parse_known_args()
sys.argv = [sys.argv[0]] + unparsed
if parsed.nightly:
_do_setup('dagster-slack-nightly')
else:
_do_setup('dagster-slack')
@@ -0,0 +1,15 @@
[tox]
envlist = py37,py36,py35,py27

[testenv]
passenv = CIRCLECI CIRCLE_* CI_PULL_REQUEST COVERALLS_REPO_TOKEN
deps =
-e ../../dagster
-r ../../dagster/dev-requirements.txt
-e .
commands =
coverage erase
pytest -vv --junitxml=test_results.xml --cov=dagster_slack --cov-append --cov-report=
coverage report --omit='.tox/*,**/test_*.py' --skip-covered
coverage html --omit='.tox/*,**/test_*.py'
coverage xml --omit='.tox/*,**/test_*.py'

0 comments on commit a4b2f66

Please sign in to comment.
You can’t perform that action at this time.