Provisioning, CI Environment, Deployments and Automated Testing

In this post I explain the overall strategy I had for provisioning instances, performing deployments and automated testing that I had incorporated for FaxDroid. The image below shows the overall architecture and in the sections that follow I explain each part in detail.

 


Provisioning

FaxDroid servers are built on EC2 instances. For the service to work certain applications need to be preinstalled on the instances. Examples include:

The actual provisioning is done using Ansible. Once complete an image is taken from the instance and a new LaunchTemplate revision is made. This LaunchTemplate is later used by the AutoScaling group to launch new EC2 instances.


Deployments

Deployments are handled by the CI environment (Jenkins). Deployments occur in two cases:

  • When deploying code changes to the QA environment for testing
  • When releasing changes to prod.

The deployment process is identical for both environments. During deployment different events occur. These events are explained below:

CloudFormation: FaxDroid’s infrastructure is built using CloudFormation. In the first phase of deployment CloudFormation scripts are run to perform any new updates to the infrastructure. Infrastructure as code (IaC) greatly helps create reproducible environments and prevents unexpected issues when going to production.

Flyway: Flyway is a database migration tool. It allows database migrations to be brought under version control. Similar to IaC, version controlling databases helps create reproducible environments and removes the requirement for manual changes when deploying to production. In this phase flyway scripts are run to update the database. These changes are backwards compatible to prevent things from breaking while the source code has not updated yet.

Server Code Deployment: FaxDroid servers run on PHP using Symfony (with a REST based architecture). In order to deploy code changes to production the source code is first compiled using Symfony specific command lines. After which a CodeDeploy bundle is generated and uploaded to S3. The bundle also includes an AppSpec file with AfterInsall hooks in place to warm up the instance before allowing traffic. In the end the code is deployed using CodeDeploy.

Front End Code Deployment: The front end code is written using Angular IO. The code is first compiled to be production ready. This generates many JS bundles. The bundles are all uploaded to S3 and a caching policy is applied to the keys. Finally the CloudFront distribution is updated to serve the newly uploaded files. To learn more about the front end deployment process please see Angular Server Side Rendering with Lambda@Edge and CloudFront.


Testing

For testing FaxDroid has four different layers. The first two tests (Unit and Functional) would be run directly on the CI server. The next two tests (Selenium Local and Remote) would run on the CI server testing the QA environment which is deployed in a separate AWS account from production. Details explained below:

Symfony (PHP) Unit Tests: Simple tests that would test small parts of the code in isolation. These tests were most helpful for areas of code that had heavy business logic. As an example FaxDroid initially had very complicated business logic in the billing service (however this was later simplifed). Different pricing/free trials where offered depending on factors such as:

  • Where you are connecting from
  • Where the fax is going to
  • Is this a guest fax? Registered account? Or subscription?

These would vary the number of free faxes, free pages in a fax and the price of the fax. As you could imagine there were many different branches that would need to be covered and these tests provided a lot of value there.

Symfony (PHP) Functional Tests: These tests would test the system the way the front end would make REST calls to the server. Basically they emulate the same API calls made from the client. The majority of FaxDroid’s back end tests were written this way.

Selenium Local Chrome Tests: The best way to know if your code works is by testing it the same way customers would use it. This means running tests directly on the web interface and ensuring everything is working as expected. These tests were run on a headless chrome browser on the CI server connecting to the QA environment.

SauceLabs Remote Selenium Tests: Front end can be complicated. Unlike server side code that once you’ve tested on the QA environment you can be (to a good extend) confident it will work in prod, with front end code it is not that simple. When developing and testing you might be using a wide screen chrome browser. There is no guarantee the same code will work a safari browser on an iPhone 8. This is were remote selenium tests come into play. Services such as SauceLabs provided device farms you can lease to run selenium tests. This helps in ensuring the UI will work correctly on all devices.

 

 

 

Description

Provisioning, CI Environments, Deployments and Automated Testing.

Skills:

  • Jenkins
  • Ansible
  • Selenium
  • Flyway
  • AWS CodeDeploy
  • AWS CloudFormation