<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Georgi Marokov</title>
    <description>The latest articles on DEV Community by Georgi Marokov (@gmarokov).</description>
    <link>https://dev.to/gmarokov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F161922%2F52feb6c1-049a-438c-8f98-75aac370ace3.jpg</url>
      <title>DEV Community: Georgi Marokov</title>
      <link>https://dev.to/gmarokov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gmarokov"/>
    <language>en</language>
    <item>
      <title>Analyze ASP.NET Core with React SPA in SonarCloud</title>
      <dc:creator>Georgi Marokov</dc:creator>
      <pubDate>Thu, 10 Jun 2021 21:58:32 +0000</pubDate>
      <link>https://dev.to/gmarokov/analyze-asp-net-core-with-your-react-spa-in-sonarcloud-5goj</link>
      <guid>https://dev.to/gmarokov/analyze-asp-net-core-with-your-react-spa-in-sonarcloud-5goj</guid>
      <description>&lt;p&gt;&lt;a href="https://sonarcloud.io/"&gt;SonarCloud&lt;/a&gt; is well known cloud based tool for Static Code Analysis which supports most of the popular programming languages - JavaScript, TypeScript, Python, C#, Java and counting. The tool is also known as &lt;a href="https://www.sonarqube.org/"&gt;SonarQube&lt;/a&gt; which is the self hosted version of the analyzer. SonarCloud is completely free for public repositories and SonarQube is even open sourced. These characteristics make it my go-to tool for static code analysis for this project - setup SonarCloud for ASP.NET Core with React single page application. &lt;/p&gt;

&lt;p&gt;This post is the second part from the series for Static Code Analysis for .NET Core projects. In the previous post we learned what Static Code Analysis is and introduced well known tools for the job. If you missed &lt;a href="https://dev.to/gmarokov/static-code-analysis-for-your-net-projects-3l0d"&gt;that post you can check it out here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The agenda for today is: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overview of the different source control management platforms in SonarCloud&lt;/li&gt;
&lt;li&gt;Available options for analyzing your ASP.NET Core SPA app&lt;/li&gt;
&lt;li&gt;Build pipeline in GitLab&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will use React for the demo, but you can use whatever framework you need for the job. React/Angular/Vue or any other - it doesn't really matter, the flow stays the same, only the build or test running commands may differ.&lt;/p&gt;

&lt;p&gt;Shall we begin? Let's deep dive!&lt;/p&gt;

&lt;h1&gt;
  
  
  Different source control management platforms
&lt;/h1&gt;

&lt;p&gt;SonarCloud works with the most popular SCM platforms - GitHub, GitLab, BitBucket and Azure DevOps. Different platforms but the declarative yml pipeline execution is what they all have in common. &lt;/p&gt;

&lt;p&gt;Good to know is that SonarCloud provides 2 scanners - 1 for Dotnet projects and 1 for everything else. The good news is that the dedicated Dotnet scanner can also analyze files from your frontend app - JavaScript, TypeScript, CSS and HTML files.&lt;/p&gt;

&lt;p&gt;Lets quickly go over the platforms and focus on GitLab with a full blown setup from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;If you are using GitHub there is huge chance that you are already using GitHub Actions. &lt;/p&gt;

&lt;p&gt;This is the easiest setup because SonarCloud generates pipeline setup for you. Of course you can use other CI tools as Circle CI, Travis CI or any other but you have to setup the dotnet-sonarscanner yourself. Check the &lt;strong&gt;Build pipeline in GitLab&lt;/strong&gt; section as it has pretty relevant scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  BitBucket
&lt;/h2&gt;

&lt;p&gt;Before going into BitBucket beware that the platform (not yet?) supports apps targeting .NET Framework directly, but of course you can always use containers for the purpose. &lt;/p&gt;

&lt;p&gt;SonarCloud doesn't provide any ready to go templates for .NET Core projects and BitBucket's pipeline. You still need to install and configure everything yourself. &lt;/p&gt;

&lt;h2&gt;
  
  
  Azure DevOps
&lt;/h2&gt;

&lt;p&gt;I read somewhere that dotnet-sonarscanner was developed with the partnership of Microsoft so no wonder the best integration with SonarCloud is with the famous Azure DevOps platform. &lt;/p&gt;

&lt;p&gt;To enable SonarCloud in your pipelines first you need to install SonarCloud extension from Visual Studio marketplace and then follow the super descriptive guide which mostly involved clicking and can be easily accomplished with the GUI builder.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitLab
&lt;/h2&gt;

&lt;p&gt;Nothing differs from the BitBucket setup. Later in the post comes full setup in GitLab. &lt;/p&gt;

&lt;h2&gt;
  
  
  Local (Manually)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Using the VSCode extension Sonar Dotnet gives you the ability to directly analyze from the editor. All the setup is through the GUI and reports are pushed to SonarCloud.&lt;/li&gt;
&lt;li&gt;Using the CLI - To use the CLI you must have .NET SDK, Java and the scanner installed and run the commands from the CI setup directly in the terminal. Check the requirements in the &lt;a href="https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-msbuild/"&gt;official docs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Available options for analysis
&lt;/h1&gt;

&lt;p&gt;On the road to analyze the combined single page application, we have two paths we can choose to take. &lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Analyze frontend and backend at once
&lt;/h3&gt;

&lt;p&gt;The dedicated scanner for .NET projects possess the power to also scan JS, TS, HTML, CSS etc. files. We only need to include frontend's files with wildcard in the &lt;code&gt;.csproj&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ItemGroup&amp;gt;
    &amp;lt;!-- Don't publish the SPA source files, but do show them in the project files list --&amp;gt;
    &amp;lt;Content Remove="Frontend\**" /&amp;gt;
    &amp;lt;None Remove="Frontend\**" /&amp;gt;
    &amp;lt;None Include="Frontend\**" Exclude="Frontend\node_modules\**" /&amp;gt;
&amp;lt;/ItemGroup&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you are using .NET Core 3.1 and above, the default template includes the frontend in your ASP.NET Core project in a common way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Analyze frontend and backend separately
&lt;/h3&gt;

&lt;p&gt;This option is useful when you have a monorepo with your backend and frontend in it, but they have a separate startup process or even different teams working on them. This option will require to create a 2 separate projects in SonarCloud. The option will also require to use the default SonarCloud analyzer for your frontend. &lt;/p&gt;

&lt;h1&gt;
  
  
  Build pipeline in GitLab
&lt;/h1&gt;

&lt;p&gt;Let's recap everything we discussed so far and put it to work. To cover most of the cases for setuping SonarCloud analysis, I will try to walk you through the whole setup with a example project from the ASP.NET Core with React SPA sample with a separate scan tasks for frontend and backend. &lt;/p&gt;

&lt;p&gt;Before we start lets create empty &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file in the root directory.&lt;/p&gt;

&lt;p&gt;For GitLab CI file reference checkout official docs: &lt;a href="https://docs.gitlab.com/ee/ci/yaml/gitlab_ci_yaml.html"&gt;https://docs.gitlab.com/ee/ci/yaml/gitlab_ci_yaml.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;Starting with the creation of our frontend Sonar project which needs to be done manually. Just throw some descriptive name and a project key and you are ready to go. Once done, Sonar will provide &lt;strong&gt;SONAR_TOKEN&lt;/strong&gt; and &lt;strong&gt;SONAR_HOST_URL&lt;/strong&gt;. Make sure to add them as Environment variables. &lt;/p&gt;

&lt;p&gt;Next step is to define the variables for the CI job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;SONAR_USER_HOME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"${CI_PROJECT_DIR}/.sonar"&lt;/span&gt;  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Defines&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;analysis&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;
  &lt;span class="n"&gt;GIT_DEPTH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt;  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Tells&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;branches&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;analysis&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that comes the stage definitions of the job. In this case we will have two - one for frontend and one for the backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;frontend&lt;/span&gt;
  &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;backend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the frontend's actual stage definition with the following task. You can have as many task for a stage as you like but we will stick to just one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;frontend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
  &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frontend&lt;/span&gt; 
  &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sonarsource&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
    &lt;span class="n"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"${CI_JOB_NAME}"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
  &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;Frontend&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;scanner&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;projectKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frontend&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;organization&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gmarokov&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; 
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exclusions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/node_modules/**,/build/**,**/__tests__/**"&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inclusions&lt;/span&gt;&lt;span class="p"&gt;=**/&lt;/span&gt;&lt;span class="n"&gt;__tests__&lt;/span&gt;&lt;span class="p"&gt;/**&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;javascript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lcov&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reportPaths&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"coverage/lcov.info"&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testExecutionReportPaths&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reports/test-report.xml"&lt;/span&gt;
  &lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;merge_requests&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;master&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot is happening in this task so lets walkthrough: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;frontend.build.test.analyze&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;The name of the job, its up to you to give it a descriptive name&lt;/p&gt;

&lt;p&gt;&lt;code&gt;stage: frontend&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;The name of the stage which this task belongs to. Must be predefined which we did above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;We&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt; 
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sonarsource&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
    &lt;span class="n"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we specify a Docker image which comes with sonar-scanner-cli preinstalled. This Scanner CLI is used for all languages except for Dotnet as I mentioned above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"${CI_JOB_NAME}"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We specify the cache and not download the image every time we run the job. This should be good.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;Frontend&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;npm&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing fancy here, regular npm stuff but note that tests are run with coverage report and special &lt;code&gt;jest-sonar-reporter&lt;/code&gt; in the &lt;code&gt;package.json&lt;/code&gt; which converts test result data to Generic Test Data which is one of the supported formats by SonarCloud.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;scanner&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;projectKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frontend&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;organization&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gmarokov&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; 
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exclusions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/node_modules/**,/build/**,**/__tests__/**"&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inclusions&lt;/span&gt;&lt;span class="p"&gt;=**/&lt;/span&gt;&lt;span class="n"&gt;__tests__&lt;/span&gt;&lt;span class="p"&gt;/**&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;javascript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lcov&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reportPaths&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"coverage/lcov.info"&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Dsonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testExecutionReportPaths&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"reports/test-report.xml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here comes the actual scan. Required parameters are &lt;strong&gt;projectKey&lt;/strong&gt;, &lt;strong&gt;organization&lt;/strong&gt; and the early added &lt;strong&gt;SONAR_TOKEN&lt;/strong&gt; and &lt;strong&gt;SONAR_HOST_URL&lt;/strong&gt; which are taken from the env variables. &lt;/p&gt;

&lt;p&gt;Then comes the configuration of the source directories, directories to exclude, test directories and the paths to the generated reports for coverage and test execution. &lt;/p&gt;

&lt;p&gt;More about the parameters can be found here: &lt;a href="https://docs.sonarqube.org/latest/analysis/analysis-parameters/"&gt;https://docs.sonarqube.org/latest/analysis/analysis-parameters/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And our frontend is good to go. Coming next is the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;For the backend another project needs to be created manually. Since we already have environment variable with the name of &lt;strong&gt;SONAR_TOKEN&lt;/strong&gt;, you can save the token for this project as &lt;strong&gt;SONAR_TOKEN_BACKEND&lt;/strong&gt; for example. We will manually provide it anyway. &lt;/p&gt;

&lt;p&gt;When it comes to the backend scan, it will be a little different since we will use the dedicated scanner for Dotnet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;backend&lt;/span&gt;
  &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gmarokov&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;5.0&lt;/span&gt;
  &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;sonarscanner&lt;/span&gt; &lt;span class="n"&gt;begin&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"sonar.example.backend"&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"gmarokov-1"&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"$SONAR_TOKEN_BACKEND"&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"$SONAR_HOST_URL"&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exclusions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"**/Migrations/**, /Frontend"&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opencover&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reportsPaths&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"**/coverage.opencover.xml"&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/Backend/Backend.Api"&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/Backend/Backend.Api.Tests"&lt;/span&gt;
        &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testExecutionReportPaths&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"SonarTestResults.xml"&lt;/span&gt;
   &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="n"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sln&lt;/span&gt;
   &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sln&lt;/span&gt; &lt;span class="p"&gt;--&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="n"&gt;trx&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CollectCoverage&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CoverletOutputFormat&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;opencover&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ExcludeByFile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"**/Migrations/*.cs%2CTemplates/**/*.cshtml%2Ccwwwroot/%2C**/*.resx"&lt;/span&gt;
   &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trx2sonar&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;./&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;./&lt;/span&gt;&lt;span class="n"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;SonarTestResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;
   &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;sonarscanner&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sonar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"$SONAR_TOKEN_BACKEND"&lt;/span&gt;
  &lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;branches&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;master&lt;/span&gt;
    &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's walkthrough the whole task:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;image: gmarokov/sonar.dotnet:5.0&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Again Docker image which will be used to spin a container on which we will execute our task. This image have Dotnet SDK, Java runtime, SonarDotnet and Dotnet-Trx2Sonar global tools. The image can be found on &lt;a href="https://hub.docker.com/r/gmarokov/sonar.dotnet"&gt;DockerHub&lt;/a&gt; which looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="err"&gt;# &lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dotnet&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;SDK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Java&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;,*&lt;/span&gt; &lt;span class="n"&gt;SonarDotnet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dotnet&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Trx2Sonar&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;
&lt;span class="n"&gt;FROM&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;mcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;focal&lt;/span&gt;
&lt;span class="n"&gt;ENV&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;PATH&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"$PATH:/root/.dotnet/tools"&lt;/span&gt;

&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="err"&gt;# &lt;/span&gt;&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Java&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;jre&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="err"&gt;# &lt;/span&gt;&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;SonarCloud&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;--&lt;/span&gt;&lt;span class="k"&gt;global&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sonarscanner&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Install&lt;/span&gt; &lt;span class="n"&gt;Trx2Sonar&lt;/span&gt; &lt;span class="n"&gt;converter&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="p"&gt;--&lt;/span&gt;&lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trx2sonar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might spot the following suspicious parameter:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/p:ExcludeByFile="**/Migrations/*.cs%2CTemplates/**/*.cshtml%2Ccwwwroot/%2C**/*.resx"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's because of the the underling PowerShell parser fails to parse the comma as separator so we need to use encoded value.  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;dotnet-trx2sonar -d ./ -o ./Backend/SonarTestResults.xml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The dotnet-trx2sonar tool will help us to convert .trx files (Visual Studio Test Results File) generated by Xunit to Generic Test Data which is the format specified by SonarCloud. The converted file will help us to browse the tests in SonarCloud UI. &lt;/p&gt;

&lt;p&gt;Anddd that's it! Pipeline is ready to go and provide analyzes on every CI run. I also added some nice badges to indicate the SonarCloud analysis status directly in the repo. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://gitlab.com/gmarokov/sonar-aspnet-react-example"&gt;The full demo project can found on GitLab here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Benefits of these type of analyses are enormous and setup can be dead simple. Yes, delivery is important, but static code analysis compliments it perfectly making delivery more predictable, secure and stable by catching common pitfalls and violations as early as the developer writes code or commits. &lt;/p&gt;

&lt;p&gt;If you haven't used any static code analysis tools before, now you don't have any excuse not to! &lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://codeburst.io/code-coverage-in-net-core-projects-c3d6536fd7d7"&gt;https://codeburst.io/code-coverage-in-net-core-projects-c3d6536fd7d7&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.sonarsource.com/t/coverage-test-data-generate-reports-for-c-vb-net/9871"&gt;https://community.sonarsource.com/t/coverage-test-data-generate-reports-for-c-vb-net/9871&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dotnetthoughts.net/static-code-analysis-of-netcore-projects/"&gt;https://dotnetthoughts.net/static-code-analysis-of-netcore-projects/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sonarcloud.io/documentation/analysis/scan/sonarscanner-for-msbuild/"&gt;https://sonarcloud.io/documentation/analysis/scan/sonarscanner-for-msbuild/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sonarcloud.io/documentation/analysis/scan/sonarscanner/"&gt;https://sonarcloud.io/documentation/analysis/scan/sonarscanner/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>react</category>
      <category>sonarcloud</category>
    </item>
    <item>
      <title>Static Code Analysis for your .NET projects</title>
      <dc:creator>Georgi Marokov</dc:creator>
      <pubDate>Sat, 01 May 2021 18:55:02 +0000</pubDate>
      <link>https://dev.to/gmarokov/static-code-analysis-for-your-net-projects-3l0d</link>
      <guid>https://dev.to/gmarokov/static-code-analysis-for-your-net-projects-3l0d</guid>
      <description>&lt;h1&gt;
  
  
  What is Static Code Analysis
&lt;/h1&gt;

&lt;p&gt;Every developer wants to write predictive, maintainable and high quality software. Unfortunately that's not always the case because of our human nature - we do make mistakes. That's why we try to automate all the things related to software development lifecycle: testing, deploying, running applications.&lt;/p&gt;

&lt;p&gt;But what about the codebase? What do we do to enforce minimally complex and maintainable code, ensure proper code styles standards, prevent common pitfalls and violations, and predict what the code would do at runtime?&lt;/p&gt;

&lt;p&gt;By applying RULES defined by your team, the platform or the programming language. And that's what Static Code Analysis is all about.&lt;/p&gt;

&lt;p&gt;Static Code Analysis can be simple manual inspection such as code review or automated via some of the tools we will overview in this blog post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep digging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Eric Dietrich wrote very explanatory article about what exactly Static Analysis is here:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.ndepend.com/static-analysis-explanation-everyone/"&gt;https://blog.ndepend.com/static-analysis-explanation-everyone/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you are curious about Dynamic Analysis you can also check out these articles:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://securityboulevard.com/2021/02/dynamic-code-analysis-a-primer/"&gt;https://securityboulevard.com/2021/02/dynamic-code-analysis-a-primer/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/analysis-tools-dev/dynamic-analysis"&gt;https://github.com/analysis-tools-dev/dynamic-analysis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.overops.com/blog/static-vs-dynamic-code-analysis-how-to-choose-between-them/"&gt;https://www.overops.com/blog/static-vs-dynamic-code-analysis-how-to-choose-between-them/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post is Part 1 from the Static Analysis series. In the next post we will setup SonarCloud for a ASP.NET Core + React SPA project in CI pipeline. Check it out &lt;a href="https://dev.to/gmarokov/analyze-asp-net-core-with-your-react-spa-in-sonarcloud-5goj"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Where to use Static Code Analysis
&lt;/h1&gt;

&lt;p&gt;I found plenty of NuGet packages, IDE extensions and external services available on the market. That was hard to digest and probably I might miss some very helpful tools. Would be great if you guys share your opinion or favorite tools for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  In development
&lt;/h2&gt;

&lt;p&gt;Using build-time code analysis in Visual Studio /Code (or other preferred tool), we enable developers to quickly understand what rules are being broken. This enables them to fix code earlier in the development lifecycle, and we can avoid builds that fail later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extensions for Visual Studio Code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;OmniSharp - &lt;a href="https://github.com/OmniSharp/omnisharp-roslyn"&gt;https://github.com/OmniSharp/omnisharp-roslyn&lt;/a&gt;
A go-to tool for C# development in VSC.&lt;/li&gt;
&lt;li&gt;Roslynator - &lt;a href="https://github.com/JosefPihrt/Roslynator"&gt;https://github.com/JosefPihrt/Roslynator&lt;/a&gt;
A collection of 500+ analyzers, refactorings and fixes for C#, powered by Roslyn.&lt;/li&gt;
&lt;li&gt;DevSkim - &lt;a href="https://github.com/microsoft/devskim"&gt;https://github.com/microsoft/devskim&lt;/a&gt;
DevSkim is a framework of IDE extensions and language analyzers that provide inline security analysis in the dev environment as the developer writes code.&lt;/li&gt;
&lt;li&gt;SonarLint - &lt;a href="https://www.sonarlint.org/vscode"&gt;https://www.sonarlint.org/vscode&lt;/a&gt;
Even that this extension doesn't scan your .NET projects it's still super useful for your frontend html, css, js, ts files.&lt;/li&gt;
&lt;li&gt;Sonar Dotnet - &lt;a href="https://github.com/yagoluiz/sonar-dotnet-vscode/"&gt;https://github.com/yagoluiz/sonar-dotnet-vscode/&lt;/a&gt;
Easy connect to SonarCloud from your development environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Extensions for Visual Studio
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Roslynator - &lt;a href="https://github.com/JosefPihrt/Roslynator"&gt;https://github.com/JosefPihrt/Roslynator&lt;/a&gt;
Again the famous Roslynator analyzers for Visual Studio.&lt;/li&gt;
&lt;li&gt;ReSharper - &lt;a href="https://www.jetbrains.com/resharper/"&gt;https://www.jetbrains.com/resharper/&lt;/a&gt;
This is more than just analysis tool. If you haven't heard of ReSharper, definitely should be checked out.&lt;/li&gt;
&lt;li&gt;NDepend - &lt;a href="https://www.ndepend.com/"&gt;https://www.ndepend.com/&lt;/a&gt;
The "Swiss Army Knife" for .NET Developers, Architects and Teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Rider - &lt;a href="https://www.jetbrains.com/rider/"&gt;https://www.jetbrains.com/rider/&lt;/a&gt;
Another great IDE for .NET developers which comes with the power of ReSharper.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  In build pipelines
&lt;/h2&gt;

&lt;p&gt;NuGet packaged analyzers are the easiest, and they will automatically run as your project builds on the build agents. When a build encounters a code quality error, you can immediately fail the build, send alerts, or apply any other actions you and your team needs.&lt;/p&gt;

&lt;p&gt;.NET Core SDK 3.0 or later, comes with included analyzers for Open APIs previously known as Swagger. To enable the analyzer in your project, include the IncludeOpenAPIAnalyzers property in the project file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PropertyGroup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IncludeOpenAPIAnalyzers&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;IncludeOpenAPIAnalyzers&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;PropertyGroup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NuGet packages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Microsoft recommended code quality rules and .NET API usage rules - &lt;a href="https://www.nuget.org/packages/Microsoft.CodeAnalysis.NetAnalyzers/"&gt;https://www.nuget.org/packages/Microsoft.CodeAnalysis.NetAnalyzers/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Microsoft's CSharp analyzers for ASP.NET Core MVC - &lt;a href="https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.Api.Analyzers"&gt;https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.Api.Analyzers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Roslynator analyzers as NuGet package - &lt;a href="https://www.nuget.org/packages/Roslynator.Analyzers"&gt;https://www.nuget.org/packages/Roslynator.Analyzers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SonarCloud analyzers - &lt;a href="https://www.nuget.org/packages/SonarAnalyzer.CSharp/"&gt;https://www.nuget.org/packages/SonarAnalyzer.CSharp/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Check for Async/await misuses - &lt;a href="https://www.nuget.org/packages/AsyncFixer"&gt;https://www.nuget.org/packages/AsyncFixer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;An implementation of StyleCop's rules using Roslyn - &lt;a href="https://www.nuget.org/packages/StyleCop.Analyzers/"&gt;https://www.nuget.org/packages/StyleCop.Analyzers/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security analyzers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security static code analyzer for .NET - &lt;a href="https://www.nuget.org/packages/SecurityCodeScan.VS2019/"&gt;https://www.nuget.org/packages/SecurityCodeScan.VS2019/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;DevSkim is a framework and language analyzer that provides inline security analysis - &lt;a href="https://www.nuget.org/packages/Microsoft.CST.DevSkim/"&gt;https://www.nuget.org/packages/Microsoft.CST.DevSkim/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Different CI tools may provide their own tool for security analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only Azure DevOps - &lt;a href="https://secdevtools.azurewebsites.net/helpcredscan.html"&gt;https://secdevtools.azurewebsites.net/helpcredscan.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Only GitLab - &lt;a href="https://docs.gitlab.com/ee/user/application_security/sast/index.html"&gt;https://docs.gitlab.com/ee/user/application_security/sast/index.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub - &lt;a href="https://github.com/marketplace?category=code-quality&amp;amp;type=apps"&gt;https://github.com/marketplace?category=code-quality&amp;amp;type=apps&lt;/a&gt;
Last but not least. GitHub's community driven marketplace provides so many tools for code quality, security and everything else you can think of.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NuGet packages for the Test projects&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides diagnostic analyzers to warn about incorrect usage of NSubstitute in C# - &lt;a href="https://www.nuget.org/packages/NSubstitute.Analyzers.CSharp"&gt;https://www.nuget.org/packages/NSubstitute.Analyzers.CSharp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code Analyzers for projects using xUnit.net - &lt;a href="https://www.nuget.org/packages/xunit.analyzers"&gt;https://www.nuget.org/packages/xunit.analyzers&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  External services
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SonarCloud - &lt;a href="https://sonarcloud.io/"&gt;https://sonarcloud.io/&lt;/a&gt;
My go-to tool for .NET projects. They even have a separate scanner for .NET. Pretty nice integration with Azure DevOps. Free for public projects.&lt;/li&gt;
&lt;li&gt;Embold - &lt;a href="https://embold.io/"&gt;https://embold.io/&lt;/a&gt;
Fairly new tool with Free plan for 1M executable-lines-of-code for public repositories.&lt;/li&gt;
&lt;li&gt;CodeBeat - &lt;a href="https://codebeat.co/projects/gitlab-com-autohub-autohub-web-master"&gt;https://codebeat.co/&lt;/a&gt;
Free for public repositories.&lt;/li&gt;
&lt;li&gt;CodeFactor - &lt;a href="https://www.codefactor.io/dashboard"&gt;https://www.codefactor.io/&lt;/a&gt;
1 private and unlimited free repositories.&lt;/li&gt;
&lt;li&gt;CodeClimate - &lt;a href="https://codeclimate.com/github/gmarokov/dotnet-trx2sonar"&gt;https://codeclimate.com/&lt;/a&gt;
50 free repositories.&lt;/li&gt;
&lt;li&gt;Codacy - &lt;a href="https://www.codacy.com/pricing"&gt;https://www.codacy.com/&lt;/a&gt;
Paid service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And many more counting. These are the one I found easy to get started without installing and configuring additional software.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In first issues raised by static code analysis might be considered as overhead, but static code analysis brings huge benefits in long term which can be summarized to but not only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have the confidence to release more frequently.&lt;/li&gt;
&lt;li&gt;This results in having a quicker TTM (Time to Market).&lt;/li&gt;
&lt;li&gt;Reduce business risks (data loss, vulnerabilities, application failures, ..)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rules may sometimes get on your way and slow down your development, but you and your team are in charge to establish given rules or completely ignore/disable them.&lt;/p&gt;

&lt;p&gt;In the next post I will configure SonarCloud for ASP.NET Core + React SPA so stay tuned.&lt;/p&gt;

&lt;p&gt;Which are your favorite static code analysis tools? Please share your thoughts in the comments or &lt;a href="https://github.com/gmarokov/worldwildweb-dev-blogs/blob/master/blog-posts/static-code-analysis-for-your-dotnet-projects/static-code-analysis-for-your-dotnet-projects.md"&gt;create a PR in GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy analyzing :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blog.tdwright.co.uk/2018/12/10/seven-reasons-that-roslyn-based-code-analysers-are-awesome/?preview=true"&gt;https://blog.tdwright.co.uk/2018/12/10/seven-reasons-that-roslyn-based-code-analysers-are-awesome/?preview=true&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/visualstudio/code-quality/?view=vs-2019"&gt;https://docs.microsoft.com/en-us/visualstudio/code-quality/?view=vs-2019&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/analysis-tools-dev/static-analysis"&gt;https://github.com/analysis-tools-dev/static-analysis&lt;/a&gt;&lt;/p&gt;

</description>
      <category>analysis</category>
      <category>dotnet</category>
      <category>tools</category>
      <category>sonarcloud</category>
    </item>
    <item>
      <title>Node.js Restful API template with TypeScript, Fastify and MongoDB</title>
      <dc:creator>Georgi Marokov</dc:creator>
      <pubDate>Thu, 20 Feb 2020 14:27:36 +0000</pubDate>
      <link>https://dev.to/gmarokov/node-js-restful-api-template-with-typescript-fastify-and-mongodb-4ceo</link>
      <guid>https://dev.to/gmarokov/node-js-restful-api-template-with-typescript-fastify-and-mongodb-4ceo</guid>
      <description>&lt;h1&gt;
  
  
  Why
&lt;/h1&gt;

&lt;p&gt;Have you recently started a new Node.js API project? Did you use some template or started the project from scratch?&lt;br&gt;
I was asking the same questions myself and I was looking for minimal boilerplate for a while. There were so many options that it was hard to pick one.&lt;br&gt;
Most of them are using Express.js, others are using ES5 or lack test setup.&lt;br&gt;
So I decided to spin one on my own and reuse it in the future. Here is &lt;a href="https://github.com/gmarokov/node-fastify-mongo-api"&gt;the repo at GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How
&lt;/h1&gt;

&lt;p&gt;My setup has the following characteristics:&lt;/p&gt;

&lt;h2&gt;
  
  
  API
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node version 10 or later&lt;/li&gt;
&lt;li&gt;TypeScript for obvious reasons&lt;/li&gt;
&lt;li&gt;Fastify for its asynchronous nature and being faster than Express or Restify&lt;/li&gt;
&lt;li&gt;Nodemon in development for watching for changes and restart the server&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MongoDB with Mongoose&lt;/li&gt;
&lt;li&gt;Docker for MongoDB service&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Jest for being the de facto in Node testing&lt;/li&gt;
&lt;li&gt;In memory Mongod server for easily mock the DB&lt;/li&gt;
&lt;li&gt;Coverall for coverage collector after Jest report is generated&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code formatting and static analysis
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint config&lt;/li&gt;
&lt;li&gt;Prettier config attached to the linter&lt;/li&gt;
&lt;li&gt;Editor config&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Swagger UI for API documentation&lt;/li&gt;
&lt;li&gt;Postman collections attached from testing the endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Continuous integration in Travis CI.
Steps:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Run tests&lt;/li&gt;
&lt;li&gt;Collect coverage and pass it to Coverall&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And thats it! I hope it's minimal enough.&lt;br&gt;
Please share some ideas for improvement. I thought of API versioning but Fastify seems to support that out of the box.&lt;br&gt;
API key authentication was also something I was considering, but there were so many available options of implementations. If you have something in mind would love to discuss it in the comments.&lt;br&gt;
Happy coding!&lt;/p&gt;

</description>
      <category>node</category>
      <category>fastify</category>
      <category>typescript</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Configure your dev Windows machine with Ansible</title>
      <dc:creator>Georgi Marokov</dc:creator>
      <pubDate>Sun, 10 Nov 2019 09:44:01 +0000</pubDate>
      <link>https://dev.to/gmarokov/configure-your-dev-windows-machine-with-ansible-41aj</link>
      <guid>https://dev.to/gmarokov/configure-your-dev-windows-machine-with-ansible-41aj</guid>
      <description>&lt;p&gt;Ansible is well known it the IT operations fields with its fantastic automation abilities.&lt;br&gt;
You can do whatever you want with Windows too if it's a Powershell, bat script or one of the more than the hundreds modules.&lt;br&gt;
I will use it to configure my personal machine and save the hustle every time I step on new one.&lt;br&gt;
It's not a big deal to install a few programs but I'm sure this will repay in the long term. Can be pretty useful for configuring multiple machines too.&lt;br&gt;
Using Ansible to target localhost on Linux is like click-click-go, but It's different when it's comes to Windows.&lt;br&gt;
We need to install WSL on Windows, Ansible on WSL, Enable WinRm on Windows and finally control it from WSL.&lt;br&gt;
And all this happens on your localhost.&lt;/p&gt;
&lt;h1&gt;
  
  
  Install Ansible on WSL
&lt;/h1&gt;

&lt;p&gt;From within PowerShell run the following commands.&lt;br&gt;
Enable WSL:&lt;br&gt;
&lt;code&gt;Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Install Ubuntu distribution but you may choose to install whatever distro you want:&lt;br&gt;
&lt;code&gt;Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1604 -OutFile Ubuntu.appx -UseBasicParsing&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Start your WSL and update packages:&lt;br&gt;
&lt;code&gt;sudo apt-get update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Install Ansible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt update
sudo apt install ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install packages for WinRM support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install python-pip
sudo pip install pywinrm
sudo pip install xmltodict
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Enable WinRM
&lt;/h1&gt;

&lt;p&gt;By default WinRM works only for Private or Domain networks. You can skip that by providing parameter to &lt;code&gt;Enable-PSRemoting -SkipNetworkProfileCheck&lt;/code&gt; but I don't suggest doing that. Instead make your trusted network private.&lt;br&gt;
Then enable WinRM:&lt;br&gt;
&lt;code&gt;Enable-PSRemoting&lt;/code&gt; running it in Powershell.&lt;/p&gt;

&lt;p&gt;Enable Basic Auth:&lt;br&gt;
&lt;code&gt;Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Enable Unencrypted connection:&lt;br&gt;
&lt;code&gt;Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $true&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Run the playbook
&lt;/h1&gt;

&lt;p&gt;Using &lt;code&gt;ansible-pull&lt;/code&gt; run the playbook which install Chocolatey and a few packages from it. Full details can found in the &lt;a href="https://github.com/gmarokov/ansible-win-postinstall"&gt;repo&lt;/a&gt;. Provide your username and password for your Windows machine.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ansible-pull –U https://github.com/gmarokov/ansible-win-postinstall.git -e ansible-user=your_win_user ansible_password=your_win_user_password&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I'm sure you as developer make a lot of tweaks to your os, me too. Having a few more tweaks to add, would be great to share some ideas and extend it even further.&lt;br&gt;
I also created a playbooks for &lt;a href="https://github.com/gmarokov/ansible-playbook-postinstall-ubuntu"&gt;Ubuntu&lt;/a&gt; and &lt;a href="https://github.com/gmarokov/ansible-playbook-postinstall-fedora"&gt;Fedora&lt;/a&gt;, check them out if you are using one of this distros.&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>ansibleplaybook</category>
      <category>windows</category>
    </item>
    <item>
      <title>WordPress with WP-CLI on Bash on Ubuntu on Windows 10</title>
      <dc:creator>Georgi Marokov</dc:creator>
      <pubDate>Fri, 01 Nov 2019 17:54:50 +0000</pubDate>
      <link>https://dev.to/gmarokov/wordpress-with-wp-cli-on-bash-on-ubuntu-on-windows-10-4dpg</link>
      <guid>https://dev.to/gmarokov/wordpress-with-wp-cli-on-bash-on-ubuntu-on-windows-10-4dpg</guid>
      <description>&lt;p&gt;At first sight this sounds ridiculous. In fact it sounds absurd. But it’s not, if you heard of the new Microsoft feature — Bash on Ubuntu on Windows.&lt;/p&gt;

&lt;h4&gt;
  
  
  Windows 10’s Anniversary Update offered a big new feature for developers: A full, Ubuntu-based Bash shell that can run Linux software directly on Windows. This is made possible by the new “Windows Subsystem for Linux” Microsoft is adding to Windows 10.
&lt;/h4&gt;

&lt;p&gt;In this post, I will setup fully functional WordPress installation with WP-CLI on top of LAMP server which will be installed on my Linux Subsystem through Windows 10.&lt;/p&gt;

&lt;p&gt;Let’s do this!&lt;/p&gt;

&lt;h2&gt;
  
  
  First we need to install Bash on Ubuntu on Windows
&lt;/h2&gt;

&lt;p&gt;Tutorial how to do it, can be found &lt;a href="http://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/"&gt;here&lt;/a&gt;. After the installation is completed, run the app as administrator. If you would like to go with different user than root, you can read &lt;a href="http://www.howtogeek.com/261417/how-to-change-your-user-account-in-windows-10s-ubuntu-bash-shell/"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  LAMP stack is the next task
&lt;/h2&gt;

&lt;p&gt;WordPress requires PHP, MySQL and HTTP server. We can go with Apache, so LAMP toolset is all we need. This command will install PHP, MySQL and Apache in a moment:&lt;br&gt;
&lt;code&gt;$ sudo apt-get install lamp-server^&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  When we have our server ready we can start with the fun part — installing our command-line interface for WordPress
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Note that you must have PHP 5.3.29 or later and the WordPress version 3.7 or later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Download the wp-cli.phar file via curl:&lt;br&gt;
&lt;code&gt;$ curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now lets check, if it is running:&lt;br&gt;
&lt;code&gt;$ php wp-cli.phar --info&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To use WP-CLI from the command line by typing wp, make the file executable and move it somewhere in your PATH. For example:&lt;br&gt;
&lt;code&gt;$ chmod +x wp-cli.phar&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ mv wp-cli.phar /usr/local/bin/wp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Check, if it is working:&lt;br&gt;
&lt;code&gt;$ wp --info&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If everything went okay, you should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ wp --info
PHP binary: /usr/bin/php5 PHP version: 5.5.9-1ubuntu4.14
php.ini used: /etc/php5/cli/php.ini
WP-CLI root dir: /home/wp-cli/.wp-cli
WP-CLI packages dir: /home/wp-cli/.wp-cli/packages/
WP-CLI global config: /home/wp-cli/.wp-cli/config.yml
WP-CLI project config: WP-CLI version: 0.23.0$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Run our local WordPress installation
&lt;/h2&gt;

&lt;p&gt;Аfter we have our environment and tools ready, playing with the WP-CLI makes the new local WP installation a few commands away.&lt;/p&gt;

&lt;p&gt;Navigate to:&lt;br&gt;
&lt;code&gt;$ cd ../var/www/html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is where our WP will live. Remove the default &lt;code&gt;index.php&lt;/code&gt; file.&lt;br&gt;
Also, now is a good time to start our Apache and MySQL services:&lt;br&gt;
&lt;code&gt;$ rm index.html&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ service apache2 start&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ service mysql start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s download our WP core files:&lt;br&gt;
&lt;code&gt;$ wp core download&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will download the latest version of WordPress in English (&lt;code&gt;en_US&lt;/code&gt;). If you want to download another version or language, use the &lt;code&gt;--version&lt;/code&gt; and &lt;code&gt;--locale&lt;/code&gt; parameters. For example, to use the Bulgarian localization and 4.2.2 version, you would type:&lt;br&gt;
&lt;code&gt;$ wp core download --version=4.2.2 --locale=bg_BG&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once the download is completed, you can create the &lt;code&gt;wp-config.php&lt;/code&gt; file using the &lt;code&gt;core config&lt;/code&gt; command and passing your arguments for the database access here:&lt;br&gt;
&lt;code&gt;$ wp core config --dbname=databasename --dbuser=databaseuser --dbpass=databasepassword --dbhost=localhost --dbprefix=prfx_&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will use the arguments and create a &lt;code&gt;wp-config.php&lt;/code&gt; file.&lt;br&gt;
Using the db command, we can now create our datebase:&lt;br&gt;
&lt;code&gt;$ wp db create&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will use the arguments from &lt;code&gt;wp-config.php&lt;/code&gt; and do the job for us.&lt;br&gt;
Finally, to install WordPress, use the &lt;code&gt;core install&lt;/code&gt; command:&lt;br&gt;
&lt;code&gt;$ wp core install --url=example.com --title=WordPress Website Title --admin_user=admin_user --admin_password=admin_password --admin_email=admin@example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you’ve got your success message, restart Apache:&lt;br&gt;
&lt;code&gt;$ service apache2 restart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After the restart is completed, open your browser and type &lt;a href="http://localhost/"&gt;http://localhost/&lt;/a&gt; and enjoy your brand new WP installation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that every time you start the application you must first start up MySQL and Apache services:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ service mysql start|restart|stop&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ service apache2 start|restart|stop&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Final words
&lt;/h1&gt;

&lt;p&gt;I like WP-CLI a lot for saving me time in doing boring stuff, but this may seems as a workaround and it probably is. Still, nothing compares to a real Linux environment.&lt;br&gt;&lt;br&gt;
But let’s face the fact we are running native Linux software on Windows. That by itself is fantastic. The benefits are unlimited.&lt;/p&gt;

&lt;p&gt;Keep in mind that the Bash on Ubuntu on Windows feature is still in beta, so let’s hope that Microsoft will keep up with the good news.&lt;/p&gt;

&lt;p&gt;Please, share and comment in the section below for your opinion.&lt;/p&gt;

&lt;h1&gt;
  
  
  Further readings
&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://www.howtogeek.com/261383/how-to-access-your-ubuntu-bash-files-in-windows-and-your-windows-system-drive-in-bash/"&gt;How to access your Ubuntu Bash files in windows and your Windows system drive in Bash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.howtogeek.com/261591/how-to-create-and-run-bash-shell-scripts-on-windows-10/"&gt;How to create and run Bash shell scripts on Windows 10&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://wp-cli.org/docs/tools/"&gt;http://wp-cli.org/docs/tools/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>wordpress</category>
      <category>wpcli</category>
      <category>windows</category>
    </item>
    <item>
      <title>Getting started with Ansible and configuring Windows hosts</title>
      <dc:creator>Georgi Marokov</dc:creator>
      <pubDate>Fri, 01 Nov 2019 17:06:14 +0000</pubDate>
      <link>https://dev.to/gmarokov/getting-started-with-ansible-and-configuring-windows-hosts-20nd</link>
      <guid>https://dev.to/gmarokov/getting-started-with-ansible-and-configuring-windows-hosts-20nd</guid>
      <description>&lt;p&gt;Ansible is a configuration management, provisioning and deployment tool which is quickly gaining popularity in the DevOps areas. Managing and working on various platforms including Microsoft Windows.&lt;br&gt;&lt;br&gt;
What makes Ansible stand out of other configuration management tools is that it’s agentless. Which means no software is required on the target host. Ansible uses SSH for communication with Unix based hosts and WinRM for Windows hosts.&lt;br&gt;&lt;br&gt;
Recent announcement from Microsoft’s team is an upcoming fork of OpenSSH for Windows, which would make things ever smoother for DevOps teams managing Windows infrastructure.&lt;/p&gt;

