Cosmo’s Guide to Developer Builds and Deployment in the Cloud
Published: 2021-09-07 15:30:21

by Phil Jacobs – January 22, 2021

Yes! My last merge request was accepted, the automated build kicked off, and I’m anxiously awaiting for the continuous integration (CI)  pipeline to complete.

What are some of the steps that I could have taken?

    Used solid unit tests, part of a test-driven development process
    Added new code that calls a web service, and validated the request was accepted
    Perhaps, saved a new field to a persistent data source

During my test-driven development process, I experimented with the new API I’m consuming. I fulfilled the non-functional requirements related to logging, tracing, authentication, analytics, metrics, and monitoring.  All of these added complexity to the small piece of code  I developed.

Using your devbox, and your favorite toolset, were you able to validate your changes? It turns out that validating a simple change isn’t always easy to do, even with the use of containers.

You should rely on the CI pipeline for an automated build, and execution of integration tests to validate a change. To get to a build that passes the integration tests, you evolve your deliverable. Let’s spend some time looking at your development effort in more detail.

    You use your IDE to compile, if necessary, and kick off your unit tests.
    To sanity test your work, you exercise your changes.

In my case there are multiple dependencies to my microservice, see Figure 1. To exercise my change, I check that I have a recent Application UI on my devbox, make sure my datasource schema is current, and so forth. But there has to be a quicker way.

![Application UI connects to SSO Service and Microservice, which uses Datasource](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4q2lm41y9f272ukkr7h1.png)
Figure 1

 

Using CI with a pipeline for developer builds and deployment, I kick off a build and deployment by committing and pushing my work to my feature branch. For this pipeline I’m using Gitlab CI. Since my team is sharing the development environment in the cloud, our components are kept up to date.

Our typical CI pipeline may have the stages Build and Release, see Figure 2. There are two jobs for the build, build-arm64 and build-x86_64.

![A build pipeline with two build jobs feeding into a release job](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/perbrg7sap6d6sjf1qj6.png) 
Figure 2

 

To incorporate feature branch build and deployment, I added the stage Deploy to the pipeline, with jobs to deploy our supported architectures, deploy-develop-arm64 and deploy-develop_x86_64.

![A build pipeline with a build job feeding into two deploy jobs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iiwcfy0sj2f6dfk0xap0.png) 
Figure 3


In Gitlab CI, Jobs are defined in the gitlab-ci.yml file in your repository. So that our jobs for the Deploy stage are only used for development deployments, I made extensive use of Rules.

  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == null && $CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master"'
      when: manual

The Gitlab CI variable CI_MERGE_REQUEST_TARGET_BRANCH_NAME is compared to null so the job is not run for merge requests. The CI_COMMIT_REF_NAME variable is compared to our dedicated branches for our continuous integration and release. Deployment should occur if it is not one of our dedicated branches. And the step is manual, the deployment should occur if the developer desires the build to be deployed to the development environment.

In conclusion, adding a development deployment step provides automation for a frequent developer task. Benefits include a simpler setup on your devbox, and the automation is there for the whole team. Tedious troubleshooting of devboxes is reduced, and having a working state in a development environment are all benefits.

![a ginger cat](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qd3ctfxwg0yno16xd0cu.png)
 Cosmo