top of page
Search

Continuous Deployment

  • Writer: Kieran Mangan
    Kieran Mangan
  • Apr 2, 2023
  • 3 min read

Updated: Jun 14, 2023

The fastest and safest way to release code


Continuous Deployment is about pushing code through to a live environment as soon as it's merged into a master branch, without any further manual intervention. If this sounds scary, you've probably worked in places where manual and regression testing is an important part of the release process, even for server-side changes with no functional impact.


Are you sure this is safe?


It can be - if we think about how it could be possible to isolate and automatically test what we've changed. With the correct automated testing, it's not only possible enable Continuous Deployment for back-end components, it's actually the safest way to go.


Ok, so what's the 'correct' automated testing then?


To answer that question, let me introduce the Test Pyramid. Inside this pyramid are all the tests that a system needs. The idea is that any test that is needed is as far down the pyramid as possible. Tests at the bottom of the pyramid (like unit tests) are faster to run and easier to maintain, so we can afford lots of them. Tests towards the top are slower to run and harder to maintain (like web automation tests), so we should have less of them. The eye at the top of the pyramid signifies manual or exploratory testing, which is the slowest form of testing.




So the idea is - lots of easy and fast tests, and few hard and slow ones, work together to provide all the coverage we need for a service. For example, an endpoint that returns a paginated list of entities can mostly be tested at unit or integration level, and reams of pagination tests need not be found in a web automation suite.


This makes sense, so what kinds of tests would my service need?


For a 'typical' back-end service, everything in above pyramid's red box 🙂 Lets take a simple microservice as an example - an 'account-view' service, which provides some RESTful endpoints, and receives Kafka messages.


Unit tests: Obviously, any logic found in the code should have a unit test.


Integration tests: These can usually run at build time, and will spin up mock HTTP, Kafka and any mock database that's needed. Here, we are testing our service configuration, the security of our endpoints, and that HTTP operations return successfully and send the correct messages.


Contract tests: Every deployed service communicates with the outside world somehow, be it by HTTP or a messaging technology. If we think of the format of this communication being a 'contract' between two services, we can test that this contract has not been broken before deploying a service. In our 'account-view' example, the response body has some required fields. These fields help define the contract between this service and any other component that calls the endpoint (e.g. a front-end application). If one of these required fields is removed or renamed, the contract is broken and the test will fail, preventing the deployment from going ahead. The same principal applies for messaging technologies. There are multiple tools to help us with contract testing (e.g. Pact for HTTP and Avro for Kafka).


Feature tests: Once a service is deployed to a test environment, we need to make sure it works in conjunction with other deployed services. In our example we might first create an account before asserting we can get the account details. A feature test will call a 'create' endpoint and check the operation has completed successfully, by calling the 'get' endpoint. We know that a symphony of message must have occurred across services for this order to have been placed successfully, so we know everything is working as it should.


Ok that's great, but why do we even want to deploy to production every time there's a change?


Keeping changes as small as possible reduces risk by avoiding 'big bang' releases and keeping production and test environments in sync. It also allows any fixes to be applied more easily (as you never have to worry about releasing patch branches or reverting un-released changes to enable a fix).


Sounds great, we'll try this for some of our microservices!


Good luck! 🚀


 
 
 

Comments


© 2023 Kieran Mangan

bottom of page