&lt;p&gt;In this post we will get started with Ansible by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Setup of the control machine&lt;/li&gt;
&lt;li&gt; Configure Windows server in order to receive commands from Ansible&lt;/li&gt;
&lt;li&gt; Install Chocolatey and SQL Server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Ansible requires PowerShell version 3.0 and .NET Framework 4.0 or newer to function on older operating systems like Server 2008 and Windows 7.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you covered the requirements, let’s get started with the first step.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup Ansible control machine
&lt;/h2&gt;

&lt;p&gt;As previously mentioned Ansible is agentless, but we need control machine — machine which talks to all of our hosts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ansible can’t run on Windows but there’s a trick
&lt;/h3&gt;

&lt;p&gt;Currently Ansible can only be installed on Unix based machines, but if you are using Windows as your primary OS, you can install Ubuntu subsystem. Read &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10"&gt;this&lt;/a&gt; for further installation details. If you are non Windows user please continue reading.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install Ansible
&lt;/h2&gt;

&lt;p&gt;After the installation of Ubuntu subsystem on Windows (if you had so), lets proceed with the installation of Ansible by opening terminal.&lt;/p&gt;

&lt;p&gt;Install Ubuntu repository management:&lt;br&gt;
&lt;code&gt;$ sudo apt-get install software-properties-common&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets update our system:&lt;br&gt;
&lt;code&gt;$ sudo apt-get update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add Ansible repository:&lt;br&gt;
&lt;code&gt;$ sudo apt-add-repository ppa:ansible/ansible&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then install Ansible:&lt;br&gt;
&lt;code&gt;$ apt-get install ansible&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add Python package manager:&lt;br&gt;
&lt;code&gt;$ apt install python-pip&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add Python WinRM client:&lt;br&gt;
&lt;code&gt;$ pip install pywinrm&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Install XML parser:&lt;br&gt;
&lt;code&gt;$ pip install xmltodict&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If every thing went OK you should be able to get the current version:&lt;br&gt;
&lt;code&gt;$ ansible --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So far, so good. Lets continue with configuration of the tool.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configure Ansible
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Inventory — list of the hosts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Inventory.yml&lt;/strong&gt; is the main configuration file of your hosts addresses separated in groups with descriptive names.&lt;/p&gt;

&lt;p&gt;Let’s create that file and set the example below:&lt;br&gt;
&lt;code&gt;$ vim inventory.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Enter the IP/DNS addresses for your group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[dbservers]
mydbserver1.dns.example 80.69.0.160

[webservers]
mywebserver1.dns.example 80.69.0.162
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure the connection
&lt;/h2&gt;

&lt;p&gt;We are a few steps away from establish connection to the remote servers. Let’s configure the connection itself — credentials, ports, type of connection. The convention is to name the config file based on your group of hosts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you want all of your inventory to use that same configuration file you can name it&lt;/em&gt; &lt;strong&gt;&lt;em&gt;all.yml&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. We will use&lt;/em&gt; &lt;strong&gt;&lt;em&gt;all.yml&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;as all servers will have same credentials and connection type.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s begin by creating folder:&lt;br&gt;
&lt;code&gt;$ mkdir group_vars&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create the file and edit it:&lt;br&gt;
&lt;code&gt;$ vim group_vars/all.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add the configuration details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ansible_user: ansible_user
ansible_password: your_password_here
ansible_port: 5985
ansible_connection: winrm
ansible_winrm_transport: basic
ansible_winrm_operation_timeout_sec: 60
ansible_winrm_read_timeout_sec: 70
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This credentials will be used to access the remote hosts with connection set to WinRM basic authentication. We will create them in the next section.&lt;br&gt;
&lt;em&gt;We use basic authentication but for your production environment you probably want to use more secure schema. See&lt;/em&gt; &lt;a href="https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html?highlight=windows"&gt;&lt;em&gt;this&lt;/em&gt;&lt;/a&gt; &lt;em&gt;article for more info.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configure Windows hosts
&lt;/h2&gt;

&lt;p&gt;Our Windows hosts need to be configured before execute any commands on it. The following PowerShell script will do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create the Ansible user we defined in &lt;strong&gt;all.yml&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Add the user to the Administrators group&lt;/li&gt;
&lt;li&gt; Set WinRM authentication to basic and allow unencrypted connections&lt;/li&gt;
&lt;li&gt; Add Firewall rule for WinRM with your control machine IP address&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open PowerShell on the host and execute the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NET USER ansible_user "your_password_here" /ADD
NET LOCALGROUP "Administrators" "ansible_user" /ADD
Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true
Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $true
netsh advfirewall firewall add rule name="WinRM" dir=in action=allow protocol=TCP localport=5985 remoteip=10.10.1.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the execution is completed we can try to ping our host from the control machine to check that connection is OK. We ping only the DB servers:&lt;br&gt;
&lt;code&gt;$ ansible dbservers -i inventory.yml -m win_ping&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Write our first playbook
&lt;/h2&gt;

&lt;p&gt;Getting back to our Ansible control machine to add a playbook — set of tasks or plays which together form the playbook.&lt;/p&gt;

&lt;p&gt;The target is to install Chocolatey which is the community driven package manager for Windows. After that we will install SQL Server and reboot the server.&lt;/p&gt;

&lt;p&gt;Ansible come with many modules for Windows with a lot of functionalities out of the box. They are prefixed with “win_” like for example win_feature. You can check more &lt;a href="https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html?highlight=windows"&gt;here&lt;/a&gt; for your specific needs.&lt;/p&gt;

&lt;p&gt;Let’s continue with the creation of the playbook file:&lt;br&gt;
&lt;code&gt;$ vim configure-win-server-playbook.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the file describe the playbook as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--------
- hosts: dbservers
  tasks:
   - name: Install Chocolatey
     raw: Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

   - name: Install SQL Server
     win_chocolatey:
     name: sql-server-2017
     state: present

   - name: Reboot to apply changes
     win_reboot:
      reboot_timeout: 3600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute the playbook by typing:&lt;br&gt;
&lt;code&gt;$ ansible-playbook dbservers -i inventory.yml configure-win-server-playbook.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will see each task running and returning status of execution and after reboot we are all ready!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Ansible is really powerful tool. Microsoft and the community is doing really fantastic work for porting Ansible modules to Windows which are written in PowerShell. Yet the plan to have SSH feature on Windows is great too. No matter if your inventory is of physical or virtual servers, you should definitely try out Ansible on your infrastructure for saving time, money and of course avoid human mistakes by manually configure, deploy or provision those environments.&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>windows</category>
      <category>devops</category>
    </item>
    <item>
      <title>Getting started with Hangfire on ASP.NET Core and PostgreSQL on Docker</title>
      <dc:creator>Georgi Marokov</dc:creator>
      <pubDate>Fri, 01 Nov 2019 17:06:14 +0000</pubDate>
      <link>https://dev.to/gmarokov/getting-started-with-hangfire-on-asp-net-core-and-postgresql-on-docker-56ak</link>
      <guid>https://dev.to/gmarokov/getting-started-with-hangfire-on-asp-net-core-and-postgresql-on-docker-56ak</guid>
      <description>&lt;p&gt;Hangfire is an incredibly easy way to perform fire-and-forget, delayed and recurring jobs inside ASP.NET applications. No Windows Service or separate process required. Backed by persistent storage. Open and free for commercial use.&lt;/p&gt;

