commit
				
					
						42317f74d9
					
				
			
		
					 7 changed files with 153 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -3,3 +3,4 @@
 | 
			
		|||
.mypy_cache
 | 
			
		||||
coverage.xml
 | 
			
		||||
htmlcov
 | 
			
		||||
__pycache__
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -88,6 +88,19 @@ Add a JSON webhook with `?formatter=github`, and put the `API_KEY` as secret
 | 
			
		|||
 | 
			
		||||
Add a webhook with an URL ending with `?formatter=grafana&key=API_KEY`
 | 
			
		||||
 | 
			
		||||
### For Gitlab
 | 
			
		||||
 | 
			
		||||
At a group level, Gitlab does not permit to setup webhooks. A workaround consists to use Google
 | 
			
		||||
Chat or Microsoft Teams notification integration with a custom URL (Gitlab does not check if the url begins with the normal url of the service).
 | 
			
		||||
 | 
			
		||||
#### Google Chat
 | 
			
		||||
 | 
			
		||||
Add a Google Chat integration with an URL ending with `?formatter=gitlab_gchat&key=API_KEY`
 | 
			
		||||
 | 
			
		||||
#### Microsoft Teams
 | 
			
		||||
 | 
			
		||||
Add a Microsoft Teams integration with an URL ending with `?formatter=gitlab_teams&key=API_KEY`
 | 
			
		||||
 | 
			
		||||
## Test room
 | 
			
		||||
 | 
			
		||||
