Skip to content

Instantly share code, notes, and snippets.

@Abdallatif
Created May 11, 2022 21:55
Show Gist options
  • Save Abdallatif/573d10c14dffb5f8093edce7b9480c4f to your computer and use it in GitHub Desktop.
Save Abdallatif/573d10c14dffb5f8093edce7b9480c4f to your computer and use it in GitHub Desktop.
AWS Amplify Previews Discord Bot

Send Amplify previews build notifications to a discord channel.

Inspired by https://dev.to/aws-builders/enable-slack-notifications-for-aws-amplify-deployments-5a0l

You should probably read the article above and follow it. I added a few enhancments on the code - get more details on the PR and related JIRA ticket.

const https = require('https')

// Update this to be sent as Authorization header for bitbucket
const Authorization = "Basic 123"

const options = {
  host: 'discord.com',
  port: 443,
  path: '/api/webhooks/{webhookId}/{webhookToken}',
  headers: { 'Content-Type': 'application/json' },
  method: 'POST'
};

exports.handler = async (event) => {
    const message = event.Records[0].Sns.Message
    
    const msgType = getMsgType(message)
    if (!["success", "failed"].includes(msgType)) {
        return;
    }
    
    const buildUrl = getBuildLink(message)
    const prNumber = getPRNumber(message)
    if (!prNumber) {
        return;
    }

    const prDetails = await getPRDetails(prNumber)
    const prTitle = prDetails.title ?? ""
    const author = prDetails.author?.display_name ?? ""
    const prLink = prDetails.links?.html?.href ?? ""
    const ticketLink = getTicketLink(prDetails.rendered?.title?.html ?? "")

    return await 
        requestAsync(options, {
            username: "AWS Build Bot",
            avatar_url: "Bot avatar url",
            content : `Build ${msgType} for pull request: ${prTitle}`,
            embeds: [{
                title: "Build info",
                url: buildUrl,
                description: `Deployed at: ${buildUrl}`,
                fields: [
                    {
                        name: "Ticket",
                        value: ticketLink,
                        inline: true
                    },
                    {
                        name: "Author",
                        value: author,
                    },
                    {
                        name: "PR Link",
                        value: prLink
                    }
                ]
            }]
        })
            .then((data) => console.log(data))
            .catch((e) => console.error(e.response.data))
}

function getMsgType(msg) {
    if (typeof msg !== "string") {
        return "invalid"
    }
    if (msg.includes("Your build status is STARTED")) {
        return "start"
    }
    if (msg.includes("Your build status is SUCCEED")) {
        return "success"
    }
    if (msg.includes("Your build status is FAILED")) {
        return "failed"
    }
    return "unkown"
}

function getPRNumber(msg) {
    return /pr-(\d+)/.exec(msg)[1]
}

function getTicketLink(html) {
    return /https:\/\/.*\.atlassian\.net\/browse\/\c+-\d+/.exec(html)[0]
}

function getBuildLink(msg) {
    return /https:\/\/pr-\d+\..*amplifyapp\.com/.exec(msg)[0]
}

async function getPRDetails(prNumber) {
    const options = {
      host: 'api.bitbucket.org',
      port: 443,
      path: `/2.0/repositories/.*/portal/pullrequests/${prNumber}`,
      'method': 'GET',
      'headers': {
        'Authorization': Authorization,
        'Accept': 'application/json'
      }
    };
    const res = await requestAsync(options)
    return JSON.parse(res)
}

async function requestAsync(options, payload) {
    const data = new TextEncoder().encode(JSON.stringify(payload))

    return new Promise((resolve, reject) => {
        const post_req = https.request(options, (res) => {
            res.setEncoding('utf8');
            let str = ""
            res.on('data', (chunk) => {
                str+=chunk;
            });
            res.on('end', () => {
                resolve(str)
            })
            res.on("error", (err) => {
                reject(err);
            });
        });
        if (payload) {
            post_req.write(data);
        }
        post_req.end();
    });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment