Skip to content
This repository was archived by the owner on May 5, 2025. It is now read-only.

Commit b715526

Browse files
author
Pablo Mercado
authored
Merge pull request #219 from triggermesh/bridge/webhook-to-slack
Add bridge webhook to slack
2 parents b30f4e2 + 3511aa5 commit b715526

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# Writing a Webhook to Slack Bridge
2+
3+
This Bridge connects an HTTP endpoint to Slack. Every time the webhook is called a message will be produced, which we will validate and transform into an Slack message.
4+
5+
We will be calling the exposed HTTP endpoint using `curl`, in a real world scenario the caller would be an application configuring a webhook callback.
6+
7+
## Events
8+
9+
Webhook Source produce arbitrary events based on configuration and received requests.
10+
11+
- `type` attribute is set to the one configured by user.
12+
- `source` attribute is set to the one configured by user.
13+
- `datacontenttype` is set to the `Content-Type` received at the incoming request.
14+
- `data` is set to the body of the received request.
15+
16+
Slack Target expect one of these 3 event types along with their related payload:
17+
18+
- `com.slack.webapi.chat.postMessage` for consuming [chat.postMessage][chat.postMessage]
19+
- `com.slack.webapi.chat.scheduleMessage` for consuming [chat.scheduleMessage][chat.scheduleMessage]
20+
- `com.slack.webapi.chat.update` for consuming [chat.update][chat.update]
21+
22+
This fictional scenario will send the following data to the Webhook Source using `curl`.
23+
```json
24+
{"message": "Hello Slack!"}
25+
```
26+
27+
The Webhook Source is expected to produce this event.
28+
29+
```json
30+
type: webhook.slack.postmessage
31+
data: {"message": "Hello Slack!"}
32+
others: ...
33+
```
34+
35+
We will be using TriggerMesh's Function to perform a transformation which will consume the event above and produce this one.
36+
37+
```json
38+
type: com.slack.webapi.chat.postMessage
39+
data: {"channel":"ABCDE12345", "text": "Hello Slack!"}
40+
others: ...
41+
```
42+
43+
This event will finally be consumed by the Slack Target that will in turn call the Slack API to post the message.
44+
45+
## Webhook Source
46+
47+
For simplicity we are setting up a non authenticated Webhook and using the default Kubernetes namespace.
48+
49+
```yaml
50+
apiVersion: sources.triggermesh.io/v1alpha1
51+
kind: WebhookSource
52+
metadata:
53+
name: post-message
54+
spec:
55+
eventType: webhook.slack.postmessage
56+
eventSource: webhoock.post-message
57+
58+
sink:
59+
ref:
60+
apiVersion: eventing.knative.dev/v1
61+
kind: Broker
62+
name: default
63+
```
64+
65+
The `eventType` and `eventSource` CloudEvents attributes are being set for further event filtering. There is a reference to a Broker sink object where events will be sent, we will get to that one later.
66+
67+
## Slack Target
68+
69+
Slack Target requires:
70+
71+
- Creating a new [Slack App][slack-apps]: add the `chat:write` permission under `Bot Token Scopes`, then install the application at your workspace.
72+
- A Slack API token: from the **Install App** menu retrieve the OAuth Access token that begins with `xoxb-`.
73+
74+
Create a secret using the Slack API token
75+
76+
```yaml
77+
apiVersion: v1
78+
kind: Secret
79+
metadata:
80+
name: slack-tm
81+
type: Opaque
82+
stringData:
83+
token: xoxb-12345-abcde
84+
```
85+
86+
Create the Slack Target referencing the API token.
87+
88+
```yaml
89+
apiVersion: targets.triggermesh.io/v1alpha1
90+
kind: SlackTarget
91+
metadata:
92+
name: slack-tm
93+
spec:
94+
token:
95+
secretKeyRef:
96+
name: slack-tm
97+
key: token
98+
```
99+
100+
## Transformation Component
101+
102+
To bridge the gap between the event produced by the Webhook Source and the one expected at the Slack Target we need to perform a transformation, which we can do using a declarative or coded approach. We will use the later here.
103+
104+
Replace the channel ID in this transformation with the one you want to use. The channel ID can be retrieved from the URL either at the browser or selecting the `copy link` option at the Slack app. Please make sure that the bot user is added to the Slack channel.
105+
106+
```yaml
107+
apiVersion: extensions.triggermesh.io/v1alpha1
108+
kind: Function
109+
metadata:
110+
name: webhook-to-slack
111+
spec:
112+
runtime: python
113+
public: false
114+
entrypoint: transformToSlack
115+
ceOverrides:
116+
extensions:
117+
type: com.slack.webapi.chat.postMessage
118+
code: |
119+
from random import randrange
120+
121+
def transformToSlack(event, context):
122+
return {
123+
"channel":"REPLACE-CHANNEL-ID",
124+
"text": event['message']
125+
}
126+
```
127+
128+
## Routing Components
129+
130+
In order to connect all components we will setup these elements:
131+
132+
- A central Broker that receives messages from the Source
133+
- A Trigger that consumes Webhook events filtered by the `webhook.slack.postmessage` type and sends them to the transformation Function.
134+
- A Trigger that consumes transformed events filtered by the `com.slack.webapi.chat.postMessage` type and sends them to the Slack target.
135+
136+
The Broker name is set to `default` to match the one used at the Webhook Source earlier.
137+
138+
```yaml
139+
apiVersion: eventing.knative.dev/v1
140+
kind: Broker
141+
metadata:
142+
name: default
143+
```
144+
145+
Both Triggers are setup on the Broker and subscribe their corresponding destination filtering by types.
146+
147+
```yaml
148+
apiVersion: eventing.knative.dev/v1
149+
kind: Trigger
150+
metadata:
151+
name: wehook-to-transform
152+
spec:
153+
broker: default
154+
filter:
155+
attributes:
156+
type: webhook.slack.postmessage
157+
subscriber:
158+
ref:
159+
apiVersion: extensions.triggermesh.io/v1alpha1
160+
kind: Function
161+
name: webhook-to-slack
162+
163+
---
164+
165+
apiVersion: eventing.knative.dev/v1
166+
kind: Trigger
167+
metadata:
168+
name: slack-post-messages
169+
spec:
170+
broker: default
171+
filter:
172+
attributes:
173+
type: com.slack.webapi.chat.postMessage
174+
subscriber:
175+
ref:
176+
apiVersion: targets.triggermesh.io/v1alpha1
177+
kind: SlackTarget
178+
name: slack-tm
179+
```
180+
181+
## Done
182+
183+
Retrieve the URL where the Webhook is listening for incoming requests.
184+
185+
```console
186+
$ kubectl get webhooksources.sources.triggermesh.io post-message
187+
NAME READY REASON URL SINK AGE
188+
post-message True https://webhooksource-post-message.woodford.dev.triggermesh.io http://broker-ingress.knative-eventing.svc.cluster.local/woodford/default 61s
189+
190+
Use `curl` or any HTTP capable client to post messages at Slack.
191+
192+
```
193+
curl -d '{"message":"test my bridge"}' https://webhooksource-post-message.woodford.dev.triggermesh.io
194+
```
195+
196+
Thid Bridge can be extended in many different ways:
197+
198+
- Validation and error handling at the transformation Function.
199+
- The Channel could be provided as a parameter from the WebhookSource, defaulting to a channel provided by the Function.
200+
- AWS Comprehend could be used for sentiment analysis.
201+
- Messages could be enriched if they contain word `avocado` with 🥑
202+
- Add a Twilio Source that will also feed incoming messages to the Broker.
203+
- Add a Datadog Target that will convert a subset of filtered messages into alerts.
204+
205+
If you have any questions on how to build this Bridge or how to modify it to suit your needs, join our [Community Slack](http://triggermesh-community.slack.com/) and [contact us](mailto:[email protected]).
206+
207+
[chat.postMessage]: https://api.slack.com/methods/chat.postMessage
208+
[chat.scheduleMessage]: https://api.slack.com/methods/chat.scheduleMessage
209+
[chat.update]: https://api.slack.com/methods/chat.update
210+
[slack-apps]: https://api.slack.com/apps
211+

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ nav:
4747
- Doing a Transformation: guides/doingatransformation.md
4848
- Writing a Function: guides/writingafunction.md
4949
- Using TIL: guides/tilgettingstarted.md
50+
- Bridges:
51+
- Webhook to Slack: guides/bridges/webhook-to-slack.md
5052
- Installation:
5153
- '': guides/installation.md
5254
- Using an AWS AMI: guides/installation-ami.md

0 commit comments

Comments
 (0)