C.I.

In the previous article, we reviewed the main components of the CI/CD Kubernetes platform of Gitorion. In this article we will take a closer look at the implementation of code hosting, version control system and continuous integration CI.

Abstract problem statement

Abstractly, the task sounded like this:

  1. Select and install a Self-hosted Git server so as not to depend on commercial and cloud solutions;

  2. Organize joint amendments to the code by a group of developers so that they do not interfere with each other;

  3. Provide for the possibility of preliminary demonstration of changes made to management;

  4. Develop a mechanism for delivering changes made to production after management approval;

  5. Automate all processes as much as possible;

  6. Consider the possibility of rolling back to previous versions in case of errors.

Simplified diagram of an abstract problem statement

Simplified diagram of an abstract problem statement

Choosing code hosting and version control system

After a short search, we found the lightweight Open-Source product Gitea, which implements the functions of code hosting and collaborative development based on Git. Gitea is created as a Self-hosted solution, but it also runs Codeberg public code hosting. In 2022, a course was set for the commercialization of Gitea, which contradicted point 1 of the above task. In response to the commercialization of Gitea, some of the developers made a fork A Forgejo that will remain independent, community-owned, have an independent codebase, and be self-sustaining. We will replace Gitea with Forgejo and write a separate article about it. Below we will look at solutions based on Gitea functionality, since the same functionality is also available in Forgejo.

Distribution of Git branches along contours

We started by creating 3 isolated circuits (aka namespace in Kubernetes) – development, staging and production with an identical set of microservices (frontend, backend, mysql/postgresql, redis, etc.) in each of the circuits.

  • development – outline for developers. Each programmer creates his own sub-branch from the main branch and makes changes to the project code only within his sub-branch. After completing the task, he makes a push to Gitea. Gitea sends a Webhook to Jenkins. Jenkins assembles a Docker microservice container with the code of this programmer and delivers it to the dynamic environment for review. This is how we solved the second problem.

  • staging – a contour for demonstrating changes to management. The team leader merges changes from programmers' branches into the main branch in an organized manner and pushes them into Gitea. Gitea also sends a Web hook to Jenkins, which collects the Docker container and delivers it to the staging circuit for demonstration to management. This is how we solved the third problem.

  • production – production circuit. After management approval, the team lead manually launches a pipeline in Jenkins that promotes the Docker image from the staging circuit to the production circuit. This is how we solved the fourth problem, but this rather relates to continuous CD delivery, which will be discussed in the next article

Scheme of CI/CD platform Gitorion

Scheme of CI/CD platform Gitorion

Developer procedure

The team leader creates an account in Gitea for the new programmer (for example, user3).

List of users in Gitea

List of users in Gitea

Makes the developer a co-author of the microservice repository, to the code of which the programmer will make changes.

List of co-authors of the backend microservice repository

List of co-authors of the backend microservice repository

Programmer user3 clones the Git repository and creates a sub-branch (for example, dev1).

List of backend microservice repository branches

List of backend microservice repository branches

And begins to complete the task. Adds edits to the code, makes a push to its branch. Jenkins automatically collects Docker images of the microservice with the programmer's edits and delivers it to the review circuit in the development circuit. Preliminary results of the work can be assessed at the link https://review-frontend-dev1.example.com (dev1 – developer branch).

Having completed the task, programmer user3 creates a Pull Request to merge changes from his dev1 branch into the main branch and reports to the team lead about the completion of the task.

Merge request in the programmer’s personal account

Merge request in the programmer’s personal account

Red shows the code that the developer has removed, and green the code that has been added. For example, we simply changed the version in the site code.

Team lead's procedure

A merge request from the developer user3 will appear in the team lead’s personal account.

Request for a merger in the team lead’s personal account

Request for a merger in the team lead’s personal account

The team lead selects a merge request and receives detailed information about it.

Pull Request Details

Pull Request Details

Goes to the “Changed Files” tab and examines the edits made by the programmer.

Edits made by the programmer

Edits made by the programmer

If everything is in order and the programmer has completed the task correctly, the team lead clicks on the “Create a merge commit” button and merges the changes from the dev1 developer branch into the main branch. If the merge is successful, the following message will appear.

Message about successful branch merge

Message about successful branch merge

A merge commit initiates a Webhook from Gitea to Jenkins. Jenkins will automatically build the Docker image and deliver the container with the programmer’s work to the staging circuit, where the team lead will be able to demonstrate the changes made to the project customer.

Automation

For automation, we used the Web hook mechanism in Gitea and Jenkins. All a programmer or team lead needs to do to make changes to a microservice is add edits to the code and make a push. Further processes occur automatically. Gitea, having received the push, sends a Web hook to Jenkins. Jenkins uses a Web hook to pull the Git repository from Gitea and launch the pipeline for the microservice, the stages of which are specified in the Jenkinsfile. Compiles the application code if the microservice is written in a compiled programming language, or simply copies the code into a Docker image if it is written in an interpreted language. Builds a Docker image according to the layers specified in the Dockerfile and places it in a private Docker Registry repository. Delivers a microservice using helm to a Kubernetes cluster. All these processes can be monitored in the Jenkins Web interface and the execution time of both the entire pipeline and its individual stages can be assessed.

You can add a web hook in the repository settings.

List of available web hook types

List of available web hook types

Select a Gitea Webhook, set the Jenkins service URL and access token.

Webhook parameters

Webhook parameters

Branch protection

By making the programmer a co-author, the team lead gives him the right to make changes not only to his branch, but also to the main branch. If all programmers uncontrollably make changes to the main branch directly, confusion and conflicts will begin, and we will not fulfill the requirement in point 2 of the task. Go to the repository settings and create branch protection rules.

Rules for protecting branches in Gitea

Rules for protecting branches in Gitea

For the main branch, create a rule that allows direct edits and Pull Request Merge changes only to users from the white list (team leads, project managers).

Restricting access to the main branch by whitelisting users

Restricting access to the main branch by whitelisting users

The platform is built in accordance with the infrastructure as code IaC approach. In one Git repository, next to the source code of the microservice, the following are stored: a Dockerfile for building the Docker image of the microservice, a Jenkinsfile with a build and delivery pipeline, microservice configuration files for all 3 circuits, a helm chart for deploying the microservice to the Kubernetes cluster.

A typical set of directories and files in a microservice repository

A typical set of directories and files in a microservice repository

To prevent programmers from “breaking” the build and delivery processes, we have restricted their access to all files and directories of the repository, except for the src/ directory with the source code of the microservice, which programmers will directly work with. We created a rule for all branches with the prefix dev** and listed the directories and files to which programmers are prohibited from accessing.

Restricting programmer access to directories and files in the microservice repository

Restricting programmer access to directories and files in the microservice repository

Conclusion

In the next article, we will take a closer look at the intricacies of implementing continuous CD delivery using Jenkins, as well as the auxiliary tools that needed to be integrated into the platform to build Continuous Delivery. Thank you.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *