📜 ⬆️ ⬇️

Phased configuration of Continuous Integration (build, test, deploy) for .NET Core WebApp + GitHub

Phased configuration of Continuous Integration (build, test, deploy) for .NET Core WebApp + GitHub




Hello. Continuous Integration (CI) has long ago penetrated the world of software development and for many is an integral part of it, which allows you to create better code while maintaining ease of development. And, if at first, setting up the CI required considerable effort and money, now it has become much more accessible, easier, and even free. If you are interested in how to configure CI for your .NET Core open-source project, I ask for cat.


Disclaimer


The article will have a lot of links, trivial moments and digressions, do not blame the author for this, you never know what the reader will stumble upon.


Although F # is chosen as the main language of the demonstration project, the manual is fully compatible with projects written in C #. F # is selected because This article and its associated repository is the basis for the second publication - “Building a complete web application on F # + Giraffe from scratch.”, which is scheduled for June.


Table of contents



Entry and necessary tools


The article uses a demo repository . For each chapter in the repository created tags , a complete list of which can be found at the end of the article.


If you want to repeat what is written in the article you will need:



Create your repository


Tag: InitialMaster


Let's get started. First of all, we need some sort of version control system . I will use git and github


Create a new repository on GitHub, select the template for the .gitignore file and the project license. The .gitignore file is needed to ensure that no unnecessary files get into your repository (for example, the results of the build process). A license is needed so that you can understand the scope of permitted actions with your code. For this project, I chose the VisualStudio template and MIT license.


After creating the repository, we need to clone it - remove its full copy and place it on the local machine. To do this, install Git locally and execute the command:


git clone PATH_TO_YOUR_REPOSITORY 

Now you have a local repository associated with the remote repository on GitHub. Keep in mind, Git has some good documentation, so if you stumble on something, you should be here .


The version control system is not the newest invention. The first VCS appeared already in 1982 (although some date its appearance even to 1972). More information about the history of the development of the tool without which modern development is almost impossible, can be found here . But Git appeared relatively recently - in 2005, thanks to Linus Torvald, the key creator of Linux.

New project


Tag: NewFSharpProject


Now that we have a repository, we are ready to create our project. Go to the repository folder and run the command to create a new project.


 dotnet new web -lang F# 

It is important that in order for this command to work you need to install the .NET Core SDK . If you are working under Windows, most likely you will need to restart the OS in order for the system to pick up new paths for dotnet.exe. And if you are not ready for F # yet (and this is a very fun language, I recommend), you can not pass the lang parameter and then dotnet will create a C # web application for you.


Having executed this command, you will receive three new files:



Despite the minimalism of this is enough to run your hello world.


Now let's agree on the project structure. Each project must be located in its own separate folder, and the root folder will contain only configuration files, regardless of projects.


As a result, we should have something like this structure (further, I will do all the manipulations with the solution through Visual Studio):


- FSharpWebAppWithCIDemo // main project folder


- - BLL // project with basic logic


- - WebServer // web server and its settings.


Important! In F #, the order of files and projects matters. Files that are located above the project tree do not have access to files that are located below the tree. This means that our web server will be able to access any of the projects (it is at the bottom), but the project with business logic will have to be content only with its own code. On the one hand, it is somewhat unusual, on the other hand, it immediately structures the code. Why, for example, the database to know about some kind of web server, right? In general, the less one module knows about other modules, the less chance there is to break it while working on some other module. In other words - low coupling high cohision


And one more, while still important moment concerning Linux systems. As you know, projects written on .NET Core are cross-platform, and can be executed on Linux systems. But the file describing our entire project entirely (.sln file) is not quite cross-platform. Therefore, if you work under Windows OS, the paths to the projects in this file will not be written completely correctly - using the bekslesh symbol: "\". Unfortunately, this is a problem now. It will be fixed soon. But if, at the time of assembly, on the server or on your local machine, you will see an error of the form:


  error MSB4025: The project file could not be loaded. Could not find file ... MySuperProject.fsproj.metaproj. 

Most likely this means that you need to go to the .sln file and manually change the "\" to "/".


Now our project is ready. Collect it, check that it is successfully assembled and let's move on.


The roots of the tradition of writing hello world date back to 1974, when the Programming in C: A Tutorial guide appeared. It is significant that the code examples described in the manual are no longer compiled by the latest compilers.

CI - Build


Tag: TravisSupport


We already have a working F # web application. It would be possible to start the development directly, but then the article would not be about that. So we will start setting up our - CI process and start it from the simplest - setting up the build.


Actually, CI is not a service or a tool. This is an approach to programming, the main and simplified idea of ​​which is frequent commits, their automatic verification and delivery of the result to the end user. Therefore, when I say that we will configure CI, this means that we will configure an automatic build process for each pull request, running tests and analyzing their results. And the results of all this will be displayed immediately under the pull request, so we will always be aware of who and how exactly broke our project.


Let's create a new branch and name it TravisSupport. By the way, if you are doing some kind of new feature, it is nice to do it in a separate branch, and not in the master. First, you will be independent of your colleagues and their commits. Secondly, in your local branch you can make any commits without fear that they will fall into the main branch and break something. And thirdly, my favorite advantage is that if you make a merge with the --squash flag, then all your commits will merge into one and look as if there were no 100,500 attempts, and everything turned out the first time. Most importantly, do not forget to delete the source branch later; if you continue the work in it and try to commit again, you can get a conflict.


But, more to the point. For CI, we need a tool that will build our project, test it, and do what we ask. I have chosen Travis-CI as such a tool. It's free for open source, relatively simple, and I have some experience with it.


To integrate with Travis we need:



The first item is quite simple. Open up https://travis-ci.org/ and log in there with your GitHub account. Then add your repository to the list of available. If you have not seen your repository, use the SyncAccount button.


The second point is much more interesting. The CI control of the travis-a process is accomplished using the .travis.yml file. Here is the documentation . Copy this file to the root of the project and let's look at what is written in it.


 language: csharp dotnet: 2.1.4 sudo: false env: global: - DOTNET_CLI_TELEMETRY_OPTOUT: 1 script: - dotnet build FSharpWebAppWithCIDemo.sln -c Release 


This is the simplest and most basic CI script. In simple words, with each pull request, we try to build our build. Going - all is well. Not going - we will see a warning right in GitHub and in the mail. The launch conditions of the CI process are easily configured both in the .travis.yml itself and in the project settings on the site. And if you are interested in additional features of Travis (for example, the choice of OS) then you are here


Once again, if during the build you will encounter an error: "MSB4025, could not find file ... .fsproj.metaproj" try replacing beksleshi with slashes in the .sln file.


By the way, if you look at the build process, you will see that it runs under Linux, which is good news.


And, of course, do not forget to add a well-deserved badge in the readme. It can be found in your Travis CI project.


If you like the visibility of badges, I recommend to look here . If you are not enough, you can create your own badge.

CI Test


Tag: CodeCov


So it's time to test. In general, we have already violated the principles of TDD , without writing tests before writing the code. So it's time to fix it.


Under the Bll project, create a new BllTest project and add BllTest.fs there. In the same project, install xUnit
Let me remind you that the structure of our project should now look like this:


- FSharpWebAppWithCIDemo


- - blll


- - bllltest


- - WebServer


In the Bll project, create a new bll.fs file with the Say module and the hello function (we again violated TDD by writing the code before the tests)


 namespace Bll module Say = open System let hello() = "Hello user #" + Guid.NewGuid().ToString() 

And test it, namely that the result of calling this function will always be different from the previous one. Which, by the way, is not guaranteed, because there is a non-zero probability that when generating two GUIDs we may get two of the same. True, most likely, until you wait for this event the sun goes out, but still there is a chance.


In fact, neither the code itself nor the test itself is important to us (after all, you have already heard this before, have you?). It is only important to have them in order to integrate correctly with Travis and CodeCov. Run the test manually, make sure it passes and let's continue. After we got the first test, we need Travis to launch this test. For this, in .travis.yml you need to add another line to the script section


 - dotnet test -c Release --no-build BllTest/BllTest.fsproj 

Everything is obvious here - we run the tests without the build (since the build artifacts have already been obtained in the previous step) than we save ourselves time.


But this is not enough. We need code coverage statistics. For this we need a great tool coverlet.msbuild which is embedded in msbuild and creates reports in different formats, including the opencover we need . Open the Nuget tab (or run the command from the console) and install this package for the BllTest project. In other projects it is not needed. After that, change the previous line in .travis.yml to this:


  - dotnet test -c Release --no-build BllTest/BllTest.fsproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover 

Let me remind you that the full version of .travis.yml can be collected here.


You can run the same command from under the console to make sure everything works. At the same time you will see the current code coverage of your project.


So, we have tests, they run, and even some report on code coverage is visible. But this is not enough either. Now we need someone else who can process this report and report its results. Here Codecov is useful to us, which is also free for OpenSource projects. Login to Codecov using your GitHub account and add the project you need. Finally, the last time we update .travis.yml - we add a new section after_script.


  after_script: - bash <(curl -s https://codecov.io/bash) 

When I saw this example I sobbed. Before that, I killed about three hours to start sending the report to coverall, but here everything turned out to be so simple ... Thank you guys for making me happy.


Now that all the preparations have been made, we can make a commit and go to receive our well-deserved badge with 100% coverage.


Some people call the author of TDD Kent Beck , but he himself says that he has just rediscovered the methodology, which he read about a long time ago in some ancient book on programming.

CI Deployment


Tag: DeployToAzure


Take a breath, drink coffee, the end of infrastructure works is near. We begin preparations for the deployment process.


In short, deployment is the process of delivering the results of our work (build artefacts) for execution. This can be done by hand, or in automatic mode, that as a lazy person I like much more. I’ll show you how to set up a deployment in Azure (but this is only because I already have an account there and there are still a couple of dollars left). If this does not suit you, you can use build artifacts that Travis will prepare for you. It is enough to change the dotnet build to dotnet publish and send the results to your server, for example:



And much more


But now not about it, but about Azure. Deploying configuration is relatively simple and (most pleasant) managed from the outside by Azure itself. I'll tell you now.


First we need to create our own web application. This is done very simply. We come into Azure , then Create a resource -> Web App or simply by this link . There we choose the name of our future site, the subscription (subscription is the place where you will be charged money, so it’s better to choose free, for example for students) and the OS where our server will be deployed. Since we use the core, you can choose both Linux and Windows. I choose Windows as I feel more comfortable, but in general there is no difference. Create your own web site, check that it really works and let's start setting up deployment. For this, you need to add two files to the project root folder:



At first glance, build.cmd looks pretty scary, but quite trivial things happen inside:



After we added these files, we only need to connect our web application with the repository on GitHub. To do this, select our application, then DeploymentOptions -> Github -> Project -> Branch. By the way, you can also configure load tests. Everything, it now remains to wait until everything is synchronized and deactivated.


The code name of the project, which then turned into Azure was "Project Red Dog".

Git hooks


Talking about CI and not mentioning git hooks would probably be wrong. Moreover, it is the hooks that are the instrument that made the features described in the article possible.


Git hooks, or interceptors, are a special mechanism that allows custom scripts to be executed before or immediately after important events in your repository. Using them, you can modify commits, change log, do automatic formatting and in general everything that is enough rights in the system. By default, they are in .git / hooks.


A bit out of style, but dotnet also has hooks , such as pre-build and post-build. They also allow you to execute custom scripts.

Results


Today, we have learned how to set up a full CI cycle for a project based on a Git repository. However, one of the main questions still remained unanswered - whether you need a CI as such. One side:


... of time, singing takes only a small amount, and, by the way, the whole carriage benefits from this singing ... ©

On the other hand, if you are doing a POC or if your deadlines have been burned for a long time, probably, CI will not have a yard code.


In other words - to use CI or not to use is up to you. But if you have not tried it yet, I recommend it for tasting.


Tags



Links



With all due respect.


')

Source: https://habr.com/ru/post/354682/


All Articles