Table Of Contents
- Introduction
- GitLab terminology for project tracking tools
- How To Get Started
- Gitlab CI/CD
- Conclusion
Introduction
Every enterprise or every project needs to have a codebase. Without it, It's chaos. Developers working on project will have a hard time picking up on updates. As each of them will have their own copy. If local computer is somehow crashed, The entire data is deleted. So many problems. In our case, We have our own on-prem GitLab Server.
Let's delve into what we are going to learn here:
- The systematic approach of how a project should handle repository code. Some guidelines and stuff.
- How Clean Architecture helps in GitLab to avoid Merge Conflicts etc.
GitLab terminology for project tracking tools
Some of the content here is from ChatGPT as iam lazy
Issues – Track tasks, bugs, or feature requests.
Issue boards – Visualize and manage issues using customizable kanban boards.
Milestones – Group issues and merge requests by project goals or deadlines.
Wiki – Collaborative documentation space for your project.
Merge requests – Propose, review, and merge code changes.Repository – Central storage for your project’s codebase and version history.
Branches – Independent lines of development within the same repository.
Commits – Snapshots of changes made to the codebase.
Tags – Named points in history used to mark releases or important commits.
Labels - Customizable tags used to categorize, prioritize, and filter issues and merge requests for better project organization and workflow management.
Pipelines – Automated CI/CD workflows triggered by code changes.
Artifacts – Output files generated by pipeline jobs (e.g., build results).
Package Registry – Built-in system to publish and share packages (e.g., NuGet).
How To Get Started
When it comes to Enterprise applications, Everybody just dumps the code into the codebase without any use of core concepts. It's okay, But still it looks alot more useless. You will achieve the prime responsibility of the codebase .i.e your code is safe and the recent code is pushed. But, What if you want to categorise it. Where you went wrong and stuff.
Let me show you the approach i use.
At first, Iam assuming you already have a project in gitlab. Now, There are two scenarios in Enterprise applications. Either you develop or you maintain.
Step 1: Milestone
So entire process starts with the Milestone. You can find it Project Repo
/ Plan
/ Milestones
:
In our case, We have maintained two milestones
- Development : As we are developing some applications
- Maintenance : As we are maintaining some applications as employees raise issues, a change in application workflow etc..
Step2: Labels
Labels are prime differentiators in your repo. You can find it
Project Repo
/ Manage
/ Labels
:
For both, Development and Maintenance we have some common labels
Feature
: When a new change is introduced by app owner or by developer. This flag is used.
Bugs
: If employee or tester has raised an issue. This flag is used
Priority-low
: When priority is low
Priority-Med
: When priority is medium
Priority-High
: When priority is high
Update
: When you have fixed an issue or you are working on feature that has already deployed. This flag is used
Documentation
: Used when you are updating the document related to app. And Yes, Its better to keep the documents here as well.
Step 3: Issues
Whenever something happens, It's always best practice to create an issue. Whether it is a new feature or update or bug. Each commit has to have atleast one issue.
You can find it
Project Repo
/ Plan
/ Issues
:
While creating a new Issue, Details matter. Write Precisely what you are expecting. This includes files that are going to change. It's better you have someone who assigns the issues or you can do it yourself.
This is where Labels and Milestone comes into picture. Once created, An issue id is generated. Usually it would be like #3, #120 etc. It's incremental.
Step 4: Branches
You can create branches within VS 2022. Like below
Or in GitLab:
Project Repo
/ Code
/ Branches
The format for Branch name i follow is if its an
feature
: feature/EmployeeId/IssueId
update
: update/EmployeeId/IssueId
bug
: bug/EmployeeId/IssueId
This will help me make it easier to understand, which branches and issues are mine. Please make sure one branch for one deployment.
There should be two more branches: main (default, prod), integration (test env).
*Please maintain an approval system for the merge request to these branches. *
Step 5: Merge Requests
Once you create the branch and push into it. Then there will be only two merge requests created for the entire feature deployment.
- your branch -> integration
- integration -> main
You can find it here:
Project Repo
/ Code
/ Merge Requests
:
Now, Keep in mind. You have issue open and a branch created. When you create a merge request from your branch -> integration and is approved by your senior. The issue should be automatically closed and branch should be automatically deleted. Because, the recent code will be merged into integration and there is no need of branches getting piled up. To achieve this,
Inorder to close the issue:
- In Title, Issue closes or closes or closes Issue . This makes GitLab understand that once merge request is approved, This issue should be closed.
- Give a description. We can create a template as well, We will check it later.
- Select milestone, Label, Reviewer, Assigner etc.
- Under Merge Options,
- Select Delete source branch when merge request is accepted to delete the branch you created.
- Select Squash commits when merge request is accepted. If you have multiple commits under same branch.
GitLab CI/CD
GitLab CI/CD is an integrated toolset that automates the build, test, and deployment phases of your software development lifecycle, directly within GitLab.
.gitlab-ci.yml
: A YAML file in your repo that defines CI/CD pipelines, jobs, and stages.
Runners
: Agents that execute the jobs; can be shared or project-specific. We have set up our gitlab runner in our server. It runs as windows service.
How to set up runner
To install Gitlab runner in your environment or server. You can click here
Once done, Go to your repo project and go to
Settings
->CI/CD Settings
->Runners
- Click on new project runner. You can select the platform, tags. Tags help in differentiating the jobs that needs to be run. In your yaml file, if you set the build to specific tag, Then the build will run on runner which has that tag. You specify that tag here
- If you dont have any tags. Check the run untagged jobs.
- Once you click on create runner. You will redirected here
- Go to the server or environment where gitlab runner is installed and run the command provided in gitlab to register the runner. You can register multiple runners as well.
- Then you run the command gitlab-runner run. If it succeeds, The runner is working fine.
CI/CD GitLab yaml file
stages:
- build
- test
- deploy
build-job:
stage: build
script:
- echo "build started"
- 'dotnet build Test.sln'
- 'dotnet publish Test.WebApi\Test.WebApi.csproj -c Release -p:PublishProfile=StageProfile -o publish-api'
- 'dotnet publish Test.WebUI\Test.WebUI.csproj -c Release -p:PublishProfile=StageProfile -o publish-webui'
- echo "build complete."
artifacts:
paths:
- publish-api
- publish-webui
unit-test-job:
stage: test
script:
- echo "Started Testing"
- 'dotnet test Test.Unit.Tests\Test.Unit.Tests.csproj'
- echo "Testing Completed"
deploy-staging:
stage: deploy
environment: staging
script:
- echo "Deploying application to Staging server..."
- .\deploy\deploy_staging.ps1
- echo "Application successfully deployed on staging"
only:
- integration
deploy-prod:
stage: deploy
environment: production
script:
- echo "Deploying application to production server..."
- .\deploy\deploy_prod.ps1
- echo "Application successfully deployed on production"
only:
- main
The above is the content in yaml file.
There are 3 stages
- Build
- Test
- Deploy
Each stage has job
build-job -> This job builds two projects webapi, webui. Once build succeeds, It pushes the release to the server path of our dev server. This is maintained in Stage Profile. This is not a cleaner approach and i wont reccomend it. The code is pushed to respective artifact folders in gitlab runner server.
Unit-Test-Job -> This checks all the testcases written in Test project.
Both of the above jobs run of each commit push to the repo.
deploy-staging -> This job runs the powershell thats present in file deploy_staging.ps1. This only runs when the merge request is approved to integration branch. This stops the app pool and pushes the release code from artifacts to dev server web app folder.
deploy-prod -> This job runs the powershell thats present in file deploy_prod.ps1. This only runs when the merge request is approved to main branch. This stops the app pool and pushes the release code from artifacts to prod server web app folder.
Test Cases integration
If you want to check the test case report to check how many test cases are covered. This can also be integrated.
stages:
- build
- test
- deploy
build-job:
stage: build
script:
- 'dotnet build Test.sln'
- echo "build complete."
unit-test-job:
stage: test
only:
- pushes
script:
- echo "Started Testing"
- 'dotnet test Test.Unit.Tests\Test.Unit.Tests.csproj --results-directory $CI_PROJECT_DIR/cobertura --collect:"XPlat Code Coverage" --test-adapter-path:. --logger:"junit;LogFilePath=..\artifacts\{assembly}-test.xml;MethodFormat=Class;FailureBodyFormat=Verbose"'
- 'Copy-Item -Path "$CI_PROJECT_DIR\cobertura\*\coverage.cobertura.xml" -Destination "$CI_PROJECT_DIR\cobertura\coverage.cobertura.xml"'
- dotnet tool install -g dotnet-reportgenerator-globaltool #uncomment it if you are using gitlab runner for the very 1st time
- dotnet tool install -g CodeCoverageExtractor #uncomment it if you are using gitlab runner for the very 1st time
- reportgenerator -reports:"$CI_PROJECT_DIR/cobertura/coverage.cobertura.xml" -targetdir:"coveragereport" -reporttypes:"Html"
- codecoverageextractor $CI_PROJECT_DIR/cobertura/coverage.cobertura.xml
artifacts:
when: always
expire_in: 1 week
paths:
- ./**/*test.xml
- $CI_PROJECT_DIR/cobertura/coverage.cobertura.xml
- coveragereport
reports:
junit:
- ./**/*test.xml
coverage_report:
coverage_format: cobertura
path: $CI_PROJECT_DIR/cobertura/coverage.cobertura.xml
dependencies:
- build-job
coverage: /total_coverage=(\d+.?\d?)/
deploy-dev:
stage: deploy
environment: Development
script:
- echo "Deploying application to Staging server..."
- 'dotnet publish Test.WebApi\Test.WebApi.csproj -p:PublishProfile=StageProfile'
- 'dotnet publish Test.WebUI\Test.WebUI.csproj -p:PublishProfile=StageProfile'
- echo "Application successfully deployed on staging"
only:
- integration
deploy-staging:
stage: deploy
environment: Staging
script:
- echo "Deploying application to Staging server..."
- 'dotnet publish Test.WebApi\Test.WebApi.csproj -p:PublishProfile=StageProfile'
- 'dotnet publish Test.WebUI\Test.WebUI.csproj -p:PublishProfile=StageProfile'
- echo "Application successfully deployed on staging"
only:
- integration
deploy-prod:
stage: deploy
environment: Production
script:
- echo "Deploying application to production server..."
- 'dotnet publish Test.WebApi\Test.WebApi.csproj -p:PublishProfile=ProdProfile'
- 'dotnet publish Test.WebUI\Test.WebUI.csproj -p:PublishProfile=ProdProfile'
- echo "Application successfully deployed on production"
only:
- main
As you can see, We have used cobertura for test cases count and to generate xml. We have set it to expire in 1 week as well. This is used by junit to show the xml file. Once its generated, The Gitlab will fetch it automatically and display the report from xml file.
Conclusion
This is the entire process we follow. From the configuration to standardization to Deployming automatically. This is the magic that runs behind CI/CD.
Top comments (0)