CI/CD for REST API — Azure DevOps
By: Tiago Martins
Tags: Programming, Ci Cd Pipeline, Rest Api, DevOps, Azure

More and more we want automatic things. The operating processes that are always the same can be done autonomously following a set of steps. In the not too distant past, every time we want to deploy an application we build and copy those generated files to the server. So we need to have remote access to a server machine, we need to know which files need to be copied, where we should put them, and which other multiple services must be restarted. I’m tired of just describing this process.

The CI/CD principle, which means Continuous Integration and Continuous Delivery or Continuous Deployment, provides an agile method to enable a development team to deliver code changes more frequently and reliably to their clients.

CI/CD pipeline

Continuous Integration

There are some steps before anything merges to the master branch. Build the application guarantees that there aren’t syntax errors or build errors. Run all the existing unit tests to check if all are passing. If everything is ok, the pipeline will merge the code to the master.

Continuous Delivery

Ensure that is a version always ready to be deployed in a production environment.

Continuous Deployment

The last step for a consistent CI/CD pipeline is the deployment of the application. This is one step further than continuous delivery. Every time a new version is merged to master will trigger a new deployment process.

REST API with CI/CD in Azure DevOps

There are many tools to implement this type of agile CI/CD pipeline. For this example, I will use Azure DevOps.

Setup your build pipeline

I decided to create my pipeline using YAML. Let’s see the file:

trigger:

- master pool:

vmImage: 'windows-latest' variables:

solution: '**/WebAPI.csproj'

buildPlatform: 'Any CPU'

buildConfiguration: 'Release' steps:

- task: NuGetToolInstaller@1 - task: DotNetCoreCLI@2

displayName: Restore

inputs:

command: 'restore'

projects: '$(solution)' - task: DotNetCoreCLI@2

displayName: Build

inputs:

command: build

projects: '$(solution)'

arguments: '--configuration Release' - task: DotNetCoreCLI@2

displayName: Test

inputs:

command: test

projects: '**/*Tests/*.csproj'

arguments: '--configuration $(buildConfiguration)' - task: DotNetCoreCLI@2

displayName: 'Publish and zip'

inputs:

command: publish

publishWebProjects: False

projects: $(solution)

arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)' - task: PublishBuildArtifacts@1

displayName: 'Publish Build artifacts'

inputs:

PathtoPublish: '$(Build.ArtifactStagingDirectory)'

ArtifactName: 'drop'

publishLocation: 'Container'

These steps are applied every time I want to merge something to the master branch, this is my trigger. So when I open a pull request into master this pipeline will trigger, since this is one of my required conditions to allow the merge.

Create a pull request and check changes with the build pipeline

This pull request is trying to merge with the master, so it will trigger the build pipeline.

Pull request with the build pipeline validation

The result of the build is the following:

Execution of the build pipeline

Success! Now I can merge my pull request into master because the condition that I defined is fulfilled. At this point, we already have continuous integration and continuous delivery. However, we also want to deploy these changes to the production environment.

Setup your App Services in Azure

To keep things simple I will use the Azure App Service to deploy my REST API. This service has a free tier.

I created an App Service Plan for each API App. I chose the size F1 which is for free but I’m able to define a better configuration for the production environment if I want. This is the reason why we should have one service plan for each environment because their necessities are different.

Choose the F1 option

This is really basic hardware but it’s enough for our simple API. I will create two App Services, one for development and another for production.

API App for development and production

Setup your release pipeline

In the releases tab, below of pipelines, create a new release with the template for Azure App Service deployment.

After that, you need to configure your first stage of the release pipeline. I named him Development. Choose your Azure subscription, application type, and then the App Service that was created for development environment purposes.

Now we need to define our artifact that will trigger this pipeline. In this case, will be the build pipeline that I presented earlier.

Configure artifact to be deployed

So every time that a new build is done on the master branch I want to automatically trigger this release pipeline. For that, we need to edit the artifact properties to enable continuous deployment and to include just the master branch. Here you can define other branches to be included to trigger this deployment process.

Now we can create a new stage for the production environment. At this stage, I configured a pre-deployment condition so don’t be an automatic transition. The condition has one approver.

Production stage waiting for approval

This is a good approach in order to avoid to put some version with issues in production. The idea behind this condition is to guarantee that the team will test the API in development and in the end, if everything goes as expected, the approver can accept the deployment.

Your release pipeline should be similar to the following image:

Release pipeline with two stages

Congrats, you have the continuous deployment all setup!

Conclusion

The CI/CD is a DevOps best practice because reduces the distance of knowledge between developers, who want to push changes frequently, with operations that want stable applications. In the beginning, this method requires the collaboration between development and operations teams in order to decide which technologies, practices, priorities, and policies should be applied. Once this is defined both teams know how to work with the CI/CD pipeline.

Remember that this is not the future, it’s the present! So, if you haven’t started using it yet, you should consider getting started.