Nonstop API

Deployment

Cake

The API and Admin use the open source CakeBuild project to author their build script. CakeBuild allows developers to write their build script in C# which is compiled to either Powershell or Bash using the cross-platform .NET compiler.

build.cake contains the definitions of the tasks which are executed as part of the build. build.ps1 or build.sh are the scripts which are executed to perform the build.

e.g.

    ./build.ps1 -Target Docker -Verbosity Diagnostic

Tasks

  • Clean - clears the output artifacts directory
  • Restore-NuGet-Packages - Fetches the NuGet packages for the Admin and Client APIs
  • Create-Version-Info - Creates two empty files which will house the version information for the build
  • Update-Version-Info - Runs GitVersion the determine the current version of the API based on it's git history and git tags. Then writes this information into the files created during Create-Version-Info so that when the project is built later in the process it's able to encode this information into the binary.
  • Update-AppVeyor-Build-Number - see AppVeyor. Sets the AppVeyor build number in line with the previously determined version.
  • Run-Tests - runs the tests defined for the Admin and Client APIs and reports any results as an AppVeyor artifact
  • Publish-Admin-API-For-Windows - Runs dotnet publish to create a folder containing the files required to run the Admin API in a Windows environment
  • Publish-Admin-API-For-Linux - Runs dotnet publish to create a folder containing the files required to run the Admin API in a Linux environment
  • Publish-Public-API-For-Windows - As above for the Public API
  • Publish-Public-API-For-Linux - As above for the Public API
  • Publish-WebJob - publishes the background service for a Windows environment
  • Restore-NPM-Packages - uses Yarn to install the npm packages required for the Admin Client
  • Build-Admin-Project - uses the Angular CLI to compile the Admin Client and combine it with some web server configuration files in an output directory
  • Create-Admin-API-Deploy-Package - zips the Admin API output folder containing the built assets for Windows
  • Create-Admin-API-Docker-Image - creates a Linux Docker Image to run the Admin API from the built assets for Linux
  • Create-Public-API-Deploy-Package - as above for the Public API
  • Create-Public-API-Docker-Image - as above for the Public API
  • Create-Admin-Deploy-Package - zips the Admin output folder containing the output from the Angular CLI build
  • Create-Admin-Docker-Image - as above for the Admin Client
  • Create-WebJob-Deploy-Package - as above for the WebJob/background service
  • Docker - aggregate task which runs all of the required tasks above to generate 3 docker files - one for the Public API, one for the Admin API and one for the Admin Front End
  • Default - aggregate task which runs all of the required tasks above to generate 3 zip files for running the application components under IIS/Microsoft Azure App Service

AppVeyor

The CI system AppVeyor is used to build the project and store any artifacts. The CI script simply executes:

    ./build.ps1 -Verbosity Diagnostic

and stores the test results and the resultant zip files.

These artifacts can then be deployed using AppVeyor's concept of environments.

There is an AppVeyor Environment for each component of the system i.e. one for the Public API website, one for the Admin API website and one for the Admin client website. Additionally, due to the architecture of the system having two globally redundant regions when deployed there is an additional AppVeyor environment for each region (currently East US and West US).

Each environment allows any valid artifact produced during the build phase to be deployed to it. Currently, artifacts are not auto-deployed to any environment, however, as the suite of automated tests for the application improves we will be looking to introduce more Continuous Delivery process to this.

Manual deployment steps currently consist of:

  • selecting the correct environment which should be deployed to
  • selecting the correct artifact which should be deployed
  • waiting for the system to confirm the correct deployment

Automatic deployment recording is via Slack notifications. NewRelic deployment recording is currently in the product backlog.

Azure

Configuration

Configuration is managed via the use of Azure App Service App Settings. These allow configuration to be set dynamically in the Azure portal and applied to the deployed website without the need to update a config file locally and deploy.

Hot-swapping

In order to minimize downtime during deployments to Production we make use of Azure App Service Deployment Slots. When deploying to production, therefore, the process is:

  1. Update Failover/East-US website
  2. Smoke test failover site
  3. Update Release Candidate Deployment Swap and initialize a "Swap with preview". This makes the new code available on a separate URL with all of the production settings applied to it. This website is then available to be tested and "warmed up" so that when it starts receiving the production traffic, it doesn't need to go through a "cold start" process.
  4. Smoke test release candidate slot, ensuring that site responds quickly by the end of the smoke test.
  5. Complete the swap to production
  6. Test production
  7. Post launch hypercare for any issues

If any issues are found during step 4, then it is possible to abort the deployment and not proceed with the swap.

This process allows us the ability to both test the website in its final form with its production settings without affecting the production traffic. Additionally the "warming" of the site minimizes any slowness as the deployment rolls out.

Database Migrations

The project contains a console app which performs the database migrations. At present, these are not executed as part of the CI pipeline, however, this is on our roadmap. Performing migrations currently is a case of updating the connection string for the Migrator console app and running it against the correct database using the correct version of the code.

In this document