Matrix provides an “open network for secure, decentralised communication”. With Matrix bridges, you can connect to Slack, IRC, Teams, Discord, you name it!
This blog post explains how to interconnect a Tekton pipeline with a Matrix room, for the purpose of notifying the room members of the pipeline status.
Matrix API
Matrix provides several APIs, Client-Server API is one of them.
In order to be able to send messages to a matrix room, the Tekton pipeline needs to send an access_token along with the request to the Matrix server.
Thus, a prerequisite to this task is to register a Matrix user for the bot with one of the Matrix servers.
Obtaining a Matrix access_token
Once the registration process is done, I obtained the access_token through a simple login API call:
{“user_id”:”@sherine.khoury:matrix.org”,”access_token”:”syt_c2hlcmluZS5raG91cnk_NFpzzGCtxFAHEDVKhYTl_123456″,”home_server”:”matrix.org”,”device_id”:”CNYGHLSLQY”,”well_known”:{“m.homeserver”:{“base_url”:”https://matrix-client.matrix.org/”}}}
With the access_token, I created a secret, with name matrix-access-token in the namespace hosting my pipeline, of type generic with a single key, token, containing the access_token I just obtained in the step above.
Example
apiVersion: v1
metadata:
name: matrix-access-token
stringData:
token: {OAuth token for the bot app}
Obtaining the Matrix Room ID
The hardest for me was to create a room with Matrix. I’m pretty new to Matrix 😛, and it seems every server has different rules when it comes to the request body of POST /_matrix/client/v3/createRoom.
Similarly, every Matrix client calls the room differently: On FluffyChat, it’s a Group, which can be created after creating a space. In Element, it’s simply called a room!! Thankfully.
When you create a room in Element, the web UI provides the room ID back to you.
But you still need to set a Local address for the room in the Room Settings in order to be able to query the roomAlias by API. 🤷
The room alias usually is #ROOM_NAME:SERVER_NAME.
So for a room with name my-team on matrix.org, you can also obtain the RoomID by sending the following request to the client-server API:
{“room_id”:”!xWldUqOaDUkrHUZRIP:matrix.org”,”servers”:[“matrix.org”]}
Notice there is no need for authentication here. Notice also the %23 replacing the # character in the room alias.
Tekton Task
Largely inspired from the Slack task on TektonHub:
kind: Task
metadata:
name: send-to-matrix-room
labels:
app.kubernetes.io/version: “0.1”
annotations:
tekton.dev/pipelines.minVersion: “0.12.1”
tekton.dev/categories: Messaging
tekton.dev/tags: messaging
tekton.dev/platforms: “linux/amd64,linux/s390x,linux/ppc64le”
spec:
description: >-
These tasks post a simple message to a matrix room.
This task uses Matrix’s Client-Server REST api to send the message.
params:
– name: matrix-access-token
type: string
description: secret name containing matrix access token (key is token)
– name: room
type: string
description: room id (in the format !<ROOM_ID>:<SERVER_NAME>)
– name: endpoint
type: string
description: Matrix server URL to which to send the message
– name: message
type: string
description: plain text message
steps:
– name: post
image: docker.io/curlimages/curl:7.70.0@sha256:031df77a11e5edded840bc761a845eab6e3c2edee22669fb8ad6d59484b6a1c4 #tag: 7.70.0
script: |
#!/bin/sh
/usr/bin/curl -X POST -H ‘Content-type: application/json’ –data ‘{“msgtype”:”m.text”, “body”:”$(params.message)”}’ https://$(params.endpoint)/_matrix/client/r0/rooms/$(params.room)/send/m.room.message?access_token=$TOKEN
env:
– name: TOKEN
valueFrom:
secretKeyRef:
name: $(params.matrix-access-token)
key: token
💡 It could be an idea to replace room and endpoint by the room alias.
Instead of having a single step I could have used:
Use cut -d: -f2, I could retrieve the endpoint
Curl the /_matrix/client/v3/directory/room to retrieve the RoomID
Send the message using the RoomID and Endpoint
💡 If this looks good, I could send a PR to the TektonHub.
Tekton example pipeline
Now that I’ve got a task, I can use that task in a pipeline, like so:
kind: Pipeline
metadata:
name: pipeline-matrix-hello
namespace: okd-team
spec:
params:
– name: matrix-room
description: room id (in the format !<ROOM_ID>:<SERVER_NAME>)
type: string
– name: matrix-endpoint
description: room id (in the format !<ROOM_ID>:<SERVER_NAME>)
type: string
– name: repo-name
description: The repo name
type: string
– name: bundle-version
description: The bundle version
type: string
tasks:
– name: talk-to-matrix
params:
– name: matrix-access-token
value: matrix-access-token
– name: endpoint
value: $(params.matrix-endpoint)
– name: room
value: $(params.matrix-room)
– name: message
value: Going to run operator pipeline on repo $(params.repo-name) to build $(params.bundle-version)
taskRef:
kind: Task
name: send-to-matrix-room
Finally, start the pipeline using
The logs of the pipelinerun show:
[talk-to-matrix : post] % Total % Received % Xferd Average Speed Time Time Time Current
[talk-to-matrix : post] Dload Upload Total Spent Left Speed
100 172 0 59 100 113 114 219 –:–:– –:–:– –:–:– 334
[talk-to-matrix : post] {“event_id”:”$EYhJ9A5DlMlBx8xD4ORF9q-8r1KmLTsvODvCgwu5xkU”}