How to Automate Netlify Deploys with a Slack Bot
I believe that everything that can be automated should be automated. That is why I decided to harness the power of webhooks and build a Slack bot, instead of going to my Netlify dashboard to trigger a deploy when I make a change to the code for my website. The Slack bot automates the triggering of new Netlify builds, which saves time and reduces the friction that comes with manually triggering Netlify deploys. In this post, I will help you along as you learn how to build out this service and automate your deploys.
After reading this post, you will learn how to :
- Build a Slack bot & configure Slack webhooks
- Configure Netlify Build Hooks
Setting up the Slack Bot and Netlify integration
Building The Slack Bot
The Slack bot is crucial to this service. Once a user on our workspace mentions the bot, the goal is for it to trigger a Netlify deploy. To get started creating this feature, head over to the Slack API dashboard and create a new Slack app by clicking the “Create A Custom App” button at the top of the page. Next, write the name of the app in the Popup menu, select the workspace the bot will be associated with, and save. After creating the Slack app, it’s time to hook into Slack webhooks to receive notifications when your bot gets mentioned in a Slack channel!
Before you can subscribe to a specific event, you need to provide Slack with a URL. This link is where Slack will send notifications when the event subscribed to is triggered. Slack also requires confirmation that you have control over the URL, and asks you to echo the challenge request parameter they send.
Below is an implementation of the logic of the web server that Slack will send webhook notifications to, written in NodeJS.
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/", async (req, res) => {
const challenge = req.body.challenge;
res.send(challenge).status(200);
});
app.listen(3000, () => console.log(`App is running on port 3000`));
This server can then be deployed using a local tunneling tool like Ngrok [Learn how to set up Ngrok] or Hookdeck CLI. After deploying the above server, you can continue to set up the Slack bot. In the home page of the Slack app we created above, navigate to the event subscriptions page and toggle the “Enable Events” button. Input the URL of the server created above as the value for the request URL field. Select the app_mention from the dropdown menu under the "Subscribe to Bot Events” tab.
The last step in setting up Slack is installing the Slack bot we just configured to our Slack workspace. Click the “Install App” menu on the left hand side of the dashboard, and go ahead and authorize the bot to access your workspace.
Configuring Netlify
In the previous section, we set up the Slack bot to send notifications to our URL any time it is mentioned in the workspace. In this section, you will learn how to set up Netlify’s webhook offering, called “build hooks”.
- In the Netlify dashboard, navigate to Site settings > Build & deploy > Continuous deployment > Build hooks.
- Select “Add Build Hook,” a suitable name for the hook, as well as the Github branch that should be triggered by the hook.
After creating the build hook, you will be provided with a URL that will trigger the build once it receives a request.
Putting It All Together
Our app is coming together nicely. In a couple more steps, you will be done configuring this service. It must be configured so that immediately after a webhook notification is received from Slack, a request is made to Netlify and the build is triggered. To do that, you will need to modify the code for the server we created above.
const TriggerDeploy = () => {
const options = {
method: "POST",
url: "https://api.netlify.com/build_hooks/xxxxxxxxxxxx3b15ad",
headers: {
"Content-type": "application/json",
},
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.statusCode);
});
};
const hasWord = (str, word) => str.split(/\s+/).includes(word);
app.post("/", async (req, res) => {
const body = req.body.event.text;
res.status(200);
const shouldTrigger = hasWord(body, "deploy");
if (shouldTrigger) {
TriggerDeploy();
}
});
The snippet above contains three parts:
- The TriggerDeploy function — this function simply makes a post request to the Netlify build hook URL.
- The hasWord function, which checks whether a word is contained in a sentence and returns a Boolean value.
- The request handler. Within the request handler function, we extract the notification text sent by Slack from the request body, invoke the hasWord function, and conditionally invoke the TriggerDeploy function (if the word “Deploy” is present in the notification sent by Slack).
At this point, you can go ahead and try this service out. Mention the Slack bot in your workspace, and say deploy! You will notice that a new build on your Netlify dashboard will be triggered, as seen below.
Before going to production
Now that we have a working integration, there are a few things we must talk about. Going to production has its challenges specifically with webhooks. Missing one or failing to properly synchronize has consequences. We published a whole guide to help you with this, you can find it right here.
Deploying integration to production
Before you deploy to production, it is important to tidy up your service. You will need to deploy your web server to a proper hosting service like Heroku. [Learn how to deploy a server on Heroku]
After this, set up Hookdeck to handle the ingestion and error handling of the webhook connections. This ensures that you will not miss any webhook notifications. Finally, update the request URL field with the new URL Hookdeck has provided.
Conclusion
In this tutorial, we have learned how to harness the power of webhooks to automate what could otherwise be a very boring task: manually triggering Netlify deploys. We also learned about Slack bots and webhooks, and gained some confidence in our skills along the way. Thanks for joining me!