NB: this approach is no longer required as CodeBuild now supports badges natively. See Build badges sample with CodeBuild in the AWS docs.

Most build systems have a built-in method of producing status badges or a plugin that will create them. With CodeBuild, we can use CloudWatch Events and a Lambda function to generate a badge when our build succeeds or fails, upload it to S3 and then display it in our README.

To get started, the following JSON is a shortened example of a CloudWatch event for a CodeBuild job that failed to run. I’ve removed the “additional-information” section but we can still see the job that it relates to and also the overall status.

{
  "version": "0",
  "id": "ad70013b-ccb2-41ac-fffb-346b3ad27940",
  "detail-type": "CodeBuild Build State Change",
  "source": "aws.codebuild",
  "account": "000000000000",
  "time": "2017-11-06T19:11:15Z",
  "region": "eu-west-1",
  "resources": [
    "arn:aws:codebuild:eu-west-1:000000000000:build/website-frontend:f4a667e4-6b52-4863-9a03-9440dbade2c0"
  ],
  "detail": {
    "build-status": "FAILED",
    "project-name": "website-frontend",
    "build-id": "arn:aws:codebuild:eu-west-1:000000000000:build/website-frontend:f4a667e4-6b52-4863-9a03-9440dbade2c0",
    "additional-information": {
        "...": "..."
    },
    "current-phase": "COMPLETED",
    "current-phase-context": "[]",
    "version": "1"
  }
}

We can write a Lambda function that will parse this information out and then use badges generated by the excellent shields website, upload them to S3 and display them on our project’s README.

To save you having to create the Lambda function, I’ve made one that can be found on GitHub.

Stage 1 - Creating an S3 bucket for the badges

  1. Head to the S3 Dashboard.

  2. Hit “Create bucket” and follow the instructions in the wizard, ensuring that on the “Set permissions” page you choose “Grant public read access to this bucket” under “Manage public permissions”.

  3. Note down the name of the bucket as you’ll need it in the next stage.

Stage 2 - Creating the Lambda function

  1. Head to the AWS Lambda Dashboard.

  2. Hit the “Create Function” button and then choose “Author from scratch” on the right hand side.

  3. Choose a name for your function and in the role selection, select “Create a custom role”.

  4. In the new window that appears, enter a name for your role and then click “Show Policy Document” to display the default Lambda function policy. Click the “Edit” link to the side and enter the following policy. It’s the same as the default, with an added permission to put badges into our bucket.

    NB: Ensure you replace the BUCKET_NAME with the name of your bucket.

     {
         "Version": "2012-10-17",
         "Statement": [
             {
                 "Sid": "AllowLoggingToCloudWatch",
                 "Effect": "Allow",
                 "Action": [
                     "logs:CreateLogGroup",
                     "logs:CreateLogStream",
                     "logs:PutLogEvents"
                 ],
                 "Resource": "arn:aws:logs:*:*:*"
             },
             {
                 "Sid": "AllowUploadingBadges",
                 "Effect": "Allow",
                 "Action": [
                     "s3:PutObject",
                     "s3:PutObjectAcl"
                 ],
                 "Resource": [
                     "arn:aws:s3:::BUCKET_NAME/*"
                 ]
             }
         ]
     }
    
  5. After entering the policy and creating the role, select it on the Lambda creation wizard and click “Create Function”.

  6. Download the latest release of the Lambda function.

  7. If you want to change the badges at this stage, you can unzip the release, edit the images and then re-upload it.

    Check out shields.io for an easy way to generate badges.

  8. Back on the Lambda page, choose “Upload a .ZIP file” for the “Code entry type”, “Node.js 6.10” for the “Runtime”, “index.handler” for the “Handler” and then click “Upload”.

  9. Select the release that you just downloaded and then expand the “Environment variables” section.

    You’ll need to create one with the key of BUCKET and the value as the bucket name from Stage 1.

    Once you’ve done this, hit “Save” at the top of the page.

Stage 3 - Setting up CloudWatch

  1. Head to the CloudWatch Dashboard.

  2. Choose “Events” on the left hand side.

  3. Click “Create rule”.

  4. For the “Service Name” and “Event Type” choose “CodeBuild” and “CodeBuild Build State Change”.

  5. Under “Targets”, select “Add target” and choose your Lambda function in the dropdown list.

  6. At the bottom of the page, click “Configure details”.

  7. Enter a name for your rule and click “Create rule”.

Testing it out

Run any of your CodeBuild jobs and check the S3 bucket. If everything has worked, you’ll see an SVG appear with the project’s name, for example “website-frontend.svg”. You can link to this in your project’s README or other documentation.

Happy building!

What about CodePipeline?

If you’re using AWS CodePipeline instead of CodeBuild, you can select the “Service Name” of “CodePipeline” and the “Event Type” of “CodePipeline Pipeline Execution State Change” when creating the CloudWatch event. The Lambda function will work without modification.