Continuous Deployment with Travis and AWS Elastic Beanstalk

Our problem

We, at TeraHorse, are willing to have full CI/CD environment and we started with our next product, the Fobit Game. To finish the Continuous Deployment implementation we need to tell Travis-CI to deploy our game at AWS Elastic Beanstalk. This can be done in at least 2 ways: Gradle or using the Travis-CI Elastic Beanstalk addon.

Gradle/Bash approach

We first defined a new task in Gradle, called “deployEb”:

task deployEb(type: Exec) {
    description 'Deploy this application on AWS, using Elastic Beanstalk.'
    doFirst {
        executable "sh"; args "-c", "eb deploy PROD"
    }
}

Then we can simply run

$ ./gradlew deployEb

This task will first run all dependencies to create a new docker image with the game and then will call the program eb. The tool eb is a CLI to do Elastic Beanstalk operations in AWS. Can be installed installing python, pip3 and awsebcli:

$ apt install python3-pip
$ pip install awsebcli --upgrade --user

To configure eb we must go to our app folder (the folder with .git) and run:

$ eb init

After typing some information (user, pass, application, region, etc), we can configure the autogenerated file .elasticbeanstalk/config.yml and do a simple call to deploy our app to AWS

$ eb deploy

Well, this works perfectly. The problem is that this is a local configuration and we want a Continuous Deployment environment, in a REMOTE server. Because of that, we decided to migrate these instructions to Travis-CI.

Travis-CI

Well, we tried some minutes to configure Travis-CI to reproduce the same steps. We’re even able to add new some dependencies in .travis.yml file using this:

 before_install:
 - pip install awsebcli --upgrade --user

The problem is that this becomes too complex and we a did Google search and realize that Travis already has a plugin to deploy in AWS Elastic Beanstalk automatically. So, we ignored all Gradle stuff and simply follow the instructions of Travis.

We are using a public build in Travis and don’t want to expose our personal AWS credentials, of course. So, we tried to use the travis encrypt command to cipher our AWS keys. But this command is not working in our machine. We installed ruby and many other dependencies and simply doesn’t work.

So, how can we run the Travis CLI? Docker came to save us!

Docker Solution

We created a very simple Docker image, defined in our GitHub. It’s simply an extension of Ubuntu 18.04, with Ruby, some build tools (GCC, Make, etc), Git and of course the Travis CLI. The first version of the Dockerfile is:

FROM ubuntu:18.04
MAINTAINER Rafael Topera
RUN apt update
RUN apt upgrade -y
RUN apt install ruby ruby-dev build-essential -y
RUN apt install git -y
RUN gem install travis

Then, we access DockerHub and configured and new (public) “Automated Build” project, here.

Done, now anyone on this planet can simply run one command to have our modified Ubuntu image with Travis CLI running inside:

$ docker pull topera/travis

Docker Usage

Now, we can easily download the docker image, run a new docker container from it and run any travis command inside it, including our command to obfuscate our passwords:

$ travis encrypt myKey=myValue -r topera/fobit

To see more details about this docker image, please take a look at our GitHub page.

Enjoy!

Update 1

The deploy with Travis-CI Elastic Beanstalk Plugin is not working well, maybe because it’s a beta feature. So, we decided to switch back to the Gradle/Bash solution.

One point is that we don’t need to store access key in the source code. We can define then as environment variables in Travis-CI, because the eb tool will read them first. The variables are AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

A second point is that this command works locally

$ eb deploy

But it was not working in Travis. We need to add the environment also, like this:

$ eb deploy PROD

Now the Continuous Deployment is working. To take a look in our configuration, please see our travis file.

Update 2

I realized that the eb cli tool is deprecated. It’s better to use aws cli tool.

This is a Gradle task that deploys to Elastic Beanstalk using aws cli. You just need to edit the variables 🙂

task deployEb(type: AWS) {
    description 'Deploys application in AWS Elastic Beanstalk'
    doFirst {
        run "aws configure set default.region $awsRegionName"
        run "aws s3 cp $buildDir/$jarLocal s3://$awsBucketName/$awsJar"
        run "aws elasticbeanstalk create-application-version --application-name=$awsAppName --version-label=$buildNumber --source-bundle S3Bucket=$awsBucketName,S3Key=$awsJar"
        run "aws elasticbeanstalk update-environment --environment-name=$awsEnvName --version-label=$buildNumber"
    }
}

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s