How to Use Cloud Functions to Automate GitHub Moderation
Tags: webdev, github, programming, tutorial
Published: 2023-12-05 11:49:36

In today's world, automated tools enhance productivity and ensure task consistency while maintaining accuracy. When managing repositories on GitHub, moderation can become tedious, especially as the number of issues open each day increases.

What if there were a way to bring automation to this process, streamlining the workflow and ensuring timely responses? [Appwrite](https://appwrite.io?utm_source=hackmamba&utm_medium=hackmamba-blog) Functions — a potent tool to supercharge our GitHub moderation tasks — is all we need.

In this tutorial, we‘ll learn how to automate GitHub moderation using Appwrite Functions and the "GitHub issue bot" template. We‘ll also cover customizing the comments the bot posts when creating an issue and tailoring it to our preferred response. Finally, we’ll discuss how to monitor the performance of the Appwrite function.

## Prerequisites

We’ll need a few things to fully understand the concepts presented in this tutorial:

- A basic understanding of JavaScript
- A GitHub [account](https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F&source=header-home)
- An Appwrite [account](https://cloud.appwrite.io/register?utm_source=hackmamba&utm_medium=hackmamba-blog)


## Getting started

First, let’s create a GitHub repository; this will serve as the workspace for our Appwrite Function to perform and await new issues. Here's how:

- Log into [GitHub](https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F&source=header-home).
- Click the **New Repository** button.
- Name it `github_moderation`.
- Click **Create Repository**.


![Create a GitHub repository](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698268860458_Screenshot+2023-10-25+at+22.19.46.png)

## Setting up a webhook

With the repo set up, let’s establish the webhook. Webhooks are automated systems that allow external services to track changes and send data within a system. Here, we’ll set up a webhook to monitor actions within the repository to listen to events closely. 

To do this, navigate to the **Settings** tab of the repository and click **Webhooks** as shown below.

![Navigate to the webhook section](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698269052180_Screenshot+2023-10-25+at+22.22.32.png)


Next, we need to set the webhook with the following details:

- Click **Add webhook**.
- For the **Payload URL**, enter `https://sample.com/`.
- Choose `application/json` for **Content type**.
- Type in `myTopSecret` for the **Secret**.


![Add webhook](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698269268062_Screenshot+2023-10-25+at+22.25.26.png)

![Input webhook details](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698269521024_Screenshot+2023-10-25+at+22.31.43.png)

> Note: The https://sample.com URL is a placeholder; we will replace it with our Appwrite Function domain later.  It's also important to note the secret we entered, as it will be used when configuring the Function.

Next, change the event option to **Let me select individual events**, select Issues, and **Add webhook**.

![Select individual event type](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698269699112_Screenshot+2023-10-25+at+22.34.00.png)

![Select issues from the option and save](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698269775088_Screenshot+2023-10-25+at+22.35.35.png)

## Create an access token

We must create an access token for our Function to connect to GitHub and securely monitor activities via the Webhook. To do this, click the **Settings** menu under the profile drawer and navigate to the **Developer settings** section.

![Click settings on GitHub profile](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1699664138158_Screenshot+2023-11-11+at+01.55.25.png)

![GitHub Developer Settings](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698270398063_Screenshot+2023-10-25+at+22.44.06.png)


Navigate to the **Fine-grained tokens** tab and click the **Generate new token** button.

![Generate a New Token](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698270923715_Screenshot+2023-10-25+at+22.52.10.png)


Input `github_moderation` as the name, and change the **Repository access** to **All Repository.**


![Input token name and give access](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698271137543_Screenshot+2023-10-25+at+22.58.00.png)


Scroll to the **Repository permissions** section in the **Issues** category, change the permission to **Read and Write**, and then click the **Generate token** button to create it.

![Update permission in the issues category](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698271380726_Screenshot+2023-10-25+at+23.02.12.png)


After completing these steps, GitHub will generate an access token for us. Store this token securely; we will need it when creating our Function.

![Generate Access Token](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698271617967_Screenshot+2023-10-25+at+23.05.47.png)


All set with GitHub! Let’s create a cloud function on Appwrite in the following step.


## Create a Cloud Function on Appwrite

To make the process seamless, Appwrite offers two options for creating functions. We can create a function from scratch, allowing for extensive customization, or we can choose from a set of templates with support for various runtimes, making it more convenient. In our case, we will create from a template.

To do this, we need to log into our Appwrite console, click the **Create project** button, input `github_moderation` as the name, and then **Create**.


![Create project on Appwrite](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1699567327082_Screenshot+2023-11-09+at+23.01.53.png)


Next, navigate to the **Functions** tab, select the **Templates** tab, locate the GitHub issue bot, and click **Create function**.


![Appwrite dashboard](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1699567752899_Screenshot+2023-11-09+at+23.03.57.png)


Input `GitHub issue bot` as the function name, select Node.js - 16.0 as the runtime, and click **Next**.


![Add configuration to Appwrite cloud function](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698272412060_Screenshot+2023-10-25+at+23.19.44.png)


Input the GitHub token and secret we generated earlier and continue.


![Add the required secret](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698272634713_Screenshot+2023-10-25+at+23.23.21.png)


Select **Add to existing repository,** connect to **GitHub**, select the `github_moderation` repository, and continue.


![Connect function to an existing GitHub repository](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698272751651_Screenshot+2023-10-25+at+23.25.39.png)

![Connect GitHub](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698272868832_Screenshot+2023-10-25+at+23.26.54.png)

![Select Repository](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698273060709_Screenshot+2023-10-25+at+23.30.22.png)


Accept the default branch and directory and then **Create**.


![Create Appwrite Function](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698273151949_Screenshot+2023-10-25+at+23.32.06.png)


That’s it! Appwrite will automatically scaffold a function, deploy it, and push the corresponding source code to the specified repository on creation, as shown below.


![Appwrite Function Deployment](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1699568349162_Screenshot+2023-11-09+at+23.15.14.png)

## Update the webhook payload URL and issue comment

With our function deployed, we can get the domain on which it will run and use it as our **Payload URL**. To do this, navigate to the **Domain** tab and copy the URL as shown below.


![Copy Function URL](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1700220512479_3ryR7vH4.png)


Next, we need to update our Webhook URL on GitHub with the copied URL.


![Update Function URL on GitHub](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1700220848474_Screenshot+2023-11-17+at+12.33.05.png)


Finally, to customize the comment that the bot will post when an issue is created, navigate to the **Code** tab and modify the `src/main.js` as shown below:


![Manage webhook](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698274135847_Screenshot+2023-10-25+at+23.47.26.png)


Next, update the following code snippet to the `main.js` file.

```JavaScript
import GithubService from './github.js';
import { throwIfMissing } from './utils.js';
    
export default async ({ res, req, log, error }) => {
     throwIfMissing(process.env, ['GITHUB_WEBHOOK_SECRET', 'GITHUB_TOKEN']);
    
 const github = new GithubService();
    
 if (!(await github.verifyWebhook(req))) {
      error('Invalid signature');
      return res.json({ ok: false, error: 'Invalid signature' }, 401);
 }
    
 if (!github.isIssueOpenedEvent(req)) {
      log('Received non-issue event - ignoring');
      return res.json({ ok: true });
 }
    
 await github.postComment(
    req.body.repository,
    req.body.issue,
    `Thank you for helping us improve our project, someone from our team will respond soon!` //UPDATE THE COMMENT HERE
 );
    
  return res.json({ ok: true });
};
```

![Update main.js](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698274833131_Screenshot+2023-10-26+at+00.00.15.png)


Now that it's set up, we can try it out by opening an Issue in the `**github_moderation**` repository.



{% embed https://www.loom.com/share/2a656fce3ba44e65b593b66c3d57a60f?sid=f3918219-2434-4ee2-84b5-f9e7a4256072 %}


Additionally, we can check the Appwrite function's performance and the GitHub webhook's operation, as shown below.

![Execution on Appwrite](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1698275589770_Screenshot+2023-10-26+at+00.12.16.png)

![Webhook deliveries on GitHub](https://paper-attachments.dropboxusercontent.com/s_0FD9F6C4264404EAD8C20D4E02F7FF9F1D9DF860385D62F086E40E39E79BA09C_1699887793493_MSWpkB7c.jpg)


As mentioned above, Appwrite allows the flexibility to create custom functions from scratch and offers numerous templates. These templates are a game-changer, providing developers with flexibility and a head start and enabling them to rapidly develop and customize functionalities in new and existing applications using Appwrite's functions. 

Additionally, the range of templates available supports multiple programming languages, giving developers a broad spectrum of options within the Appwrite ecosystem.


## Conclusion

In this tutorial, we provided a step-by-step guide on how to use Appwrite Cloud Functions for automating GitHub moderation. We also demonstrated how to customize the comments the bot posts when creating an issue, tailoring it to our preferred response. Additionally, we discussed how to monitor the Appwrite function's performance and the GitHub webhook's operation via the dashboard.

These resources might also be helpful:

- [Appwrite Function guide](https://appwrite.io/docs/references/cloud/client-web/functions?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite Function development guide](https://appwrite.io/docs/products/functions/development?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [GitHub Webhook documentation](https://docs.github.com/en/webhooks?utm_source=hackmamba&utm_medium=hackmamba-blog)