Coder Social home page Coder Social logo

mattermost-github-integration's Introduction

Github integration for Mattermost

Inspired by mattermost-integration-gitlab this program creates a server using flask that listens for incoming GitHub event webhooks. These are then processed, formatted, and eventually forwarded to Mattermost where they are displayed inside a specified channel.

Requirements

System requirements

  • Python3 or Python2

Application requirements

  • Flask (install with pip install flask)
  • requests (install with pip install requests)
  • (optional) PIL (install with pip install pillow) - needed to hide big Github avatars

All requirements can also be installed using the command

pip install -r requirements.txt

Installation and usage

  1. Clone the repository
  2. Within the mattermostgithub directory, copy config.template to config.py and edit it with your details. For example:
USERNAME = "Github"
ICON_URL = "yourdomain.org/github.png"
MATTERMOST_WEBHOOK_URLS = {
    'default' : ("yourdomain.org/hooks/hookid", "off-topic"),
    'teamname/repositoryname' : ("yourdomain.org/hooks/hookid2", "repository-channel-id"),
    'teamname' : ("yourdomain.org/hooks/hookid3", "town-square"),
    'teamname/unimportantrepo' : None,
}
GITHUB_IGNORE_ACTIONS = {
    "issues": ["labeled", "assigned"],
}
SECRET = 'secretkey'
SHOW_AVATARS = True
SERVER = {
    'hook': "/"
,   'address': "0.0.0.0"
,   'port': 5000
}

Test the server with python server.py. For deployment, please consider using WSGI (more details here). For example to run using Gunicorn, execute:

gunicorn -b 0.0.0.0:5000 mattermostgithub:app

Alternatively, a Dockerfile is provided to run using Docker (see below).

Webhooks

GitHub messages can be delegated to different Mattermost hooks. The order is as follows:

  • First try to find a hook for the repositories full name.
  • If that fails, try to find a hook for the organisation name.
  • Otherwise use the default hook.

Repositories can be blacklisted by setting them to None instead of (url, channel).

Ignore actions

Specific Github events can be ignored by adding GITHUB_IGNORE_ACTIONS to config.py. In the example above labeled and assigned events for issues are ignored, while opened, closed, etc. events will continue to show up on Mattermost.

Server settings

The server is listening by default on address 0.0.0.0, port 5000, and using / as base route. Make sure to point your Github webhooks to http://yourdomain.org:5000/.

If you have a proxy/load-balancer in front of your machine, and do not want to expose port 5000 to the outside, change the SERVER['hook'] value and redirect it to this service. For example, if SERVER['hook'] is /hooks/github, your Github webhooks would be http://yourdomain.org/hooks/github.

Secret

The secret key that can be set when setting up the Github webhook. If you don't want to use a secret, set the field to None.

Deploying with Docker

To deploy with Docker, make sure you have Docker installed and run:

docker build --rm=true -t mm-github .
docker run --rm -v "$(pwd)":/home/app -w /home/app -p 5000:5000 -ti mm-github

If you want to run in background mode, change the option --rm for -d.

Supported Events

Not all Github events are forwarded to Mattermost. Currently supported events are:

  • Ping events (send when first adding the Github webhook)
  • Commit pushes and comments
  • Issues (open, close, comment)
  • Pull Requests (create, merge, remove, comment)
  • Create/Delete repositories
  • Create/Delete branches and tags

All other events will report back to GitHub with 400 Not Implemented.

Known issues

  • Channel names need to use the spelling that is used in their URL (the channel ID), e.g. instead of Town Square it needs to be town-square.

  • If you set a custom username (as shown in the default config), make sure you also set Enable webhooks and slash commands to override usernames under Custom Integrations in the System Console to True. Otherwise the bots username will be that of the person that setup the Mattermost integration.

mattermost-github-integration's People

Contributors

cormier avatar dependabot[bot] avatar elimisteve avatar jaheba avatar kostecky avatar lfbayer avatar ltratt avatar psidium avatar ptersilie avatar remimarenco avatar shulhan avatar tomryanx avatar valvin1 avatar vext01 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mattermost-github-integration's Issues

