Creating and Publishing Private NuGet Packages using Jenkins with Auto version
Why do we Have to Create Private Packages?
When working in an organization or a firm, we may have automation frameworks for web, mobile, API, and desktop. Each of these frameworks will have generic base modules/components that any team can use to automate the company’s applications.
So, if you ever wanted to share this with the other teams or another department, the ideal way to do it in real-time is to make the common modules/components of the framework a package in a NuGet package that sits in the company’s private NuGet server. So, anyone that has access to this can easily download this in their Visual Studio and use it.
The best thing about this is that since the original team will be working on the framework and updating it, any other group using the package will also have access to the updated versions. This reduces much of the redundant work and makes teams work more efficiently.
In this blog post, let us cover the below topics.
● Create a project in Visual studio and generate the NuGet package
● Push project to GitLab repo
● Download BaGet server and run on the local machine
● Set up and configure Jenkins Job pipeline
Software and Tools Used
It is quite important to know how a code is running as it is before you use it. We’ll be creating a new project in Visual Studio as a sample to generate a NuGet package for it. You also have to be a bit familiar with GitLab and how to use it. We’ll then be using Jenkins to run our pipelines and host our nuget in a Baget server.
GitLab is a git web repository. It is mainly used for version management. The specific use cases of GitLab often align with continuous integration. However, this need not be true for all the repositories in GitLab. If you know GitHub, then you won’t have much trouble with GitLab either.
We will also be using Jenkins to run our automation pipeline. Jenkins is an open-source automation server with numerous plugins. Jenkins will support the building, deploying, and automating of any project. Jenkins is easy to learn and use. Even a beginner can learn how to use Jenkins pretty quickly.
We will also be using a nuget server called Baget and I will explain more on this further down in the blog.
Everything you need to know about these tools to use them effectively will be in this article itself. You have to be familiar with .NET to follow the code.
Creating the Private Package
First, create and configure a Class Library .Net Standard project. For this demo, I named mine ‘XYZAPIAutomation’; usually, it’s best to name it CompanyName and then give it the type of framework it is.
After creating the project let’s create a class and some methods. I created a TestBase folder and created a class called ‘CrudOperation’ where I just have some static methods printing messages to the console. I will not be writing any selenium or API automation code as the agenda for the blog is to show you the processing of packaging and publishing this project as a NuGet using Jenkins.
Now we will set up the visual studio to create our NuGet package during the build. To do this right-click on the project- > select properties -> Package
Then click on the check box ‘Generate NuGet package on build’ and fill out the following fields. Package Id, Package version, Authors, Company, and Product and save it. That’s all we need for this demo. Note for the first manual package build, I have used 1.0.0, but Jenkins will auto-increment this when we set up the pipeline. Now build the project, and you should see XYZAPIAutomation.1.0.0.nupkg package. This is our NuGet, and it will always be in your project bin/debug path.
Now we will create a Gitlab repo and push this project. Assuming you guys know about git and code repository management. So, I will just include the screenshot of mine. I named my GitLab project with ‘Common’ just to differentiate the common code shared with other projects in the same GitLab group. Again, another good practice we should follow, in my opinion.
Note: ignore the Jenkins file as we will create this file again in the coming steps.
We will now be using BaGet to put our NuGet package in. BaGet is an open-source lightweight cross-platform cloud-ready NuGet server with a great front end UI. I love this NuGet server, and my previous organization uses this as well.
BaGet is used by many organizations and firms all over the world. You can run a BaGet server on a local computer, Docker, Azure, AWS, Google Cloud, and Alibaba Cloud (Aliyun) as well. The flexibility that BaGet offers isn’t available in many other open-source servers.
BaGet is a very advanced server and has numerous functions and features that can make your work easier. Visit the BaGet official documentation page to know more about this incredible server. https://loic-sharma.github.io/BaGet/
To download and get started, please follow the steps:
- Install the .NET Core SDK
- Download and extract BaGet’s latest release
- Start the service with Dotnet BaGet.dll
- Browse http://localhost:5000/ in your browser
If you have followed the steps correctly, you should be to see the landing page of BaGet
Now, make sure not to close the BaGet server as we will now be diving into the main work, which is creating a Jenkins job for our project and the Jenkins file. Before that, though, make sure you have Jenkins running on your local machine. If you either close the BaGet server or if Jenkins is not running on your system, you will see an error when we run the below code.
You don’t have to worry about anything, though. You can just start the server or the Jenkins on your local system and re-run the code again to get the desired output. So, let’s get started!
Let’s create a new Job; I named mine the same as ‘XYZAPIAutomationCommon’. You can name it whatever you want. Creating proper names with reference to a coding standard or a set of rules will make code maintenance easier. Now, choose the pipeline option.
Now, let’s open an editor. I like to use my all-time favorite Eclipse IDE, especially for writing my groovy scripts, as it has a great groovy plugin. You can use the editor of your choice, but if you want to use eclipse, you can download the plugin or install using the software link, which can be found on groovy official GitHub wiki page https://github.com/groovy/groovy-eclipse/wiki
So, we will begin creating the pipeline first. We will define three stages, first will be to create the package, which will build out the project and package the NuGet. The next stage is to push this package now to the BaGet server. The last stage will be to update the version and clean the workspace, and that’s it!
Let’s go over this pipeline a little more in-depth to understand exactly what we are doing here. First, we declared the environment, and I am using Home, which is our Jenkins home directory. Then we create our first stage, ‘Create Package’, where I am using a shell script to run the command dotnet build, which will build our project. Then I am using the dotnet pack command, and I am locating the .csproj file, which will create the nupkg file, which is our NuGet package.
This file will be in our bin/debug folder. The next stage is our ‘Push Package’ stage, where I am using the dotnet push command to push the package to our BaGet server. Here you will need to navigate to the bin/debug directory where your .nupkg file is and give your URL to the BaGet server along with the API key password.
You will also notice I am using string interpolation for the version as we will pass this as a parameter for our Jenkins job. There are a couple more methods to name the versions, but string interpolation is the simplest and the fastest method. The last stage is our ‘Update Version’, which will get the current version in the parameter and update it, and it will clean the workspace.
Now that we have the base skeleton of the pipeline, we will create two functions, ‘getUpdatedVersion’ and ‘updateVersion’. Our ‘getUpdatedVersion’ method decides the version type here, and I am using semantic versioning.
We then call this function in our ‘updateVersion’ method, and this method takes the job name, then we iterate through the list of parameters defined in the project and then we check if the version is the same as the current instance item which it is and if true we will split the default value and get the index of 1 and put it in the minorVar variable.
Then the next if the condition is to check if our minor value is greater than 8 increments the major. So, I put this so if it’s 1.9.0, the next time, it will be 2.0.0. So, we are incrementing the major based on the minor. I hope these two functions are clear now to you guys.
We will now put all the pipelines and the functions into a Jenkins file and put this in our project. We will need a few import statements as well. I highly suggest you run the pipeline using inline scripted first as you will need to approve, or your Jenkins admin for your company will need to approve the script functions.
Here is a screenshot of what needs to be approved. Once this is done, then you put them in the Jenkins file. So, let us see how it looks together below!
Let’s go to our job as we need to add a parameter. Click on configure and choose the ‘This project is parameterized’ option under general and give it name ‘version’ and give it the first default value 1.0.0
Next, click on the ‘Poll SCM’ and give a cron time of 5 minutes. Ex: H/5 * * * *
So, if you do not know what Poll SCM does, Jenkins will check basically if the master branch or whatever branch you specify, and if it has some new changes, it will kick off a new build; otherwise, it will not trigger a build. This feature will be useful especially if there is more than one branch in the project. Usually, when working on high-level projects, there will be multiple sub-master branches and a single master branch. This feature will reduce version anomalies and keeps the code cleaner.
So, let’s say you need to update the framework with some new helper functions, and this code gets merged to master, this job will check and when it identifies that there are new changes in master, it will trigger a new build, and you will get your updated version.
If your version was 1.0.0 that new auto-trigger would then be 1.1.0, and it will be pushed to your BaGet server. Now anyone can go download it on their IDE in Visual studio or down the NuGet package itself by going to the BaGet server.
Additionally, make sure in the pipeline section you choose ‘Pipeline script from SCM’ and authentication to your git repo as this will be our source code check out part of the stage in the pipeline.
Let’s find out if our pipeline is working or not by manually triggering it. If you have followed everything, you should get a successful build. Let’s check that BaGet server! We have successfully pushed our NuGet package using the pipeline!
Now let us check if you can see this package in our visual studio. To do this, open visual studio and right-click on project->click on Manage NuGet packages -> Click on the Package source gear icon ->Click on the green plus button and add your localhost BaGet server and click on Ok. Choose your BaGet server as the package source and click on the refresh button.
Congratulations, you can now see your package! You may install it and start using the framework!
The last thing we will check is auto-increment. If you remember, we configured our job using poll scm and gave it 5 minutes cron time. So, let us update our framework and push something new and check the following.
When we push new code, does our Jenkins job trigger automatically within 5 minutes.
Does it successfully push a new version to the BaGet server, and is the versioning correct? (Note next version should be 1.1.0)
Check-in visually studio if we got the new package with the correct version.
I have added this new line of code. Let’s get this merged!
As you can see, a new Job is triggered by the SCM change, which means it triggers because of the poll scm we gave, and also, my build was successful.
Now let’s check the visual studio if we got the new version with the new code. For this, I created a new project, ‘TestNuGetPackage’, to test it.
Let’s install it and check if we get that ‘NewMethod’ in this version! As you can see, we can call the method.
I hope this blog post helps you understand how we achieve building NuGet packages and sharing common code in an organization using Jenkins. Please do follow me on medium for more upcoming blogs on real-world use cases/usage of the latest tools and technologies for test automation.
Happy Versioning 😊