In this article, we will walk through the CI pipeline that builds a docker image for an API service that has some dependencies and services dependent on it. Let's count all the cases when an event should trigger the CI pipeline.

The pipeline should execute unit tests on the commit.
The pipeline should execute integration tests on the commit.
A commit should be deployed to pre-production.
A commit should be deployed to the production.
Unit tests are blessings for Developers
As the developer creates the future branch and pushes the code, the CI pipeline should run the unit test to inform the developer of any failures as soon as possible. In most cases, you will not need to build any images; some other preparation is required. You'll need to install more unit testing libs on your CI worker; however, you can use prebuilt docker images for the worker. Unit tests are executed on a single machine; therefore, preparation is fast, and execution is more rapid. These are the most valuable tests from an ROI standpoint. Invest in writing as many unit tests as possible; unit tests are a blessing.
Only the developer knows the next version
When the developer thinks the code is good enough to be checked with the rest of the codebase, a PR to the integration branch (called development in many cases) should be created or converted from the draft(GitHub) to a regular PR. In this case, you must build a docker image and run the service on it, as it will serve requests and initiate others. In some cases, contract testing is used, which changes things slightly, but in general, you need to build an image to run a container. However, you only need to store it if it passes the integration tests. You can fully automate this process if you have a quality set of integration tests with no flakiness. As the pipeline sees all the integration tests passing, it can create a release candidate and push it to the container registry. But there is a problem here. A version tag must be assigned before moving it to the container registry. Suppose the current version is 0.1.0. What will the new version be? We know it should end with "-rcN," but what should come before that? The answer is only people know. A bot can't know what kind of commit it is. Has it been introduced as a bug fix or a new feature? Therefore, you must think twice before building an image from the integration branch. The PR can have the semantics missing. That can be solved with conventional commits, forcing developers to be mindful of commits. And remember, most of them hate that. PR creation can trigger the integration tests if no traditional commits are used. If all the tests are passed, a human can create a release candidate tag and push that to the integration branch, which will trigger another pipeline to assign the tag to the image with some metadata(tag) about the commit(a commit sha) to ensure that the workflow assigns the release candidate tag to the proper image. There is no need to say that the image should be removed immediately if the tests are filed.
No images should be rebuilt
The image with a release candidate(pre-release) tag can be deployed in a testing environment for manual testing or the so-called UAT. As the QA gives the green light for the production deployment, a new tag with the pre-release portion removed should be assigned to the same image. That should be done with another pipeline execution, and the trigger for that should be in the event of a release tag push to the main branch. Of course, the tested pre-release tag should be merged with the main branch, and a release tag should be manually created on the main branch. In many compliance standards, a business process that ensures the deployment of the same image used for testing is required for production.
Comments