DevOps, as said is the integration of development and operations. It is a new stream of automation that takes the software development and its life cycle to the next level thereby reducing a lot of manual and risk/error-prone situations. It adds value to the accelerated delivery and serves to enhance the quality of the software. In today's era, if we look around, we see a lot of tools and technologies built over to leverage DevOps. One of them is Jenkins. Jenkins is not new, but its seamless and easy methodology of integration into any system has made it more robust and reliable. Gone were the days, when integration and deployment was a troublesome task as it was done manually. Having these kinds of tools in place helps a developer, in fact, the whole team, forget about the integration and deployment as they know that there is an automated process in place to take care of this. This article will cover the topic of continuous integration and deployment using Jenkins in detail. This article will explain the concept of CI/CD, Jenkins, getting started with Jenkins, integrating and deploying an ASP.NET Core application locally and to the Azure Service as well. While we go through, we’ll also cover topics like creating Azure service, creating Azure service principal, configuring Jenkins on Azure.
Following is the road-map we would be following to completely learn end to end development and configurations of Continuous Integration and Deployment (CI/CD) of ASP.NET Core Application on Azure Web App using Jenkins.
DevOps is the combination of different people, processes and operation tools. It helps the development and operations team providing a common, mutually understandable platform. It segregates and draws the line on where the development team stops and where the operation team starts. The tools and technologies for continuous integration and deployment are the part of DevOps which helps to fetch the committed code, restoring the dependencies, compiling the application, running the unit test cases (if any), deploying the application and make sure it is up and running. There is a lot more that comes under DevOps but is out of the scope of this article like monitoring the application and its related attributes.
The situation where a developer commits the code to a source control (be it SVN, Git or any other source control) and an operation/process/tool continuously monitoring that source control to fetch the fresh copy of the code, restore the dependencies, compile the code, run all the unit tests, integrate the code with the code of other developers, generates the report, notifies the team members and generates the artifacts and deployable package is in simple terms known as Continuous Integration. There are a lot more operations that could be part of CI, but this is the basic flow to understand CI.
Continuous deployment is the next step a DevOps operation/process/tool continuously looks up to. It helps the team based on certain parameters to continuously deploy the deployable package produced by CI. These CI and CD steps are repetitive and are subject to how their triggers or callers are configured. The deployment could be done in stages, for e.g., there could be stages where the code first needs to be deployed on the dev server, then QA server, then UAT, Stage and then Prod. Continuous deployment thereby eliminates the manual process of deployment and based on certain triggers, parameters, and conditions, the code automatically gets deployed and running on the configured servers and that too in sequential stages.
Jenkins being an open-source tool for automation helps a team/developer to build and test the software code continuously. It makes it easy for a developer to integrate and test the code without manual intervention. The tool could be set up to create a deployment pipeline that includes continuous integration of the code at each code commit, continuously testing the build, publishing artifacts and documents and deploying the code. Jenkins could be configured on the servers, say it be development, staging or production as per the deployment needs.
Azure Web App Service
Azure App Services serves as Platform as a Service (PAAS) in Azure cloud. Azure Web App Service makes it easy to host an application on a cloud platform with the liberty to build, deploy the application using tools, frameworks, and platforms as per discretion. It takes care of autoscaling, high availability and load balancing of the applications so that developers do not have to worry about the environment and can focus on development.
This article series will explain using Jenkins for CI and CD of an ASP.NET Core web application on the local development environment, publishing the web application to Azure Web App Service and configuring Jenkins on Azure for continuous integration and continuous deployment of the hosted application. GitHub will DevOps as a source control repository. We’ll create a pipeline using Jenkins that fetches the code from GitHub, builds the code, runs the tests and deploy the package. This will be a repetitive task on each commit to the code located on GitHub.
Following are the prerequisites for developers to have on their machines before getting started:
- Visual Studio 2017/2019
- Dotnet 2.1 SDK installed
- Azure Subscription Free/Paid
- Java 1.5 or higher
- Git account
- Git for Windows
Let’s install and get Jenkins running on the local development environment step by step.
Jenkins is a Java application and needs Java Runtime to run. So, install Java 1.5 SDK or its higher version on the development machine. Download the latest version here.
Download and Install
Navigate to the URL: https://jenkins.io/ and follow the instructions as given below:
- Click on the Download button and it will show the list of options for downloadable. We’ll use the Windows version of Jenkins downloadable. So, click on Windows in the LTS list and the download should begin immediately.
- Once downloaded, unzip the package and run the MSI to install Jenkins, follow the instructions of the wizard and install Jenkins.
- Jenkins will be installed on localhost:8080 by default. Once the installation is done. Navigate to the URL http://localhost:8080/ and the screen will appear to unlock Jenkins. Use the password stored in the file initialAdminPassword to unlock Jenkins as shown in the following image:
Before working with Jenkins, there are few plugins that need to be installed. Since Jenkins supports many tools, frameworks, so the desired set of tools needs to be plugged into Jenkins to get the things working. We’ll install our needed set of plugins. Initially, install all the ones that are recommended. So, click on the first option, i.e., “Install Suggested Plugins.”
This will take a while and install all the basic plugins for Jenkins.
Once the basic plugins are installed, it will ask to create an Admin user. You can provide the desired details and make sure you remember the user name and password at least.
Once you provide the details and click on “Save and Continue”, you are done installing Jenkins and get that running. Click on “Start using Jenkins”.
To avoid login at each time you open Jenkins, you can go to the “Configure Global Security” section shown on Jenkins dashboard and check the “Allow anonymous read access” option.
Since we would be using an ASP.NET application and unit tests. So, install the related plugins that support this application. Go to Plugin manager and install MSBuild, MSTest, MSTestRunner, PowerShell, VSTestRunner and Git plugin if those are not already installed.
ASP.NET Core Application
I have used ASP.NET Core MVC application version 2.1 for demonstration. It is a simple application with just showing the host or container in which the application is running.
Download or Create the ASP.NET Core Web Application
Create any sample ASP.NET core application, or clone/download the already created application from https://github.com/akhilmittal/Getting-Started-With-Jenkins.
You can use the git clone command to clone the repository in the desired folder of the local drive.
Build the Application Locally
Let’s compile the application locally through the dotnet command to make sure it is working fine and later, we can automate these steps using the same command configured in Jenkins.
- Open the developer command prompt for Visual Studio.
- On the command prompt, navigate to the folder where the solution file is cloned. Type the command “dotnet build <solution file name>”. This will compile the solution file.
Run the Unit Tests Locally
If you open the solution file in Visual Studio, you’ll see that there is a test project named “JenkinsIntegration.Tests.csproj” that contains a single test. We’ll run this test vis dotnet command locally and log the results in a log file. So, run the rest via the “dotnet test <test project name> --logger:trx” command as shown below. Once the tests are passed, it will say “Test Run Successful”.
You can check the test results, i.e., the created log file in the “TestResults” folder under the test project directory.
Continuous Integration of ASP.NET Core Application using Jenkins
We see that our application compiles the file and the tests are also green. It is time to get rid of this manual process of running the command and automate this build and test running process. We’ll do this using two approaches in Jenkins, i.e., Pipeline approach and Freestyle project approach.
The pipeline project approach helps in creating a workflow for the set of activities to run in a sequential manner or in the form of a flowchart. This pipeline in Jenkins could be created by writing small scripts for each stage of CI that we target, i.e., fetching the source code, compiling it, running the tests, etc.
- On the Jenkins home page, click on “create new jobs”.
- Select the project type as “
Pipeline” and give the project a meaningful name, for e.g., “
JenkinsPipeline” in this case.
- On the next screen, you need to provide a basic sequential script for the pipeline to execute the stages one by one. For e.g., checkout, build and run tests, i.e., the things that we did manually. Following is the script I used in the Pipeline script as shown in the following image.
dotnet = 'C:\\Program Files\\dotnet\\dotnet.exe'
git credentialsId: 'b92a2c28-2693-4fc1-8490-49c7db00ed8a',
url: 'https://github.com/akhilmittal/Getting-Started-With-Jenkins', branch: 'master'
bat 'dotnet build JenkinsIntegration\\jenkinsIntegration.sln --configuration Release'
bat 'dotnet test JenkinsIntegration\\JenkinsIntegration.Tests\\
The pipeline script created above has three stages.
- Checkout: In this stage, we provide the URL of the Git repository, branch as master and git credentials id. Git credentials could be stored in Jenkins configuration and a corresponding id will be provided that could be used in the configurations so that you do not have to provide the credentials again and again.
- Build: Once the checkout is done, dotnet build command is used to build the solution as we did manually.
- Test: Once code compiled, runs the tests vis dotnet test command.
So, we simply configured our manual commands in the form of a script. In the environment section, we provided the path of the dotnet EXE because we are using it in our script and Jenkins should know where the EXE must be run from.
- We also need to configure when our pipeline build should be triggered. So, in the “Build Triggers” section, check the two options of Poll SCM and GitHub hook trigger as shown in the following image. Here, we can set the intervals for which Jenkins should check the code on GitHub and perform the build And provide the schedule as “* * * * *” which means, keep checking the Git repository and as soon as a commit/check-in is done, trigger the build process. We can also trigger the build manually if we went from Jenkins dashboard.
- Go to the Jenkins home page and we see our job created there and at the rightmost side is the icon to trigger the build. Now, trigger the build manually to check if our workflow really works.
- Once the build trigger finishes execution, it showed the status on the left side panel. You can click on the build on the left side while it is executing to know the live status of the build or when it is complete. Click on the build and we see that our pipeline headers like Checkout, Build and “UnitTests” are listed in a sequential way telling the time each process took. All the processes run successfully including the tests. You can also check the log file we intended to create after running the tests by clicking on the Logs on “
UnitTests” completed process as shown below.
Following is the log file that got generated with passing tests.
Freestyle Project Approach
Freestyle project is another approach to do the same thing except you do not have to write scripts here and provide needed configurations. Let’s check this step by step.
- Again, on the dashboard, click on “create new jobs”.
- Provide a name to the item for e.g., “JenkinsFreeStyle” and select
Freestyle project as the project type.
- On the next screen, under “Source Code Management”, select Git (since we are using Git) and provide the Git credentials. Provide the branch as “*/master”.
- In the “Build Triggers”, we’ll again use “
* * * * *” which is explained in the last section.
- In the Build section, we’ll now provide our dotnet commands to be executed sequentially both for compiling and running the tests as shown below:
- In the post-build actions, let’s provide the name of the test result file we intend to get created. Quote the same name in the dotnet test command in the Build section.
- Now, save the configuration, go to the home page and run the created trigger. Now once build completes, check the build execution for the newly triggered build and we see that the build is executed, and tests are passed. You can check the test result by clicking on the “Latest Test Results” link.
- The link navigates to the test method and says it is passed.
So, we explored that Jenkins works seamlessly with our .NET Core application on our local. This was the small sample application with fewer configurations and only one simple test. There could be cases where your build may fail, or tests do not pass. In that case, be patient and try to check logs to understand what caused failure and try to fix that. In the next article, we will see how to publish the ASP.NET Core application to Azure App Service.
- 27th November, 2019: Initial version