Introduction
Time is a crucial element in modern development. The faster an important feature is developed, the faster it can be tested and implemented. There are many methodologies and concepts of development, but Continuous Integration (CI) should be an integral part of every project. Let's clarify the CI meaning and its core objective. CI is a DevOps process that allows developers to merge their code into the main branch of development often and as early as possible. This approach breaks down big tasks into smaller ones and ensures their quality control by allocating specific roles among different members of the team. CI automates most or all of the manual human intervention that needs to be done after code is merged into a branch or after other events occur. We use continuous integration so that we can get feedback about the state of our project as early as possible. We accomplish this by using systems that run automated tests, linters, additional checks, or other tools. This helps us optimize our project, alerts us when there are problems, or runs any console commands we need to execute.
History
Before the advent of CI, testing, linting, assembling, and sending a project to the server were all manual processes that programmers performed before submitting their work. Manual testing was time consuming and prone to error. With the advent of CI all these processes became simpler and faster. Programmers could save their resources and time and focus more on development.
The term continuous integration was first used in 1994 by Grady Buch. Kent Beck and Ron Jeffries later presented the concept of continuous integration in practice, when they invented Extreme Programming (XP), a software development methodology that included CI.
Initially, Grady Buch did not intend to use CI throughout the project. But as the code base and business procedures grew more complex, it became necessary to adopt a CI strategy.
Problems and their solution with the help of CI
Continuous integration allows us to eliminate manual labor during such tasks as building and publishing new versions of code. We can do this with the help of special tools, which we'll explore later in this chapter.
With the help of Continuous Integration, we solve important problems by increasing the speed of implementation of new functionality and improving code quality through early detection of errors. CI runs many checks and tests, allowing developers to focus on writing code rather than spending time tracking down bugs. It allows us to quickly fix bugs by enabling us to individually track each step and job in our Pipeline and view the error log when an error occurs.
By continually improving our development processes, we can not only use the CI best practices but also automate build processes using the automated build software and execute any console commands we need to optimize our project or development process. This might include sending letters with the results of a CI completion to email or another messenger, optimizing images or files, etc.
Tools
- Jenkins. One of the most popular AI tools that helps you create, deploy and automate any project. This tool helps organize the chain of actions for Continuous Integration, using an automated approach. It has a large and active community.
- CircleCI. This tool automates the testing and deployment of your project. It is known for improving productivity by giving development teams control and flexibility.
- TeamCity. It streamlines the code integration cycle and ensures that you never end up with non-working code in your repository. This service can run parallel builds simultaneously in different environments and platforms.
- Bamboo. This service stabilizes and consolidates your builds and tests into a single workflow. It helps developers focus on writing code rather than integrating it with other tools.
- GitHub Actions. With this tool, you can create Continuous Integration workflows in your GitHub repository. After you've committed your code, your tests and checks run. These processes can be run either on virtual machines that are hosted on GitHub or on your own host that you have previously configured.
- GitLab CI/CD. The tool, which is similar to the previous one, only uses services and a repository located on GitLab.
Don’t know where to start?
We will advise you on the best way to realize your idea, leveraging our expertise
An example of CI setting up and configuring
Let's take a look at GitLab CI as an example. For example, we have a repository for our code, a repository. GitLab CI has an integrated functionality that acts as a coordinator and is responsible for running the entire CI process. Our repository can generate events such as commit, pull/merge request. Thanks to these events, we connect with the coordinator. These events tell the coordinator that something is happening to the code.
Also in our repository is a file (.gitlab-ci.yml) with a description of the rules and instructions for what to do when certain events occur. That is, when an event occurs, such as a commit, you need to check the entire code of ESLint, Prettier, run tests, and so on. We also need a Runner - this is a program for executing jobs in the pipeline that we have passed to it, after the event has occurred. After the Runner has received a job, it executes it and reaches the end. Each Runner can execute several jobs in parallel. After that, he informs the coordinator about the job execution result.
The coordinator, which according to the configuration file describes what to do, plans the job. After that, the Runner (executor) turns to the coordinator and picks up jobs one by one, executes them until they are all finished.
The entire process of executing jobs is called Pipeline. A pipeline consists of steps. Steps, in turn, consist of jobs. Below is an example Pipeline.
Pipeline is described in the file .gitlab-ci.yml, which should be located in the root folder of our repository.
Let's consider an example of the configuration and setting of Continuous Integration (CI). Suppose we have a project in which we need to run our code through linters after each merge request or push event, and at the end deploy. If we pushed to the dev branch, then deploy should be on the test server, and if to the main branch, then on the production server. First, let's create a .gitlab-ci.yml file in the root of our project. First, we will describe image and stages.
Image - this option indicates which Docker container our Pipeline runs in. In our case, we want to run in Linux, which has Node 16.7.0 installed.
Stages is a description of the order of tasks. Stages are the steps in our Pipeline.
Let's examine the steps and their functions in more detail.
1. Setup. Before we run our code through tests, linters, we should install all dependencies in our project.
First, we describe the name of our job, in our case it is setup. Next, we describe what should happen in this job:
Stage is a binding to stages, which we described above. In our case, we specify that job - setup should be executed at the setup step.
Cache - list of files to be cached between subsequent launches. That is, we cache the directive node_modules/
Script - a set of commands that will be executed during job execution. As you can see in our example, we set dependencies.
2. Build is the second step in our process. In it, we also have one job, in which we will compile our project.
- Artifacts - this option specifies the directory or file that we want to make available to subsequent jods. In our case, we made the dist folder available, it appears after the execution specified in the job, script. We will need it when we deploy.
3. Code quality is our third step and in it we configure linters. For this, we create 2 separate jobs, one for linting js files -lint:js, and the second for linting style files - lint:styles. Since these 2 jobs do not depend on each other, we can execute them in parallel.
4. Deploy is the last step in our Pipeline where we deliver our build to the server. We will have two separate jobs for this stage. One job to upload the build to the test server if we committed to the 'dev' branch, and another job will upload our build to the production server if we committed to the 'main' branch. We will use the Netlify service. To do this, we specify in the job that needed services must be installed on our image and deployed to the corresponding server. To access our server, we use variables defined in the Netlify service and specified in the settings of our repository.
- Only - allows you to determine when the job should work and when not. We can see that deployment happens according to the branch in which the changes were made.
More detailed information about the .gitlab-ci.yml options is at the link
Read more:
- An overview of React Hooks and Vue Composition API
- No code, pre-made or custom solutions: What is the best for your MVP?
- Should you prefer to React over Vue.js
Conclusions
CI is the practice of integrating code into a shared repository several times a day. It is a software engineering discipline and it aims at building, testing, and releasing software faster and more reliably. The advantages of the CI process to business are that programmers have more confidence that your product is in a working state at all times, and it allows you to move faster and iterate faster—but for this, it is necessary to automate not only testing but also the entire work process. And CI is very good at it. All manual processes we have to perform after merging our code can be described in a configuration file. Setting up such kind of system for your project can be quite an expensive process, but the benefit of CI you will receive as a result will be many times greater than what you have invested in it.
FAQ
Why is CI important for software development?
Continuous integration (CI) is a software development practice that aims to minimize the delay between writing code and testing it by automatically building and testing the code for every new change by independent developers. It is an extension of Test-driven development, in which writing tests before writing code helps to ensure that all elements of the application are tested, minimizes integration problems and reduces time spent debugging.
What are the basic principles of CI?
Continuous integration is a software development practice that aims to improve team collaboration and software quality by automating the building and testing of code every time a team member adds to or modifies their shared project.
What basic problems does CI solve?
Continuous integration is a software development practice that enables teams to build and test software more frequently and reliably. By automating builds and tests, developers can make smaller changes and commit them with confidence. In addition, continuous integration tools provide a level of feedback early in the development process that fosters greater collaboration among developers, enabling them to be more productive.
What is a CI failure?
When a CI/CD pipeline builds fail, one of the most common reasons is changes in credential permissions. For example, a build that was working for a while and then suddenly fails may have been set up with credentials that are no longer valid or whose permissions have changed.
Table of contents:
Want to estimate your app idea?