HTTPS support (without ssl verification)

Changed server.py and added:

  1. import os under other imports

  2. ASSETS_DIR = os.path.dirname(os.path.abspath(file)) after SECRET

  3. context = ('/path/to/cert.pem', 'path/to/privkey.pem') before app.run(...

  4. ssl_context=context after debug=False inside app.run(..)

Now Github hooks starting with HTTPS://... work as well. SSL verification must be turned off however.

What to do in mattermost

Ok, so I checked the code out and running it on my server. So now what do I do in Mattermost? Do I create an incoming or outgoing webhook?

The initial ping from GHE will fail with organizational hooks

The cause is rather simply that server.py:41 tries to access a repository entry. The fix can be equally simple.

diff --git a/mattermostgithub/server.py b/mattermostgithub/server.py
index ad26bec..9daee73 100644
--- a/mattermostgithub/server.py
+++ b/mattermostgithub/server.py
@@ -38,7 +38,12 @@ def root():
 
     msg = ""
     if event == "ping":
-        msg = "ping from %s" % data['repository']['full_name']
+        if 'repository' in data:
+            msg = "ping from repository %s" % data['repository']['full_name']
+        elif 'organization' in data:
+            msg = "ping from organization %s by user %s" % (data['organization']['login'], data['sender']['login'])
+        else:
+            msg = "ominous ping…"
     elif event == "pull_request":
         if data['action'] == "opened":
             msg = PullRequest(data).opened()

But now you have me wondering: are organizational hooks even expected to work?

keep getting code 400 with json and with out json data from github.

92.30.252.41 - - [19/Apr/2016 01:05:25] code 400, message Bad request syntax ('\x16\x03\x01\x00\xfa\x01\x00\x00\xf6\x03\x03W\x15\xbc\x94M;N\x9e\xe6\xc8\xdf\xb6q\xf4\x0e#\x1d\xe2H\x85\x1d4')
192.30.252.41 - - [19/Apr/2016 01:05:25] "��W��M;N���߶q�#�H�4" 400 -
192.30.252.40 - - [19/Apr/2016 01:06:27] code 400, message Bad HTTP/0.9 request type ("\x16\x03\x01\x00\xfa\x01\x00\x00\xf6\x03\x03W\x15\xbc\xd3\xe1x\xf3^Q\xc9\x90\xcd\xf0\x0f\x0e\xa5DU'\xb4\xa0X\x8d\xac\xd0\xcdA5\x84aQ>\x00\x00D\xc0+\xc0/\xc0,\xc00\x00\x9e\x00\xa2\x00\x9f\x00\xa3\xc0#\xc0'\xc0")
192.30.252.40 - - [19/Apr/2016 01:06:27] "��W���x�^Qɐ���DU'��X����A5�aQ>D�+�/�,�0�����#�'� ��$�(�" 400 -
192.30.252.41 - - [19/Apr/2016 01:07:20] code 400, message Bad request version ('\xc0\x13\xc0$\xc0(\xc0')
192.30.252.41 - - [19/Apr/2016 01:07:20] "��W �L�=n����I��xLҠ^_f�ȉND�+�/�,�0�����#�'� ��$�(�" 400 -

missing support for some pull request review comments

If you comment inside the pull request, on a line of code or somesuch, it comes through as the event type "pull_request_review_comment" which is supported.

But if you just put text in the box with approve, comment, and request changes, it comes through as "pull_request_review" which is not supported -- these messages are lost.

AttributeError: 'module' object has no attribute 'SERVER

root@mmm:/mattermost-github-integration# python server.py
Traceback (most recent call last):
  File "server.py", line 7, in <module>
    host=config.SERVER['address'] or "0.0.0.0",
AttributeError: 'module' object has no attribute 'SERVER'
root@mmm:/mattermost-github-integration# 

Using method 1

README is not clear full

How to install and run properly this app?

root@mmm:/mattermost-github-integration# cat mattermostgithub/config.py
USERNAME = "Github"
ICON_URL = ""

# Repository settings
MATTERMOST_WEBHOOK_URLS = {
    'default' : ("https://my_domain.com/hooks/eimqnptb678gfrwb9w56szeaya", "room-bots"),
}

# Ignore specified event actions
GITHUB_IGNORE_ACTIONS = {
    "pull_request": ["synchronize"]
}

# Ignore events from specified users
IGNORE_USERS = {
    "someuser": ["push"],
    "anotheruser": ["push", "create"]
}

# Redirect events to different channels
REDIRECT_EVENTS = {
    "push": "commits"
}
SECRET = ""
SHOW_AVATARS = True
SERVER = {
    'hook': "/",
    'address': "0.0.0.0",
    'port': 5000,
}

[Bug] User avatar resizing

Hello,

Github has a bug on their own image generation, they do not resize svg files.
That's why using

avatar = self.data['sender']['avatar_url'] + "&s=18"

won't work for them.
See: https://avatars2.githubusercontent.com/u/4415695?v=3&s=18
avatar with 18 px width

So be aware by using the avatar, when your team has a user with default avatar or an uploaded svg.
But because Mattermost is not able to allow resizing as well (for now - I hope this will follow), I do not have a solution for this.

Feature request: ensure repo name is always in notification

Sometimes when a comment is left against an individual commit (maybe without a PR being raised?), the repo that commit came from is not shown in the notification, e.g.:

11:19 Github:BOT<user> commented on 341591b:

<comment message>

Ideally it would be good to have the repo name in here, so the owner knows to respond to the comment.

Please don't use app.run() in the Dockerfile

People might use it for production, and app.run() (same for flask run btw) is not suitable for production; better use something like gunicorn or uwsgi (both can directly serve http requests).

How to handle 400 bad request in mattermost while using node red

#In node red,I am calling an api in one function by http request node.That api generated response
"400 (bad request) error".I am passing that response as attachment format into matter-most.
Due to the 400 response I am getting output in mattermost as JSON error.

Please help me how to over come this and how handle 400 error in mattermost in NODE-RED

Not implemented return response from Github testing

Hi!

Thanks for this project, it is awesome to be able to get the github notifications :).

Although, I encounter a few issues while trying to set it up.

My config.py is like this:

USERNAME = "rmarenco"
ICON_URL = "octodex.github.com/images/octobiwan.jpg"
MATTERMOST_WEBHOOK_URLS = {
    'default' : ("mattermost.remionramp.com/hooks/hook1", "off-topic"),
    'remimarenco/gonramp' : ("mattermost.remionramp.com/hooks/hook2", "Github"),
    'remimarenco' : ("mattermost.remionramp.com/hooks/hook3", "town-square")
}
SECRET = "mysecret"
SHOW_AVATARS = True

But I am not sure about what to insert into USERNAME...

My webhook on github side is like this:

Payload URL: http://mattermost.remionramp.com:5000
Content type: application/json
Secret: mysecret

And:

  • Just the push event
  • Active

When I try to test with Github feature, I have a return response 400 and a body like this:

Not implemented

Do you know why? How can I investigate on my side?

Also, I have nginx on mattermost.remionramp.com

Thanks!

Remi

Tests

There are no tests at the moment.

any TL,DR guide for config ?

what is the secret_key that should I provide in the config.py file? is that the key GitHub provides for new OAuth applications or the other ones ? does it work for the private repositories I contribute to?
i recently migrated from slack to mattermost and new to the concept btw

Mattermost moving to API version 4

Hey @ptersilie and everyone else!

First, hugely appreciate you sharing this project back with the world. Fantastic work!

I wanted to let you know about our plans moving to API v4:

To make the Mattermost API web service easier to use and to offer more powerful options for these integrations, Mattermost will be moving to a new API version soon. Highlights include:

  • Fully documented API endpoints
  • More in-depth access to server functionality
  • Wider use of established HTTP verbs
  • Consistent endpoint structures
  • A new and improved Go driver