&lt;p&gt;There are a number of use cases when you need to perform background processing in a web application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mass notifications/newsletter&lt;/li&gt;
&lt;li&gt;batch import from xml, csv, json&lt;/li&gt;
&lt;li&gt;creation of archives&lt;/li&gt;
&lt;li&gt;firing off web hooks&lt;/li&gt;
&lt;li&gt;deleting users&lt;/li&gt;
&lt;li&gt;building different graphs&lt;/li&gt;
&lt;li&gt;image/video processing&lt;/li&gt;
&lt;li&gt;purge temporary files&lt;/li&gt;
&lt;li&gt;recurring automated reports&lt;/li&gt;
&lt;li&gt;database maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and counting..&lt;/p&gt;

&lt;p&gt;We will get started by install and configure the database, then create new ASP.NET Core MVC project, after which we will get to Hangfire and run few background tasks with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup PostgreSQL database
&lt;/h2&gt;

&lt;p&gt;There are more than one way to setup PostgreSQL database. I’m about to use Docker for the purpose, but you can install it directly from the &lt;a href="https://www.postgresql.org/download/" rel="noopener noreferrer"&gt;Postgresql official webisite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you choose do download and install PostgreSQL, skip the following Docker commands. Instead configure you db instance with the parameters from the Docker example.&lt;/p&gt;

&lt;p&gt;Else we need Docker installed and running. Lets proceed with pulling the image for PostgreSQL. Open terminal and run:&lt;br&gt;
&lt;code&gt;$ docker pull postgresql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We have the image, let's create a container from it and provide username and password for the database:&lt;br&gt;
&lt;code&gt;$ docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create ASP.NET Core MVC project
&lt;/h2&gt;

&lt;p&gt;So far we have the db up and running, continuing with the creation of the MVC project and configure it to use our database.&lt;/p&gt;

&lt;p&gt;Create new folder and enter it:&lt;br&gt;
&lt;code&gt;$ mkdir aspnet-psql-hangfire &amp;amp;&amp;amp; cd aspnet-psql-hangfire&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When creating new project, you can go with whatever you want from the list of available dotnet project templates. I'll stick to mvc.&lt;br&gt;
&lt;code&gt;$ dotnet new mvc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next install Nuget package for Entity Framework driver for PostgreSQL:&lt;br&gt;
&lt;code&gt;$ dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add empty dbcontext:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.EntityFrameworkCore;

namespace aspnet_psql_hangfire.Models
{
    public class DefaultDbContext : DbContext
    {
        public DefaultDbContext(DbContextOptions&amp;lt;DefaultDbContext&amp;gt; options)
            : base(options) { }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restore the packages by running:&lt;br&gt;
&lt;code&gt;$ dotnet restore&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;appsettings.json&lt;/code&gt; and enter the connection string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "connectionStrings": {
        "defaultConnection":
            "Host=localhost;
            Port=5433;
            Username=postgres;
            Password=postgres;
            Database=aspnet-psql-hangfire-db"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },
    "AllowedHosts": "*"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The framework must know that we want to use PostgreSQL database so add the driver to your &lt;code&gt;Startup.cs&lt;/code&gt; file within the ConfigureServices method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddEntityFrameworkNpgsql().AddDbContext&amp;lt;DefaultDbContext&amp;gt;(options =&amp;gt; {
    options.UseNpgsql(Configuration.GetConnectionString("defaultConnection"));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are ready for a initial migration:&lt;br&gt;
&lt;code&gt;$ dotnet ef migrations add InitContext &amp;amp;&amp;amp; dotnet ef database update&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Install Hangfire
&lt;/h2&gt;

&lt;p&gt;Let’s continue with final steps — install packages for Hangfire:&lt;br&gt;
&lt;code&gt;$ dotnet add package Hangfire.AspNetCore &amp;amp;&amp;amp; dotnet add package Hangfire.Postgresql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add the following using statement to the &lt;code&gt;Startup.cs&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Hangfire;
using Hangfire.PostgreSql;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again in the ConfigureServices method in the &lt;code&gt;Startup.cs&lt;/code&gt;, let Hangfire server to use our default connection string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddHangfire(x =&amp;gt;
    x.UsePostgreSqlStorage(Configuration.GetConnectionString("defaultConnection")));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again in &lt;code&gt;Startup.cs&lt;/code&gt;, but now in Configure method enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseHangfireDashboard(); //Will be available under http://localhost:5000/hangfire"
app.UseHangfireServer();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then restore again the packages by typing:&lt;br&gt;
&lt;code&gt;$ dotnet restore&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create tasks
&lt;/h2&gt;

&lt;p&gt;In the Configure method, below the &lt;code&gt;app.UseHangFireServer()&lt;/code&gt; add the following tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Fire-and-Forget
BackgroundJob.Enqueue(() =&amp;gt; Console.WriteLine("Fire-and-forget"));

//Delayed
BackgroundJob.Schedule(() =&amp;gt; Console.WriteLine("Delayed"), TimeSpan.FromDays(1));

//Recurring
RecurringJob.AddOrUpdate(() =&amp;gt; Console.WriteLine("Minutely Job"), Cron.Minutely);

//Continuation
var id = BackgroundJob.Enqueue(() =&amp;gt; Console.WriteLine("Hello, "));
BackgroundJob.ContinueWith(id, () =&amp;gt; Console.WriteLine("world!"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally run the app:&lt;br&gt;
&lt;code&gt;$ dotnet run&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgmarokov%2Fworldwildweb-dev-blogs%2Fmaster%2Fblog-posts%2Fgetting-started-with-hangfire%2Fassets%2Fimg%2Fhangfire-tasks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgmarokov%2Fworldwildweb-dev-blogs%2Fmaster%2Fblog-posts%2Fgetting-started-with-hangfire%2Fassets%2Fimg%2Fhangfire-tasks.png" title="Hangfire tasks being executed" alt="Hangfire task being executed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Observe the console.&lt;br&gt;
Now go to the dashboard provided by Hangfire at &lt;a href="http://localhost:5000/hangfire" rel="noopener noreferrer"&gt;http://localhost:5000/hangfire&lt;/a&gt; for more task info.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgmarokov%2Fworldwildweb-dev-blogs%2Fmaster%2Fblog-posts%2Fgetting-started-with-hangfire%2Fassets%2Fimg%2Fhangfire-dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgmarokov%2Fworldwildweb-dev-blogs%2Fmaster%2Fblog-posts%2Fgetting-started-with-hangfire%2Fassets%2Fimg%2Fhangfire-dashboard.png" title="Hangfire dashboard" alt="Hangfire dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Keep in mind that the dashboard is only available for localhost connections. If you would like to use it in production, you have to apply authentication methods. There are plenty of tutorials describing how to do that.&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://github.com/gmarokov/aspnet-psql-hangfire" rel="noopener noreferrer"&gt;repo&lt;/a&gt; from the project, I hope you liked it. Happy coding!&lt;/p&gt;

</description>
      <category>aspnet</category>
      <category>hangfire</category>
      <category>postgres</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
