|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +const AWS = require('aws-sdk'); |
| 4 | +const codebuild = new AWS.CodeBuild(); |
| 5 | +const cloudwatchlogs = new AWS.CloudWatchLogs(); |
| 6 | +const ses = new AWS.SES(); |
| 7 | +const sourceEmailAddress = process.env.sourceEmailAddress; |
| 8 | +const destinationEmailAddress = process.env.destinationEmailAddress; |
| 9 | + |
| 10 | +function sendBuildEmail(subject, htmlBody, textBody, callback) { |
| 11 | + console.log(subject); |
| 12 | + console.log(htmlBody); |
| 13 | + console.log(textBody); |
| 14 | + |
| 15 | + var emailParams = { |
| 16 | + Source: sourceEmailAddress, |
| 17 | + Destination: { |
| 18 | + ToAddresses: [destinationEmailAddress] |
| 19 | + }, |
| 20 | + Message: { |
| 21 | + Body: { |
| 22 | + Text: { |
| 23 | + Data: textBody |
| 24 | + }, |
| 25 | + Html: { |
| 26 | + Data: htmlBody |
| 27 | + } |
| 28 | + }, |
| 29 | + Subject: { |
| 30 | + Data: subject |
| 31 | + } |
| 32 | + } |
| 33 | + }; |
| 34 | + |
| 35 | + ses.sendEmail(emailParams, function(err, data){ |
| 36 | + if(err) { |
| 37 | + return callback(err); |
| 38 | + } else { |
| 39 | + return callback(null, "Email sent"); |
| 40 | + } |
| 41 | + }); |
| 42 | +} |
| 43 | + |
| 44 | +function handleBuildEvent(event, callback) { |
| 45 | + const buildStatus = event.detail['build-status']; |
| 46 | + |
| 47 | + if (buildStatus != 'IN_PROGRESS') { |
| 48 | + const buildArn = event.detail['build-id']; |
| 49 | + const buildId = buildArn.split('/').pop(); |
| 50 | + const buildUuid = buildId.split(':').pop(); |
| 51 | + const sourceUrl = event.detail['additional-information'].source.location; |
| 52 | + const repoName = sourceUrl.split('/').pop(); |
| 53 | + const projectName = event.detail['project-name']; |
| 54 | + const region = event.region; |
| 55 | + |
| 56 | + // Construct email content based on build status |
| 57 | + var subject = `Nightly ${projectName} build `; |
| 58 | + var htmlBody = `Build ${buildUuid} for project ${projectName} `; |
| 59 | + var textBody = htmlBody; |
| 60 | + |
| 61 | + switch (buildStatus) { |
| 62 | + case 'SUCCEEDED': |
| 63 | + subject += "succeeded"; |
| 64 | + textBody += "succeeded"; |
| 65 | + htmlBody += "<b>succeeded!</b>"; |
| 66 | + break; |
| 67 | + case 'STOPPED': |
| 68 | + subject += "was canceled"; |
| 69 | + textBody += "was canceled"; |
| 70 | + htmlBody += "was <b>canceled</b>."; |
| 71 | + break; |
| 72 | + case 'TIMED_OUT': |
| 73 | + subject += "timed out"; |
| 74 | + textBody += "timed out"; |
| 75 | + htmlBody += "<b>timed out</b>."; |
| 76 | + break; |
| 77 | + default: |
| 78 | + subject += "failed"; |
| 79 | + textBody += "failed"; |
| 80 | + htmlBody += "<b>failed</b>."; |
| 81 | + } |
| 82 | + |
| 83 | + htmlBody += ` Visit the <a href=\"https:\/\/${region}.console.aws.amazon.com\/codebuild\/home?` + |
| 84 | + `region=${region}#\/builds\/${encodeURI(buildId)}\/view\/new\">AWS CodeBuild console</a> to view the build details.`; |
| 85 | + |
| 86 | + textBody += ` Visit the AWS CodeBuild console to view the build details: https:\/\/${region}.console.aws.amazon.com\/codebuild\/home?` + |
| 87 | + `region=${region}#\/builds\/${encodeURI(buildId)}\/view\/new`; |
| 88 | + |
| 89 | + // Add build logs snippet to the body |
| 90 | + if (buildStatus != 'SUCCEEDED' && |
| 91 | + buildStatus != 'STOPPED' && |
| 92 | + event.detail['additional-information'].logs && |
| 93 | + event.detail['additional-information'].logs['stream-name'] && |
| 94 | + event.detail['additional-information'].logs['group-name']) { |
| 95 | + |
| 96 | + var logParams = { |
| 97 | + logGroupName: event.detail['additional-information'].logs['group-name'], |
| 98 | + logStreamName: event.detail['additional-information'].logs['stream-name'], |
| 99 | + limit: 30, |
| 100 | + startFromHead: false |
| 101 | + }; |
| 102 | + cloudwatchlogs.getLogEvents(logParams, function(err, data) { |
| 103 | + if (err) { |
| 104 | + // an error occurred, ignore and send the email without the logs |
| 105 | + console.log(err, err.stack); |
| 106 | + } else { |
| 107 | + var logLines = data.events.map(function(event) { |
| 108 | + return event.message; |
| 109 | + }).join(""); |
| 110 | + htmlBody += "<br/><br/>Logs:<br/><br/><pre>" + logLines + "</pre><br/>"; |
| 111 | + textBody += "\n\nLogs:\n\n" + logLines + "\n\n"; |
| 112 | + } |
| 113 | + |
| 114 | + sendBuildEmail(subject, htmlBody, textBody, callback); |
| 115 | + }); |
| 116 | + } else { |
| 117 | + sendBuildEmail(subject, htmlBody, textBody, callback); |
| 118 | + } |
| 119 | + } else { |
| 120 | + callback("Not a completed build"); |
| 121 | + } |
| 122 | +} |
| 123 | + |
| 124 | +exports.handler = (event, context, callback) => { |
| 125 | + try { |
| 126 | + console.log(event); |
| 127 | + |
| 128 | + if (event.source && event.source == "aws.codebuild" && |
| 129 | + event['detail-type'] == "CodeBuild Build State Change") { |
| 130 | + handleBuildEvent(event, callback); |
| 131 | + } else { |
| 132 | + callback("Not a CodeBuild event"); |
| 133 | + } |
| 134 | + } catch (error) { |
| 135 | + console.log('Caught Error: ', error); |
| 136 | + callback(error); |
| 137 | + } |
| 138 | +}; |
0 commit comments