We plan to release API version 4 on March 16th, with Mattermost server 3.7. While the current API version 3 will be supported until September 16th, we recommend you begin using API version 4 soon after its release.

Contributing

API version 4 is an active and on-going project. If you're interested in helping contribute, please join our Mattermost community instance and the APIv4 channel.

We've prepared a contribution process for APIv4 and a progress tracker for new APIv4 enpoints to help you get started.

We're also open for suggestions on adding new API endpoints to help with your integration.

Long messages are split mid-line and even mid-word

When attempting to post a large message to a channel, the message is broken into multiple messages. However, the break seems to be at an arbitrary character location which causes the message breaks to appear mid-line and even mid-word.

It would be nicer if the split was done on a line-break (if there was one reasonably close to the limit), or at whitespace (again, if close enough).

How send error message from function node to template in node red to display in mattermost

Here is my node red flow:

11

Here i am handling error.I am getting error message.But I am not understanding how to send that error message to "polistTemplate" to display in mattermost.

Here is my error handling code:

var dataMsg = msg.payload;
var msgVal;
var parseData = JSON.parse(dataMsg)
if (parseData.header.status === 400) {
msgVal = parseData.header.message;
} else {
msgVal = "Access Token Expired"
}
msg.payload = JSON.stringify(msgVal);
node.error(msgVal.toString(),msg);
node.send(msg);

Here i am sending msg to another node.It display in debug node well.But not in mattermost app.

Anyone please help me how to handle errors in node red and how to send them from one node to another node and how to prepare them in attachment format and display in mattermost

No JSON object could be decoded

Getting this error when I test the plugin - any ideas?

[2018-10-12 09:58:51,671] ERROR in app: Exception on / [POST]
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functionsrule.endpoint
File "/root/src/mattermost-github-integration/mattermostgithub/server.py", line 110, in root
post(msg, url, channel)
File "/root/src/mattermost-github-integration/mattermostgithub/server.py", line 128, in post
print('Encountered error posting to Mattermost URL %s, status=%d, response_body=%s' % (url, r.status_code, r.json()))
File "/usr/local/lib/python2.7/dist-packages/requests/models.py", line 866, in json
return complexjson.loads(self.text, **kwargs)
File "/usr/lib/python2.7/json/init.py", line 339, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

webhook not publishing in mattermost

I am trying tin integrate this with GHE. I have set up webhook in GHE. I can see GHE sending payload over to integration server(10.1x.xx.xx) - - [28/Jan/2016 19:48:54] "POST / HTTP/1.1" 200 - ) seems like Integration server is not sending payload over to mattermost server. However I can manually send test messages to mattermost server using same incoming webhook.

always get bad request response before any code in def root() runs

I tried adding a print as the first line of def root():

so im running from docker
Ive connected into the running docker container
if I run wget --post-data="some=data" localhost:5000
I get this error:

bash-4.3# wget --post-data="asd=sd" localhost:5000
Connecting to localhost:5000 (127.0.0.1:5000)
wget: server returned error: HTTP/1.0 400 BAD REQUEST

where the first line of def root(): never runs. Any ideas?

(github webhook is set to application/json and also returns that the server says bad request)

`AssertionError: View function mapping is overwriting an existing endpoint function: root`

Traceback (most recent call last):
  File "mattermostgithub/server.py", line 17, in <module>
    @app.route(config.SERVER['hook'] or "/", methods=['POST'])
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1080, in decorator
    self.add_url_rule(rule, endpoint, f, **options)
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 64, in wrapper_func
    return f(self, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1051, in add_url_rule
    'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: root

I'm at 92394f2

mattermost username

I don't know if is in this part on mattermost side but username we specified in config.py is not used.

The username used is the one which has created the webhook.

In my config.py I have : USERNAME = "Github" and in Mattermost it displays mynickname (BOT)

we can so easily believe that i've sent this message.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.