[#matrix-webhook:tetaneutral.net](https://matrix.to/#/!DPrUlnwOhBEfYwsDLh:matrix.org)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
"""Formatters for matrix webhook."""
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def grafana(data, headers):
 | 
			
		||||
    """Pretty-print a grafana notification."""
 | 
			
		||||
| 
						 | 
				
			
			@ -30,3 +32,29 @@ def github(data, headers):
 | 
			
		|||
        data["body"] = "notification from github"
 | 
			
		||||
    data["digest"] = headers["X-Hub-Signature-256"].replace("sha256=", "")
 | 
			
		||||
    return data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gitlab_gchat(data, headers):
 | 
			
		||||
    """Pretty-print a gitlab notification preformatted for Google Chat."""
 | 
			
		||||
    data["body"] = re.sub("<(.*?)\\|(.*?)>", "[\\2](\\1)", data["body"], re.MULTILINE)
 | 
			
		||||
    return data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gitlab_teams(data, headers):
 | 
			
		||||
    """Pretty-print a gitlab notification preformatted for Microsoft Teams."""
 | 
			
		||||
    body = []
 | 
			
		||||
    for section in data["sections"]:
 | 
			
		||||
        if "text" in section.keys():
 | 
			
		||||
            text = section["text"].split("\n\n")
 | 
			
		||||
            text = ["* " + t for t in text]
 | 
			
		||||
            body.append("\n" + "  \n".join(text))
 | 
			
		||||
        elif all(
 | 
			
		||||
            k in section.keys()
 | 
			
		||||
            for k in ("activityTitle", "activitySubtitle", "activityText")
 | 
			
		||||
        ):
 | 
			
		||||
            text = section["activityTitle"] + " " + section["activitySubtitle"] + " → "
 | 
			
		||||
            text += section["activityText"]
 | 
			
		||||
            body.append(text)
 | 
			
		||||
 | 
			
		||||
    data["body"] = "  \n".join(body)
 | 
			
		||||
    return data
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								tests/example_gitlab_gchat.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/example_gitlab_gchat.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
{"text":"John Doe pushed to branch \u003chttps://gitlab.com/jdoe/test/commits/master|master\u003e of \u003chttps://gitlab.com/jdoe/test|John Doe / test\u003e (\u003chttps://gitlab.com/jdoe/test/compare/b76004b20503d4d506e51a670de095cc063e4707...3517b06c64c9d349e2213650d6c009db0471361e|Compare changes\u003e)\n\u003chttps://gitlab.com/jdoe/test/-/commit/3517b06c64c9d349e2213650d6c009db0471361e|3517b06c\u003e: Merge branch 'prod' into 'master' - John Doe\n\n\u003chttps://gitlab.com/jdoe/test/-/commit/1f661795b220c5fe352f391eb8de3ac4fcc6fc1d|1f661795\u003e: Merge branch 'revert-a827b196' into 'prod' - John Doe\n\n\u003chttps://gitlab.com/jdoe/test/-/commit/b76004b20503d4d506e51a670de095cc063e4707|b76004b2\u003e: Merge branch 'revert-a827b196' into 'master' - John Doe"}
 | 
			
		||||
							
								
								
									
										1
									
								
								tests/example_gitlab_teams.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/example_gitlab_teams.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
{"sections":[{"activityTitle":"John Doe pushed to branch [master](https://gitlab.com/jdoe/test/commits/master)","activitySubtitle":"in [John Doe / test](https://gitlab.com/jdoe/test)","activityText":"[Compare changes](https://gitlab.com/jdoe/test/compare/b76004b20503d4d506e51a670de095cc063e4707...3517b06c64c9d349e2213650d6c009db0471361e)","activityImage":"https://secure.gravatar.com/avatar/80\u0026d=identicon"},{"text":"[3517b06c](https://gitlab.com/jdoe/test/-/commit/3517b06c64c9d349e2213650d6c009db0471361e): Merge branch 'prod' into 'master' - John Doe\n\n[1f661795](https://gitlab.com/jdoe/test/-/commit/1f661795b220c5fe352f391eb8de3ac4fcc6fc1d): Merge branch 'revert-a827b196' into 'prod' - John Doe\n\n[b76004b2](https://gitlab.com/jdoe/test/-/commit/b76004b20503d4d506e51a670de095cc063e4707): Merge branch 'revert-a827b196' into 'master' - John Doe"}],"title":"John Doe / test","summary":"John Doe pushed to branch [master](https://gitlab.com/jdoe/test/commits/master) of [John Doe / test](https://gitlab.com/jdoe/test) ([Compare changes](https://gitlab.com/jdoe/test/compare/b76004b20503d4d506e51a670de095cc063e4707...3517b06c64c9d349e2213650d6c009db0471361e))"}
 | 
			
		||||
							
								
								
									
										54
									
								
								tests/test_gitlab_gchat.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tests/test_gitlab_gchat.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
"""
 | 
			
		||||
Test module for gitlab "google chat" formatter.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import httpx
 | 
			
		||||
import nio
 | 
			
		||||
 | 
			
		||||
from .start import BOT_URL, FULL_ID, KEY, MATRIX_ID, MATRIX_PW, MATRIX_URL
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GitlabGchatFormatterTest(unittest.IsolatedAsyncioTestCase):
 | 
			
		||||
    """Gitlab "google chat" formatter test class."""
 | 
			
		||||
 | 
			
		||||
    async def test_gitlab_gchat_body(self):
 | 
			
		||||
        """Send a markdown message, and check the result."""
 | 
			
		||||
        messages = []
 | 
			
		||||
        client = nio.AsyncClient(MATRIX_URL, MATRIX_ID)
 | 
			
		||||
 | 
			
		||||
        await client.login(MATRIX_PW)
 | 
			
		||||
        room = await client.room_create()
 | 
			
		||||
 | 
			
		||||
        with open("tests/example_gitlab_gchat.json") as f:
 | 
			
		||||
            example_gitlab_gchat_request = f.read()
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            httpx.post(
 | 
			
		||||
                f"{BOT_URL}/{room.room_id}",
 | 
			
		||||
                params={"formatter": "gitlab_gchat", "key": KEY},
 | 
			
		||||
                content=example_gitlab_gchat_request,
 | 
			
		||||
            ).json(),
 | 
			
		||||
            {"status": 200, "ret": "OK"},
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        sync = await client.sync()
 | 
			
		||||
        messages = await client.room_messages(room.room_id, sync.next_batch)
 | 
			
		||||
        await client.close()
 | 
			
		||||
 | 
			
		||||
        message = messages.chunk[0]
 | 
			
		||||
        self.assertEqual(message.sender, FULL_ID)
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            message.body,
 | 
			
		||||
            "John Doe pushed to branch [master](https://gitlab.com/jdoe/test/commits/m"
 | 
			
		||||
            + "aster) of [John Doe / test](https://gitlab.com/jdoe/test) ([Compare chan"
 | 
			
		||||
            + "ges](https://gitlab.com/jdoe/test/compare/b76004b20503d4d506e51a670de095"
 | 
			
		||||
            + "cc063e4707...3517b06c64c9d349e2213650d6c009db0471361e))\n[3517b06c](http"
 | 
			
		||||
            + "s://gitlab.com/jdoe/test/-/commit/3517b06c64c9d349e2213650d6c009db047136"
 | 
			
		||||
            + "1e): Merge branch 'prod' into 'master' - John Doe\n\n[1f661795](https://"
 | 
			
		||||
            + "gitlab.com/jdoe/test/-/commit/1f661795b220c5fe352f391eb8de3ac4fcc6fc1d):"
 | 
			
		||||
            + " Merge branch 'revert-a827b196' into 'prod' - John Doe\n\n[b76004b2](htt"
 | 
			
		||||
            + "ps://gitlab.com/jdoe/test/-/commit/b76004b20503d4d506e51a670de095cc063e4"
 | 
			
		||||
            + "707): Merge branch 'revert-a827b196' into 'master' - John Doe",
 | 
			
		||||
        )
 | 
			
		||||
							
								
								
									
										55
									
								
								tests/test_gitlab_teams.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								tests/test_gitlab_teams.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
"""
 | 
			
		||||
Test module for gitlab "teams" formatter.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import httpx
 | 
			
		||||
import nio
 | 
			
		||||
 | 
			
		||||
from .start import BOT_URL, FULL_ID, KEY, MATRIX_ID, MATRIX_PW, MATRIX_URL
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GitlabTeamsFormatterTest(unittest.IsolatedAsyncioTestCase):
 | 
			
		||||
    """Gitlab "teams" formatter test class."""
 | 
			
		||||
 | 
			
		||||
    async def test_gitlab_teams_body(self):
 | 
			
		||||
        """Send a markdown message, and check the result."""
 | 
			
		||||
        messages = []
 | 
			
		||||
        client = nio.AsyncClient(MATRIX_URL, MATRIX_ID)
 | 
			
		||||
 | 
			
		||||
        await client.login(MATRIX_PW)
 | 
			
		||||
        room = await client.room_create()
 | 
			
		||||
 | 
			
		||||
        with open("tests/example_gitlab_teams.json") as f:
 | 
			
		||||
            example_gitlab_teams_request = f.read()
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            httpx.post(
 | 
			
		||||
                f"{BOT_URL}/{room.room_id}",
 | 
			
		||||
                params={"formatter": "gitlab_teams", "key": KEY},
 | 
			
		||||
                content=example_gitlab_teams_request,
 | 
			
		||||
            ).json(),
 | 
			
		||||
            {"status": 200, "ret": "OK"},
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        sync = await client.sync()
 | 
			
		||||
        messages = await client.room_messages(room.room_id, sync.next_batch)
 | 
			
		||||
        await client.close()
 | 
			
		||||
 | 
			
		||||
        message = messages.chunk[0]
 | 
			
		||||
        self.assertEqual(message.sender, FULL_ID)
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            message.body,
 | 
			
		||||
            "John Doe pushed to branch [master](https://gitlab.com/jdoe/test/commits"
 | 
			
		||||
            + "/master) in [John Doe / test](https://gitlab.com/jdoe/test) \u2192 [Com"
 | 
			
		||||
            + "pare changes](https://gitlab.com/jdoe/test/compare/b76004b20503d4d506e5"
 | 
			
		||||
            + "1a670de095cc063e4707...3517b06c64c9d349e2213650d6c009db0471361e)  \n\n*"
 | 
			
		||||
            + " [3517b06c](https://gitlab.com/jdoe/test/-/commit/3517b06c64c9d349e2213"
 | 
			
		||||
            + "650d6c009db0471361e): Merge branch 'prod' into 'master' - John Doe  \n*"
 | 
			
		||||
            + " [1f661795](https://gitlab.com/jdoe/test/-/commit/1f661795b220c5fe352f3"
 | 
			
		||||
            + "91eb8de3ac4fcc6fc1d): Merge branch 'revert-a827b196' into 'prod' - John"
 | 
			
		||||
            + " Doe  \n* [b76004b2](https://gitlab.com/jdoe/test/-/commit/b76004b20503"
 | 
			
		||||
            + "d4d506e51a670de095cc063e4707): Merge branch 'revert-a827b196' into 'mas"
 | 
			
		||||
            + "ter' - John Doe",
 | 
			
		||||
        )
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue