Photo by Kaboompics .com from Pexels

Build and deploy with Travis CI and AWS S3

Travis CI is a website that allows you to implement many such features for free and links to repositories on GitHub. As an experiment, I used it to build and deploy my JavaScript application to an S3 bucket on AWS. S3 (which stands for “Simple Storage Service”) is Amazon’s service for static cloud storage, and in this case, allows other people access to my app over the internet.

This article describes the basic steps I followed to set up automated builds and deployments for my project with Travis CI and S3.

Travis CI links to GitHub, so if you do not already have a GitHub account, you will need to create one.

Go to travis-ci.org and click the “Sign in with GitHub” button. GitHub should prompt you for your credentials. The first time you do this, you will need to grant Travis CI certain permissions, such as accessing your repositories, commits, etc.

Once authorized, Travis CI will display a list of your repositories.

Travis CI settings page

Public repositories are immediately visible on travis-ci.org, whereas private repositories can be found on travis-ci.com. Click the slider next to the desired repository to enable builds for this repo.

If you’re going to deploy to AWS, you will need an AWS account. If you do not already have one, you can create one for free.

Once you’ve signed in to the AWS management console, navigate to the IAM service. Create a new user. Take note of the access key ID and secret access key (especially the latter, since you won’t be able to view it again). You will need these to set up the deployment. The secret key needs to remain secret, which is why you will encrypt it in a later step.

This user must have permission to write files to the S3 bucket. This can be achieved by adding them to a group that has the AmazonS3FullAccess policy attached. You can read more about access policies here.

Now, navigate to the S3 service. Create a new bucket, and take note of the name you give it. You don’t need versioning or any of the other fancy features.

If you want your bucket to be accessible to the public, you might find that this is not a trivial thing. As much as it’s possible to edit the bucket’s public access settings and unblock things, I found that as soon as new files are deployed to the bucket, Amazon automatically restricts them.

Block public access (bucket settings)

One way I could ensure public access to the bucket was by creating a policy for the bucket itself. Unfortunately, S3 choked on the output generated by the AWS policy generator, so I had to do some manual tweaking.

Essentially, you want a policy that allows the principal * (everyone) access to the action s3:GetObject (reading a file) for any resource prefixed with the bucket’s ARN, i.e. arn:aws:s3:::saratetra/*. For example:

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

Once you’ve made the necessary changes by hand, you can confirm that you’ve successfully granted public access to your bucket by looking for the orange “public” notice in S3:

Access: Public

Builds and deployments on Travis CI are configured by including a special YAML file named .travis.yml in the root of your repository on GitHub. Whenever you push your code, Travis CI looks for this file and kicks off a build based on its contents.

The .travis.yml file defines such things as the programming language and the scripts that need to be run. In my JavaScript project, I have set the build script to npm run build, and added a pre-build step to install Browserify:

language: node_js
before_script: npm install browserify -g
script: npm run build

Of course, you could do any number of things in this phase. The actual deployment steps are included in a deploy block, e.g.

deploy:
- provider: s3
access_key_id: "ACCESSKEYID"
secret_access_key: ""
bucket: "saratetra"
region: "us-west-2"
local_dir: "deploy"
skip_cleanup: true

The example above uses AWS S3 to deploy to the “saratetra” bucket in the region “us-west-2”. For the access_key_id property, use your IAM user’s access key ID. The optional local_dir setting can be used to specify a particular directory that contains the specific files you wish to deploy.

You don’t want to commit the secret access key to source control without encrypting it first (this is why I left this value empty above). In the next section, I explain how to encrypt settings in Travis CI.

Note: Depending on your project, the skip_cleanup flag above could be very important. Without it, the repository is scrubbed before deployment, which could eliminate some generated files you were hoping to deploy. 😒

Settings are encrypted using the Travis CLI, which is written in Ruby. You need to install Ruby before you can install the Travis CLI gem. If you’re on a Windows machine, you can do this using the Windows Subsystem for Linux (WLS).

Installing Ubuntu from the Microsoft Store

Should you choose to go down this road, you can install Ruby using the following command:

sudo apt-get install ruby ruby-dev

My installation didn’t work out-of-the-box, so I also tried installing the following dependencies:

sudo apt-get install gcc
sudo apt-get install make

In the end, I think it was make that did the trick.

To install the Travis CLI gem, use this command:

sudo gem install travis

Because the encryption is repository-dependent, your current working directory should be the one where your repository is located. That way, the tool can pick it up automatically. (Alternatively, you can use the -r switch to specify the repository as a command-line parameter). Remember that on WLS you can access your Windows file system under the /mnt directory.

sudo travis encrypt "abcd1234"

The command above encrypts the secret access key “abcd1234”. Note that I am passing only the value in the parameter to encrypt, not the name (as I have seen some sources mention). The result is a string like the following:

  secure: "encryptedabcd1234"

Copy and paste this entire string in your .travis.yml file, for the secret_access_key under the deploy block. This is where I had "" in my earlier example. For example:

deploy:
- provider: s3
access_key_id: "ACCESSKEYID"
secret_access_key:
secure: "encryptedabcd1234"
bucket: "Saratetra"
region: "us-west-2"

To save you a couple of trial-and-error commits, note that you can use the following command to have the Travis CLI validate your .travis.yml file offline:

travis lint .travis.yml

If you got all the steps right, the next time you push a change to your repo in GitHub, Travis CI will automatically start a new build, and finally deploy your artefacts to your S3 bucket in AWS.

  • Ubuntu 18.04.3 LTS
  • Ruby 2.5.1p57
  • Travis CLI 1.8.10
  • Visual Studio Code 1.38.1

Software developer walking the edge between legacy systems and modern technology. I also make music: https://soundcloud.com/stephanbester