Problem
In PushOwl we have a support channel in slack where unclear or urgent support questions are raised and are usually answered by developers. To avoid chaos and make things more manageable we have weekly support owners for the channel. Where developers from backend and frontend teams are made owners of the channel on a round-robin schedule. The owner gets changed every week on Monday. It becomes hard to track who becomes the next owner of the channel and do this every week on Monday morning.
Building a slack bot
To avoid this issue we decided to build a Slack bot that:
- chooses one developer each from backend and frontend from a list of developers, for the current week
- puts a message on a Slack channel about the chosen support owners every Monday morning
Bots need to be hosted on a server. But instead of hosting a separate server, we decided to use Github actions to do this. Because we are already using Github Actions, so why not!
Iterating through the list
To pick the next person on the list every week we need to store the index of the last owner.
But Github action does not provide a way to store data so we need a way to pick the next person in the list. Luckily for us, we can use the week number of the year to deal with this. So to pick up the next person for the week we can do
Index of new owner = The week of the year % Number of people on the list
This will give us a number from 0
to the length of the list iterating every week. This allows us to loop through the list every week easily
Show me the code
This is how our Github action looks now. We use a separate node script for readability but this could be done in the single workflow file
name: Channel owner
on:
push:
schedule:
- cron: "30 3 * * MON"
jobs:
tech-support-owner:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm i
- uses: actions/github-script@v3
with:
script: |
const script = require(`${process.env.GITHUB_WORKSPACE}/scripts/owner.js`)
const val = await script()
env:
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}
and the node script owner.js
looks as follows
Date.prototype.getWeek = function () {
const onejan = new Date(this.getFullYear(), 0, 1);
const today = new Date(this.getFullYear(), this.getMonth(), this.getDate());
const dayOfYear = (today - onejan + 86400000) / 86400000;
return Math.ceil(dayOfYear / 7);
};
module.exports = async () => {
const client = new WebClient(process.env.SLACK_TOKEN);
const frontendOwner =
owners.frontend[Math.floor(new Date().getWeek() % owners.frontend.length)];
const backendOwner =
owners.backend[Math.floor(new Date().getWeek() % owners.backend.length)];
await client.conversations.setTopic({
channel: CHANNEL,
topic: `Current assigned owners
Frontend: <@${frontendOwner.id}>
Backend: <@${backendOwner.id}>
`,
});
};
Things we could improve
- We could read the google calendar availability for the developer before setting them as the channel owner if they are on leave we could skip them for the week. That would be cool! 🔥