Automating Angular.js Builds and Deployments from Github to S3 Buckets with CodeBuild

I enjoy automated builds and deployments so when AWS released CodeBuild I was filled with joy. Today, we are going to automate Angular.js builds and deployments. Every time we merge changes to the master branch, our CodeBuild is going do a lot of heavy lifting for us. CodeBuild will download the application from the Github repository and run build commands that will generate a distribution folder that will have the production ready application contents. Then the contents of the distribution folder will be deployed to an S3 bucket.

Bootstrapping an Application

I'm going to bootstrap a generic Angular.js application using the Angular.js Yeoman Generator and than push the application to my Github repository:
yo angular helloAngularCodeBuild
cd helloAngularCodeBuild && git add . && git push origin master
This stuff should be pretty self explanatory .

Creating an S3 Bucket

The application is going to be hosted in an S3 bucket. Navigate to Amazon -> S3 and create a bucket in the Oregon region. We want to have both the S3 bucket and the CodeBuild in the same region for optimal performance .

We are now going to need to set the S3 bucket configurations. The bucket needs be static site enabled and the index document needs to be set to index.html .

Add a bucket policy that will allow outside access to the bucket.



I added the policy below for convenience. Make sure to replace examplebucket/* with the name of your S3 bucket.

{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"AddPerm",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::examplebucket/*"]
    }
  ]
}

AWS CodeBuild

This is the meat of the whole process. CodeBuild needs to be configured to run build operations on the application and deploy it. It needs to run grunt build to build the application and then it needs to sync the contents of our build to the S3 bucket.

Creating a Project

Navigate to AWS->CodeBuild and create a new project. Make sure that you are creating the project in the same region as the S3 bucket. Set the source provider to Github and set the Github link as the application repository. Then set the environment to be managed by AWS, operating system Ubuntu, runtime Node.js and select your particular Node.js version.

Build Command

CodeBuild can execute build commands in 2 way. You can add a buildspec.yml to the root of the project or you can specify the build commands in the CodeBuild project setting page. The former can be used to run different commands during different stages of the build process. The latter will run commands only during the build stage. For our particular case, we do not need a buildspec.yml . Lets add the following line to the build command option in the CodeBuild settings page:

sudo apt-get update && sudo apt-get install -y ruby ruby-dev && apt-get clean && sudo gem install compass && sudo npm install && sudo npm install grunt-cli && sudo npm install bower && sudo ./node_modules/bower/bin/bower install --allow-root && sudo ./node_modules/grunt-cli/bin/grunt build && aws s3 sync ./dist s3://hellodeploy  


The command line looks pretty complex so lets break it down.


The Angular.js application requires Compass and SASS which means we need to add Ruby to our environment. Then we use the Ruby Gems to install Compass.

sudo apt-get update && sudo apt-get install -y ruby ruby-dev && apt-get clean && sudo gem install compass  

This command installs the build tools and frontend dependencies management tools.

sudo npm install && sudo npm install grunt-cli && sudo npm install bower && sudo ./node_modules/bower/bin/bower install --allow-root  

Now we are building our awesome application .

./node_modules/grunt-cli/bin/grunt build

Finally, we are syncing our build contents with our S3 bucket. AWS CLI is already installed on the AWS managed server so we do not need to install it. If you look into the S3 bucket you should see your built application.

Make sure to change the S3 bucket name to your S3 bucket name.

aws s3 sync ./dist s3://helloangularjscodebuild  


Output Artifacts

AWS CodePipeline requires an output artifact from the CodeBuild. The artifact directory should contain a copy of the ./dist directory. If the build fails for any reason the ./dist directory will not be created and the whole build will gracefully fail. Notice I'm using the same directory as the application, but the output artifacts directory is _. The artifact output files need to be globs separated by a commas./dist/*, ./dist/**/*.


AWS CodePipeLine

Good work for getting this far. The application is building and the contents should be syncing to our S3 bucket. Now we need to automate this process.
Navigate to AWS -> CodePipeLine and create an new project.

Set your Github as the source provider and link the application repository.

Set your CodeBuild as the build provider and input your CodeBuild project.

Then set No Deployment Provider because our CodeBuild is going to do the deployment for us.

Review and create the pipeline.

Now run your first release

The application should have been pulled from Github, built and deployed to the S3 bucket by CodeBuild.

Enjoy*!

If you get lost any where along the process feel free to shoot me a tweet. @notmilobejda.