# Optimizing Productivity: A Step-by-Step Guide to Setting Up a Build Bot with Slack and AWS CodeBuild for Seamless Workflow

![](https://file.notion.so/f/f/f370e646-8657-43d5-9288-cf00f03fb9e4/0f0bdae9-496e-4ba9-a5f6-671479ad91b0/slack-bot-builder.png?id=f7e8d23c-0054-4f4d-8701-d52472da8fdd&table=block&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&expirationTimestamp=1703707200000&signature=7fjikz8NUVNAFAkXsVEV5u9i6ttIbBI8sD4Qwu3h8ZI&downloadName=slack-bot-builder.png align="center")

## **Why?**

***Continuous Integration and Continuous Delivery/Continuous Deployment a.k.a CI/CD; this ain’t it.***

…

CI/CDs are great - update a branch through merge, perform a commit or a PR and the build request is sent instantly. A build is made and sent to you without you having to do anything *out of the flow*.

But what if you need a particular build from a made through the source of a particular branch or at a specific commit and the ones that fall between a version change?

You cannot enable CI/CDs on every branch. It may as very well be a waste of resources. So, we have proposed a CLI tool using capabilities of Slack and AWS. A command that **can get you what you want, when you want it.**

## **TL;DR**

### Setup Slack

* Make a Slash Command
    
* Make an Incoming Webhook
    

### Setup Lambda

* Create Lambda
    
* Setup Trigger Lambda
    
* Setup Notification Lambda
    

### Setup CodeBuild

* Configure Source
    
* Configure Artifacts
    
* Configure Amazon Simple Notification Service (SNS)
    

## **How?**

According to our requirements, we needed a way to build an android app with different **build variants,** different **branches,** and due to a sub-module in flutter, a **sub-module branch** parameter was added.

You may add parameters according to your needs. These are just parameters that we required for our build.

### Setup Slack

1. Make sure you are signed-in properly. Now go to [https://api.slack.com/](https://api.slack.com/).
    
2. Click on **Create an app** *(if you don't have one already)*
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa5b2d15f-cc9d-44b8-92c2-2f0fa98bb17a%2FUntitled.png?table=block&id=f173b576-5907-41d7-b6e3-f166b734df2b&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    
3. Click on **From scratch** and enter your app details
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Ff390af5e-688f-4ade-a8c3-4d749afba6a0%2FUntitled.png?table=block&id=97381f06-107e-42bd-9efd-609084f0cf65&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    

### Make a Slash Command

1. Click on **Slash Command** and **Create New Command**
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F4d5478d1-bf88-43ca-9105-43e4fc13cb50%2FUntitled.png?table=block&id=fa59d9c5-92ac-41fa-a285-d9c5f20b595c&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    

Add the required details and click on **Save**

***Note: The request URL is a POST request so make sure the API Gateway is properly configured.***

### Make an Incoming Webhook

1. Click on **Slash Command** and **Create New Incoming Webhook**
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F5ebabae3-084b-4536-8987-a1cee29c39d5%2FUntitled.png?table=block&id=3346f461-6375-4617-a29a-2f42c4adc4e0&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    
2. **Activate Incoming Webhooks**
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc1e27313-b74a-4dd5-a6fd-6bfd28d9811e%2FUntitled.png?table=block&id=5a26d73d-a642-4cab-ab44-e89dc6a0aa3e&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    
3. **Request to Add New Webhook** at the bottom of the page. Send a request with a message that states the purpose of the Incoming Webhook and inform your admin.
    
4. Select the channel that you wish to make the Incoming Webhook of and voilà! You are done.
    

### Setup Lambda

#### Create Lambda

Create two lambda functions:

1. **Trigger lambda** - Used to trigger CodeBuild build
    
2. **Notification lambda** - Used to send a notification on Slack
    

**Note:** You may create the lambda function by referring to [this documentation](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#getting-started-create-function).

#### Setup Trigger Lambda

We will need an API Gateway as a trigger. You may refer to [this](https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html) to build an API Gateway for lambda. The endpoint should be a **POST request** because that's what the **Slack Slash Command** will provide us.

**Request Schema**

```json
{
  "version": "2.0",
  "routeKey": "ANY /triggerAndroidBuild",
  "rawPath": "/default/triggerAndroidBuild",
  "rawQueryString": "",
  "headers": {
    ...
  },
  "requestContext": {
    "accountId": "...",
    "apiId": "...",
    "domainName": "...",
    "domainPrefix": "...",
    "http": {
      "method": "POST",
      "path": "/default/triggerAndroidBuild",
      "protocol": "HTTP/1.1",
      "sourceIp": "...",
      "userAgent": "Slackbot 1.0 (+https://api.slack.com/robots)"
    },
    "requestId": "...",
    "routeKey": "ANY /triggerAndroidBuild",
    "stage": "default",
    "time": "07/Jun/2022:08:00:05 +0000",
    "timeEpoch": 1654588805616
  },
  "body": "dG9rZW49NTRQZ1Z0d2NYMFBad29JQnh5cGNxaHJJJnRlY...hZjBj",
  "isBase64Encoded": true
}
```

We are mainly concerned with the **body** given to us. It will always be **Encoded with Base64.** All you need to do is decode the string and you will get all the information that you may require.

To understand what is stored in the body, refer to [this](https://api.slack.com/interactivity/slash-commands#app_command_handling).

**Source code**

1. Import *aws-sdk* in the lambda to use it and setup the CodeBuild config according to your needs. Refer to [AWS CodeBuild Request Syntax](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html).
    
    ```javascript
    // index.js
    const AWS = require("aws-sdk");
    
    const codebuild = new AWS.CodeBuild();
      const branch = data.hasOwnProperty("branch") ? 
        data["branch"] : "develop";
      const flutter_branch = data.hasOwnProperty("flutter_branch")
        ? data["flutter_branch"]
        : "develop";
      const build = {
        projectName: "android-app",
        sourceVersion: branch,
        environmentVariablesOverride: [
          {
            name: "VARIANT_TYPE" /* required */,
            value: build_variant /* required */,
            type: "PLAINTEXT",
          },
          {
            name: "BRANCH",
            value: branch,
            type: "PLAINTEXT",
          },
          {
            name: "FLUTTER_BRANCH",
            value: flutter_branch,
            type: "PLAINTEXT",
          },
          {
            name: "TRIGGER_USER",
            value: url.searchParams.get("user_id"),
            type: "PLAINTEXT",
          },
          {
            name: "TRIGGER_USER_REF",
            value: url.searchParams.get("user_name"),
            type: "PLAINTEXT",
          },
        ],
        cacheOverride: {
          type: "LOCAL",
          modes: [
            "LOCAL_CUSTOM_CACHE",
            "LOCAL_DOCKER_LAYER_CACHE",
            "LOCAL_SOURCE_CACHE",
          ],
        },
        gitSubmodulesConfigOverride: {
          fetchSubmodules: false /* required */,
        },
        buildspecOverride: `{version: 0.2, ...`,
      };
    ```
    
    **Note:** We have added the buildspec required by the CodeBuild in this config itself. You may add it in the AWS console or in the source files as [**buildspec.yml**](https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html).
    
2. Build the application using this small snippet. Once the build is successfully triggered, we can use the **callback** function to send a message back to Slack where the command was triggered from.
    
    ```javascript
    // index.js
    
    try {
        const result = await codebuild.startBuild(build).promise();
        callback(undefined, {
          statusCode,
          body: ":white_check_mark: Success! triggering build for android-app.",
          headers,
        });
      } catch (err) {
        callback(undefined, {
          statusCode,
          body: `:warning: Error! ${err.message}.`,
          headers,
        });
      }
    ```
    
    **Note:** You may use this **callback** function for command validation as well.
    

#### Setup Notification Lambda

We will need an Amazon Simple Notification Service (SNS) as the trigger. The SNS will be created later in the [**CodeBuild**](/3710776de76f47a0b0571245bb764771#bf6e94e80d4e446989d8405b79baf601) section.

**Request Schema**

```json
{
  "Records": [
    {
      "EventSource": "aws:sns",
      "EventVersion": "1.0",
      "EventSubscriptionArn": "...",
      "Sns": {
        "Type": "Notification",
        "MessageId": "fa556e61-3b73-5f7c-b93d-357acabcb9eb",
        "TopicArn": "arn:aws:sns:ap-south-1:289014830182:codebuild-slack",
        "Subject": "None",
        "Message": "{\"account\":\"...\",\"detailType\":\"CodeBuild Build State Change\",\"region\":\"ap-south-1\",\"source\":\"aws.codebuild\",\"time\":\"2022-06-09T13:03:04Z\",...,\"additionalAttributes\":{}}",
        "Timestamp": "2022-06-09T13:03:11.226Z",
        "SignatureVersion": "1",
        "Signature": "DcgduZ8N2tyXh1ioMQNpah4m3/dol2...tEQ==",
        "SigningCertUrl": "https://sns.ap-south-1.amazonaws.com/....pem",
        "UnsubscribeUrl": "https://sns.ap-south-1.amazonaws.com/...",
        "MessageAttributes": {}
      }
    }
  ]
}
```

You will find all the CodeBuild Information in the **“Message”** section of the request. The Message section will be encoded in JSON string, so you will have to decode it before using any data.

The **Message section** will look like [this](https://docs.aws.amazon.com/codebuild/latest/userguide/sample-build-notifications.html#sample-build-notifications-ref).

**Algorithm**

1. Convert the **Message** from JSON string to Object
    
2. Format the message that you need to send to Slack using the details provided in the message. You may learn more about formatting from [here](https://api.slack.com/reference/surfaces/formatting).
    
3. Use the **Incoming Webhook** to send a **POST** request with the *formatted message as body*.
    

### Setup CodeBuild

You will need a S3 bucket to store the artifacts produced by the CodeBuild. Refer to [AWS user guide for creating bucket.](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html)

#### Configure Source

We used **GitHub** as our source. You may find other options such as:

* Amazon S3
    
* CodeCommit
    
* Bitbucket
    
* GitHub Enterprise Server
    

It’s very simple to authenticate - you just need to use the **OAuth** provided by the AWS console and login to GitHub. The cloning of the repository will be handled by CodeBuild *(to be more specific CodeStarSourceConnection)*.

#### Configure Artifacts

Below is the simple configuration to achieve pushing the Build Artifacts on Amazon S3.

![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F65379580-abcd-432f-829b-9f5709e10ae2%2FUntitled.png?table=block&id=fc6fdcb2-61cd-47bc-a461-d20789fe1815&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")

**Note:** Each config mentioned above matches with those of AWS CloudFormation and are all documented [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-artifacts.html) by AWS.

### Configure Amazon Simple Notification Service (SNS)

![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F376eb022-26e3-4118-b0f3-368236f23064%2FUntitled.png?table=block&id=580b56be-8be4-4e15-aa76-ba9e09c57fad&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")

1. **Create a SNS topic**. You may refer to this [AWS Documentation](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html#create-topic-aws-console). Once you have created the SNS, you should add the **Notifcation Lambda** as a subscriber
    
2. Hover on **Notify** and click on **Manage notification rule**
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F0cfbe27f-4c0a-41b7-893a-5907d9001a5d%2FUntitled.png?table=block&id=00963e71-70d0-4317-8a7a-5e2f822c47a1&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    
    You will be redirected to this page. Here, we already have a notification rule setup but if you don’t, click on **Create notification rule.**
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fd02b2bc2-7f78-4090-bbb4-3e191c25569a%2FUntitled.png?table=block&id=574db8b6-2897-45c8-951a-396241ffc948&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    
3. This will send you to the page below.
    
    1. Enter whatever name you may seem fit
        
    2. Choose detail type Full or Basic according to your needs. You may learn more about the notifications [here](https://docs.aws.amazon.com/codebuild/latest/userguide/sample-build-notifications.html).
        
    3. Choose a trigger according to your need. We have chosen **Failed** and **Succeeded** to get notifications when the build has failed or successfully finished building.
        
    4. In the **Targets** section you may select the SNS that you just created
        
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc3c5bd25-9f67-4eaf-9d26-19176c500b81%2FUntitled.png?table=block&id=817db581-a93f-4303-a9cd-cf052b0b373a&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    
    ![](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F3728a499-2b26-4e51-ae30-ca7a74f0c2c6%2FUntitled.png?table=block&id=4d72e4a5-d6fc-43f2-a90f-836b1fad04a3&spaceId=f370e646-8657-43d5-9288-cf00f03fb9e4&width=2000&userId=770b7e48-dc33-4b9a-854a-917ec260e8bd&cache=v2 align="left")
    
    **Note:** You may refer to any of the [following](https://docs.aws.amazon.com/codebuild/latest/userguide/create-project.html) to create a CodeBuild build.
    

## Conclusion

With this you can now add the bot to your slack workspace and experiment with the command that you just created.
