Organize code storage in GitLab and integrate code review in GitFlow
Not so long ago, on one of our company's projects, it was decided to finally abandon the use of Subversion for storing and versioning code in favor of Git.
The main objectives of the transition were as follows:
- Increase the transparency of the development process.
- Introduce a mandatory code review procedure before updates are submitted to test environments.
- Implement continuous integration to build updates after the code review and install them on test environments.
A prerequisite for achieving the goals was the use of GitLab (this Git server was already used by the customer and even the code related to the front part of the solution lived there) and Jira (also used by the customer).
As a target development model, it was proposed to use Git Flow, adding the review code to it. This de facto development model has become the standard in open source software development and is used by most industry giants. That is why its support is built into many of the popular tools for working with Git. A large number of materials have been written on the subject of its use, I will cite the most successful of them for initial familiarization: one and two times .
By itself, this model offers only general principles for maintaining code, leaving behind the processes that accompany its writing. Therefore, the implementation of everything else, including the code review, depends on the specific Git server. In this regard, GitHub is most convenient: it was originally built as a platform for collaboration of a large number of independent developers and allows you to restrict the right to send commits (Push) to the repository with the ability to create requests to send code. In addition, GitLab offers its workflow for maintaining a code called GitLab Flow, honed to use GitLab CI. Therefore, in GitLab, the functionality for creating requests for sending code is not implemented and it is proposed to use requests for merging branches to conduct a review of the change code.
Also note that for the project were configured integration in Jira and Git. In Jira, a Git plugin was added to track a repository created to store source code, and in GitLab, this repository was configured to integrate with Jira in the Integration section of the repository.
To solve this problem, a workflow was developed for working with code that is similar in structure to Git Flow, but allows you to review the code each time changes are made to the main branches of the process (develop, release-n and master) using GitLab. Next, the resulting process will be described, as well as the adjacent stages of continuous integration and software delivery to the environment. In parentheses are the corresponding commands for execution.
The repository created for storing the source code is downloaded to the local repository (git clone) and Git Flow (git flow init) is initialized in it - in addition to the master branch (to create tags to store stable releases), the develop branch is created (the main development branch, in which branches of functions, releases and corrections are integrated), masks are set for the branches of functions, releases and corrections, and a transition to the develop branch is made.
Next, the current source code branch from Subversion is transferred to the working copy, the code is committed (git add -A + git commit -m “Commit message”) to the develop branch of the local repository and loaded into the remote repository (git push origin develop). After that, you can begin to develop new functionality using Git for code versioning.
During development, the current version of the develop branch is loaded and branches are created from it to develop new functions (git flow feature start MYFEATURE) in accordance with the Jira task codes, which are being developed.
A transition to the created branch is automatically performed (git checkout MYFEATURE), the planned functionality is developed and changes are committed to the local branch MYFEATURE (git commit -m “Commit message”). Note that in order to properly integrate Git and Jira, in the commit messages, you must specify the task code in Jira, to which this fix applies. Then these commits will be displayed in their respective tasks, as well as in the “Git Commits” section of the project, with the help of which you can unambiguously determine what was included in a particular release.
When the functionality of the selected task is developed and ready for transfer to the testing environment, the created commits are loaded into a remote branch with the same name (git push -u origin MYFEATURE) and the develop team or the acting person is asked to merge the loaded branch with the develop branch.
For a merge request, the developer resolves merge conflicts (if any) and the development team (or acting) produces a code review, during which it is possible to create additional commits (git commit -m “Commit message”) with corrections of comments received during the review of the code, in a branch with new functionality and sending them to the central repository (git push -u origin MYFEATURE). After successful completion of the review, the development team (or acting) confirms the merging of branches. Here it is not superfluous to set the flag of deleting a branch after a merger - otherwise the number of branches can quickly grow to indecent scales.
To ensure continuous integration in the GitLab repository, in the "Integration" section, a Web Hook is configured that calls Jenkins to build and install new functionality on the test environment. Jenkins, using the Git plugin, downloads the source code, gets the task name from it and using the Jira API requests the list of components that have been changed and should be assembled, starts the build process, runs the Unit tests and, if they are successful, loads the artifacts in Sonatype Nexus and installs them on a test environment. If one of the stages fails or the Unit tests fail, then the development team is notified of the build result using the Telegram plug-in. If the installation was successful, the QA team is notified that the task is ready for testing.
If defects appear, the develop version of the develop branch is downloaded and a hotfix-MYFEATURE branch (git checkout [BASECOMMIT] -b hotfix-MYFEATURE) is created from the merge branch of the MYFEATURE branch to the develop branch.
When creating, a checkout is automatically made to the created branch, corrections are made and changes are committed to the local hotfix-MYFEATURE branch (git commit hotfix-MYFEATURE -m “Commit message”). When the fix is complete and ready to be transferred to the testing environment, they are pushed to the remote branch with the same name (git push -u origin hotfix-MYFEATURE) and a request is created to merge with the develop branch.
For a merge request, the developer resolves the merge conflicts (if any) and performs a code review, during which it is possible to create additional commits with corrections of received comments. After successful completion of the review, the branches are merged. Immediately after transferring the patch to the develop branch, the Web Hook also triggers to call the task in Jenkins to build, run the Unit tests, load the artifacts created in Sonatype Nexus and install the fix on the test environment. For fixes, a similar notification mechanism works.
If all defects are fixed, the current version of the develop branch is downloaded and a release-mn branch (git flow release start RELEASENAME [BASECOMMIT]) is created from the merge link of the hotfix-MYFEATURE branch to the develop branch.
Creating a release branch also initializes the launch of the Web Hook to call a task in Jenkins, which extorts the source code from Git, gets the name of the release branch from it and using the Jira API requests a list of components that have been changed as part of the release tasks, extorts the latest versions from Sonatype Nexus and installs them on the regression testing environment. Following the installation of the release on the regression testing environment, scripts are run to prepare the environment for testing (restarting applications, clearing the database, etc.) and run regression autotests to test the main functionality of the system, the results of which generate a report using the Allure Reports plugin for Jenkins. After installation, the QA team is notified to Telegram of the results of the autotest run and the readiness of the release for manual regression testing.
If during the regression testing defects appear, the current version of the release-mn branch is downloaded and a hotfix / BUGNAME branch is created from the last commit by the defect name in Jira (git checkout -b hotfix / BUGNAME [BASECOMMIT]).
A checkout is automatically made to the created branch, the necessary corrections are made and changes are committed to the local hotfix / BUGNAME branch (git commit hotfix / BUGNAME -m “Commit message”). When the fix is complete and ready for removal to the regression testing environment, they are pushed to a remote branch with the same name (git push -u origin hotfix / BUGNAME) and a request is created for merging with the release-mn branch
For a merge request, the developer resolves merge conflicts (if any) and performs a code review, during which it is possible to create additional commits with corrections of comments received during the review of the code. These commits are also made to the local hotfix / BUGNAME branch (git commit hotfix / BUGNAME -m “Commit message”) and push them into a remote branch with the same name (git push -u origin hotfix / BUGNAME). After successful completion of the review, the branches are merged. The merge initializes the launch of the Web Hook to call the task in Jenkins, similar to the previous one, but differs in that it downloads the code from Git, gets the defect name from it, using the Jira API requests the list of components that were changed as part of the fix, assembles these components, loads the Sonatype Nexus and installs them on the regression testing environment. Then, by analogy, the environment is prepared for autotesting, the regression autotest is run and the results are reported.
When all defects are fixed, the release is installed on the production environment. To do this, merge the release-mn branch with the develop and master branches, and create a release tag.
When it is created, it initializes the launch of the Web Hook to call the task in Jenkins, which downloads the source code from Git, gets the release number from it and using the Jira API requests a list of the tasks that were included in the release and the components that were changed as part of these tasks, after bringing up the current versions of the artifacts from the Sonatype Nexus and installs them on a productive environment.
With hotfixes for sale, it was decided to use a process similar to the release one - otherwise, the stages of testing the changes made are lost.
When the process was implemented, training was also conducted for employees who do not have Git and GitLab practices, for which a corresponding training program was developed. With it, you yourself will be able to conduct training on using Source Tree and Intellij IDEA to work with Git, as well as GitLab for reviewing the code. In the next post I will give it, adding illustrations.