<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://blog.nijveldt.online//feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.nijveldt.online//" rel="alternate" type="text/html" /><updated>2026-03-24T12:14:13+00:00</updated><id>https://blog.nijveldt.online//feed.xml</id><title type="html">Niels’ blog</title><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><entry><title type="html">Use Tailwind instead of bootstrap in your Blazor startup project</title><link href="https://blog.nijveldt.online//blazor-remove-bootstrap-add-tailwind/" rel="alternate" type="text/html" title="Use Tailwind instead of bootstrap in your Blazor startup project" /><published>2024-01-10T09:00:00+00:00</published><updated>2024-01-10T09:00:00+00:00</updated><id>https://blog.nijveldt.online//blazor-remove-bootstrap-add-tailwind</id><content type="html" xml:base="https://blog.nijveldt.online//blazor-remove-bootstrap-add-tailwind/"><![CDATA[<p>When creating a new Blazor project, by default, it always includes Bootstrap as a CSS framework. This is used for both the layout and component styling. And, of course, this is fine because it’s easy to use and set up, and Bootstrap is still well maintained. But I can imagine that you will probably start from scratch in most cases. In my case, I wanted to start with <a href="https://tailwindcss.com/">TailwindCSS</a>, so I created a Blazor starter project with Tailwind.</p>

<p><img src="/assets/20240110/BlazorTailwind.png" alt="picture" width="250" /></p>

<p>I wanted to use Tailwind since it’s one of the more modern CSS frameworks as of today. It’s highly flexible and suits well with creating reusable UI components.
However, how does this work with Blazor?
Since Tailwind CSS output is generated based on the classes used in your HTML. There is this fantastic Nuget package called <a href="https://github.com/Practical-ASP-NET/Tailwind.Extensions.AspNetCore">Tailwind.Extensions.AspNetCore</a>, which helps make this work within your Blazor project.
Just follow the steps in the readme, and you are good to go.</p>

<p>I added this additional configuration to make everything work with a .NET 8 solution setup with a Blazor Server and Blazor WebAssembly project.
By doing so, Tailwind will also pull all the classes from components in the Blazor WebAssebmly project.</p>

<figure class="highlight"><pre><code class="language-typescript" data-lang="typescript"><span class="kr">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">content</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">./**/*.{razor,html}</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">../BlazorTailwind.Client/**/*.{razor,html}</span><span class="dl">'</span><span class="p">],</span>
    <span class="na">theme</span><span class="p">:</span> <span class="p">{</span> <span class="p">},</span>
    <span class="na">plugins</span><span class="p">:</span> <span class="p">[],</span>
<span class="p">}</span></code></pre></figure>

<p>After that, I removed all other styling and styling sheets from the projects and, one by one, restyled the pages and components with the Tailwind classes. I tried to make it look as similar to the original default Blazor template as possible. The result can be found here: <a href="https://blazortailwind.azurewebsites.net/">https://blazortailwind.azurewebsites.net/</a>.
The source code can be found here: <a href="https://github.com/NielsNijveldt/BlazorTailwind">https://github.com/NielsNijveldt/BlazorTailwind</a>.</p>

<h2 id="pipeline">Pipeline</h2>
<p>I also added a GitHub Actions pipeline, which builds the Blazor Project, compiles and minifies the Tailwind output, and then publishes it to Azure.
For the Tailwind path, I added this script to the package.json.</p>

<figure class="highlight"><pre><code class="language-console" data-lang="console"><span class="go">npx tailwindcss -i ./Styles/tailwind.css -o ./wwwroot/css/tailwind.css --minify</span></code></pre></figure>

<h2 id="hot-reload">Hot reload</h2>
<p>If you want to develop your application in combination with hot reload, make sure to start the app with “Start without debugging” (or CTRL + F5). Otherwise hot reload doesn’t seem to work. You shouldn’t need to restart your application after creating a component with a newly used utility class since the installed NuGet package ensures it gets added to the CSS output file.</p>

<p><img src="/assets/20240110/HotReload.gif" alt="picture" /></p>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="Blazor" /><category term="TailwindCSS" /><category term="Bootstrap" /><category term=".NET" /><summary type="html"><![CDATA[When creating a new Blazor project, by default, it always includes Bootstrap as a CSS framework. This is used for both the layout and component styling. And, of course, this is fine because it’s easy to use and set up, and Bootstrap is still well maintained. But I can imagine that you will probably start from scratch in most cases. In my case, I wanted to start with TailwindCSS, so I created a Blazor starter project with Tailwind.]]></summary></entry><entry><title type="html">Troubleshoot Azure App Service instances for Linux</title><link href="https://blog.nijveldt.online//switch-instance-azure-app-service/" rel="alternate" type="text/html" title="Troubleshoot Azure App Service instances for Linux" /><published>2024-01-02T11:00:00+00:00</published><updated>2024-01-02T11:00:00+00:00</updated><id>https://blog.nijveldt.online//switch-instance-azure-app-service</id><content type="html" xml:base="https://blog.nijveldt.online//switch-instance-azure-app-service/"><![CDATA[<p>We experienced CPU and memory issues with our Blazor application a few weeks back.
To find out what was going on, we needed to create a memory dump to see what threads were causing issues.</p>

<p>When running an application in Azure App Services with a single instance, it’s easy to debug or troubleshoot that instance.
With <a href="https://github.com/projectkudu/kudu/wiki">Kudu</a>, you can find all sorts of debug information.
If that instance has a memory leak or serious CPU issues, then you can open Kudu and go to the Process Explorer page.
From there, you can collect and download a memory dump from the application.</p>

<p><img src="/assets/20240102/KuduProcessExplorerWindows.png" alt="picture" /></p>

<p>When running multiple instances of your application, this isn’t much harder.
As shown in the image above, you can easily switch between instances. This also includes the familiar name, which can be found in Application Insights.
So it’s easy to navigate from the log or graph, which shows a memory or CPU issue, to the specific instance in Kudu and troubleshoot it.</p>

<p>However, in our case, the application runs on Linux.
For Linux, Kudu has limited UI features to achieve the same thing.
There is no UI control to switch between instances, as shown in the image below.</p>

<p><img src="/assets/20240102/KuduProcessExplorerLinux.png" alt="picture" /></p>

<p>The hard way is to change the ID in the ARRAffinity cookie to the instance you want to troubleshoot.
But to figure out which id is which instance is a challenge.</p>

<p>There is a way to get a better experience.
If you navigate to https://<app-name>.scm.azurewebsites.net/newui (so with /newui appended to your URL) there is this page.
On this page, you find a dropdown to switch between instances.
Unfortunately, the instance name, as shown in Application Insights, is not shown here.</app-name></p>

<p><img src="/assets/20240102/KuduLinuxNewUI.png" alt="picture" /></p>

<p>If you navigate to the Environment page, look up the variable called “COMPUTERNAME”; this shows the instance you can correlate to the logs or graphs you use.
After selecting the correct instance, go to the Process Explorer page and press the Collect Dump button.
Make sure to select the proper process; one process is for Kudu, and the other is for your application.
By clicking the i icon, you can find out which one is which.</p>

<p>After downloading the memory dump, you can open Visual Studio and select Open File.
Then, select the downloaded dump, and you will be ready to read it.
If you select one of the “Debug with …” options, you can find the threads that were active at the time the memory dump was generated.</p>

<h2 id="new-ui">New UI</h2>
<p>I could not find any documentation about this /newui and there is also no direct reference from the App Service in Azure.
Too bad the new ui isn’t the standard, as it is more helpful for Linux apps.
There is <a href="https://techcommunity.microsoft.com/t5/apps-on-azure-blog/new-kudu-ui-for-app-service-on-linux-preview/ba-p/3212270">this older blog</a>, but no follow-up.
Also the version used in that post is still the version of Kudu as used today.</p>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="Azure" /><category term="Kudu" /><summary type="html"><![CDATA[We experienced CPU and memory issues with our Blazor application a few weeks back. To find out what was going on, we needed to create a memory dump to see what threads were causing issues.]]></summary></entry><entry><title type="html">.NET 8 and Blazor: A brief overview of What’s New and Improved</title><link href="https://blog.nijveldt.online//blazor-hosting-types/" rel="alternate" type="text/html" title=".NET 8 and Blazor: A brief overview of What’s New and Improved" /><published>2023-11-15T19:00:00+00:00</published><updated>2023-11-15T19:00:00+00:00</updated><id>https://blog.nijveldt.online//blazor-hosting-types</id><content type="html" xml:base="https://blog.nijveldt.online//blazor-hosting-types/"><![CDATA[<p>Today, Microsoft launched .NET 8, the latest version of .NET and ASP.NET.
In this release, Blazor got some significant improvements; in this post, I will provide a brief overview of the update and the new render modes that greatly benefit the creation of Blazor applications.</p>

<p>Download .NET 8 here: <a href="https://dotnet.microsoft.com/en-us/download">https://dotnet.microsoft.com/en-us/download</a>. Don’t forget to upgrade your .NET 7 applications, as the support of .NET 7 is until May 14, 2024, while the new version is supported until November 10, 2026.</p>

<p><img src="/assets/20231115/postvisual.png" alt="picture" />
<em>Visual created by Dall-E</em></p>

<h2 id="render-modes">Render modes</h2>
<p>With the previous version of Blazor you had to choose between two hosting models. You could choose between Blazor Server and Blazor WebAssembly. It was not always easy to choose because both have benefits and downsides. You may have experienced inconveniences for both hosting models while implementing specific scenarios.
After the release of .NET 7 Microsoft started a project called “Blazor United” to provide a better experience creating web apps with .NET.
Later on, they renamed it to “Full stack web UI with Blazor”.</p>

<p>With .NET 8, Microsoft offers flexibility with both hosting models. Also, a new solution is provided called Streamrendering.
You can mix and match Blazor Server, Blazor WebAssembly, and Streamrendering to develop a web app that covers all your needs with less or no hacking compared to before.
It’s also possible to choose none of these options. Then the static HTML is rendered without the possibility of interactivity.</p>

<h3 id="streamrendering">StreamRendering</h3>
<p>StreamRendering is a solution where a request from the client for a specific page returns an initial response (with placeholders) and allows loading data from a different source. Once the source is retrieved, the placeholders will be updated in this long-running task.
See this simple example:</p>

<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="n">@page</span> <span class="s">"/products"</span>
<span class="n">@attribute</span> <span class="p">[</span><span class="nf">StreamRendering</span><span class="p">(</span><span class="k">true</span><span class="p">)]</span>

<span class="n">@using</span> <span class="n">BlazorShop</span><span class="p">.</span><span class="n">Client</span><span class="p">.</span><span class="n">Components</span>
<span class="n">@using</span> <span class="n">BlazorShop</span><span class="p">.</span><span class="n">Model</span>

<span class="n">@inject</span> <span class="n">HttpClient</span> <span class="n">Http</span>
<span class="p">&lt;</span><span class="n">div</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="n">h2</span><span class="p">&gt;</span><span class="n">Products</span><span class="p">&lt;/</span><span class="n">h2</span><span class="p">&gt;</span>
    <span class="nf">@if</span> <span class="p">(</span><span class="n">result</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="p">&lt;</span><span class="n">LoadingIndicator</span> <span class="p">/&gt;</span>
    <span class="p">}</span>
    <span class="k">else</span>
    <span class="p">{</span>
        <span class="p">&lt;</span><span class="n">div</span><span class="p">&gt;</span>
            <span class="nf">@foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">product</span> <span class="k">in</span> <span class="n">result</span><span class="p">.</span><span class="n">Products</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="p">&lt;</span><span class="n">ProductDetails</span> <span class="n">Product</span><span class="p">=</span><span class="s">"@product"</span> <span class="p">/&gt;</span>
            <span class="p">}</span>
        <span class="p">&lt;/</span><span class="n">div</span><span class="p">&gt;</span>
    <span class="p">}</span>
<span class="p">&lt;/</span><span class="n">div</span><span class="p">&gt;</span>

<span class="n">@code</span> <span class="p">{</span>
    <span class="k">private</span> <span class="n">PagedResult</span><span class="p">&lt;</span><span class="n">Model</span><span class="p">.</span><span class="n">Product</span><span class="p">&gt;?</span> <span class="n">result</span><span class="p">;</span>

    <span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">OnInitializedAsync</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">result</span> <span class="p">=</span> <span class="k">await</span> <span class="n">Http</span><span class="p">.</span><span class="n">GetFromJsonAsync</span><span class="p">&lt;</span><span class="n">PagedResult</span><span class="p">&lt;</span><span class="n">Model</span><span class="p">.</span><span class="n">Product</span><span class="p">&gt;&gt;(</span><span class="s">"https://dummyjson.com/products"</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>This example will show a loading indicator on the initial response. At the end of the OnInitialized the response will be updated and finalized. Now, the client will render an overview of products instead of the loading indicator.
This is achieved without a SignalR connection (Blazor Server) or WebAssembly files.</p>

<p>If you have buttons or interactive components, by default, those will not respond to the user’s actions. There are, however, a couple of ways to make the page using StreamRendering interactive. You can use the <code class="language-plaintext highlighter-rouge">Enhance</code> attribute if there are forms on the page. See <a href="https://github.com/dotnet/aspnetcore/blob/main/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/Forms/StreamingRenderingForm.razor">this example</a>. Another way to achieve interactivity is to embed a component as child element with either the render mode defined a attribute on the element or by defining a attribute within the component.</p>

<p>A couple of sidenotes:</p>
<ul>
  <li>The  <code class="language-plaintext highlighter-rouge">AfterRender</code> and <code class="language-plaintext highlighter-rouge">OnAfterRenderAsync</code> override will not be called in your page or component since the cycle is done after the <code class="language-plaintext highlighter-rouge">OnInitialized</code></li>
  <li>By choosing “Interactive render mode” as None by creating a new project, you will be able to use StreamingRendering without any of the other render modes</li>
  <li>To achieve certain complexity, you might need to use Javascript</li>
</ul>

<h3 id="rendermodes">Rendermodes</h3>
<p>Blazor offers three rendermodes: <code class="language-plaintext highlighter-rouge">InteractiveServer</code>, <code class="language-plaintext highlighter-rouge">InteractiveWebAssembly</code>, <code class="language-plaintext highlighter-rouge">InteractiveAuto</code>.
You can either specify these on component level or page level.
When specifying <code class="language-plaintext highlighter-rouge">InteractiveServer</code> SignalR will be used to have an interactive component/page. With <code class="language-plaintext highlighter-rouge">InteractiveWebAssembly</code> the webassembly files will be used to render the component/page.
If you choose <code class="language-plaintext highlighter-rouge">InteractiveAuto</code> the best option will be used to render the component/page. It will download the webassembly files (if not available yet). In the meantime, a websocket will be started for SignalR to provide interactivity. The next time this same component/page will be opened the already downloaded webassembly files will be used instead of the SignalR connection.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"something"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Component</span> <span class="err">@</span><span class="na">rendermode=</span><span class="s">"RenderMode.InteractiveServer"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/div&gt;</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="n">@page</span> <span class="s">"/counter"</span>
<span class="n">@rendermode</span> <span class="n">InteractiveAuto</span></code></pre></figure>

<h3 id="interactiveauto">InteractiveAuto</h3>
<p>If you choose <code class="language-plaintext highlighter-rouge">InteractiveAuto</code>, there are a couple of things to consider.
Because the component’s code can run either server or client side, you need to make sure that the resources (eg, API, Database) are publicly available. Otherwise, the component will break.
The best way to use this feature is by choosing the option “Auto (Server and Webassembly)” while creating a new project. This will create two projects in your new solution. One project to provide the server logic and one (client) project to provide the webassembly logic.
Since the server project has a project reference to the client project you only have to define component and pages once. By placing them in the client project, you can use them in both projects and with both render modes.</p>

<h3 id="deployment">Deployment</h3>
<p>To deploy the Blazor app, you only need to publish the “server” project. Since it’s a server solution, you need an Azure app service to host it (or something similar outside Azure). If you want to host Blazor WebAssembly as a static web app, pick one of the Blazor Web Assembly project templates when creating a new project. However, none of the render modes mentioned earlier will be available since it’s a Blazor WebAssembly solution.</p>

<p>The upgrade for Blazor is an excellent enhancement of what we already had. It will make it easier to create modern web applications.
For a complete overview of the .NET 8 update, read both the <a href="https://devblogs.microsoft.com/dotnet/announcing-dotnet-8/">.NET 8</a> and <a href="https://devblogs.microsoft.com/dotnet/announcing-asp-net-core-in-dotnet-8/">ASP.NET Core</a> blog posts from Microsoft.
Soon, I will post more content with sample projects, such as Blazor Identity UI, using TailwindCSS within a Blazor .NET 8 solution, and more.</p>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="Blazor" /><category term="ASP.NET" /><category term="Dotnet 8" /><category term="Razor" /><category term="Web Assembly" /><category term="SSR" /><category term="SignalR" /><summary type="html"><![CDATA[Today, Microsoft launched .NET 8, the latest version of .NET and ASP.NET. In this release, Blazor got some significant improvements; in this post, I will provide a brief overview of the update and the new render modes that greatly benefit the creation of Blazor applications.]]></summary></entry><entry><title type="html">SSO on GitHub organization with Azure AD</title><link href="https://blog.nijveldt.online//sso-on-github-organization-with-azure-ad/" rel="alternate" type="text/html" title="SSO on GitHub organization with Azure AD" /><published>2020-04-02T18:30:00+00:00</published><updated>2020-04-02T18:30:00+00:00</updated><id>https://blog.nijveldt.online//sso-on-github-organization-with-azure-ad</id><content type="html" xml:base="https://blog.nijveldt.online//sso-on-github-organization-with-azure-ad/"><![CDATA[<p>GitHub offers <a href="https://help.github.com/en/github/authenticating-to-github/about-authentication-with-saml-single-sign-on">SAML single sign-on(SSO)</a> in the enterprise plan. I created an enterprise account as a trial to see how this works together with Azure AD. GitHub offers documentation to help to set this up, but it’s quite a lot and also some things are not up to date anymore. In this post I will try to explain how to do it and what you could expect of it.</p>

<p><img src="/assets/20200402/shane-avery-OHnvp41aDzE-unsplash.jpg" alt="picture" />
<em>Photo by Shane Avery on <a href="https://unsplash.com/photos/OHnvp41aDzE" target="_blank">Unsplash</a></em></p>

<p>First you will need both a GitHub enterprise organization and an Azure AD. If you don’t have GitHub enterprise, create a free trial for 14 days on <a href="https://github.com/enterprise">this page</a>. Now open both Azure AD and your GitHub organization settings. As the first step we need to create an enterprise application in Azure AD. Click “Add application”, search for GitHub and then select “github.com”. Fill in a custom name or use the default value and create the application. After creation you will see a couple of options. Step 1 is to “Assign users and groups”. Create a couple of users or groups in AD and assign them to this application. By doing this those users will be able to use this connection to sign in to GitHub. Step 2 is to “Set up single sign on”. After opening this you will see a 5 step configuration for single sign-on.</p>

<p><img src="/assets/20200402/AzureAD-Overview.png" alt="picture" /></p>

<ol>
  <li>Press edit on “Basic SAML Configuration” and fill in these fields as:
    <ul>
      <li>Identifier (Entity ID): https://github.com/orgs/<organizationname></organizationname></li>
      <li>Reply URL (Assertion Consumer Service URL): https://github.com/orgs/<organizationname>/saml/consume</organizationname></li>
      <li>Sign on URL: https://github.com/orgs/<organizationname>/sso</organizationname></li>
    </ul>
  </li>
  <li>Press edit on “User Attributes &amp; Claims” and select the required claim. Make sure the “nameidentifier” claim is set as:
    <ul>
      <li>“Email address”</li>
      <li>Source: “Attribute”</li>
      <li>Source attribute: “user.mail”</li>
    </ul>
  </li>
</ol>

<p><img src="/assets/20200402/AzureAD-Settings.png" alt="picture" /></p>

<p>Step 3 and 4 contain information we need to configure in the GitHub settings. Also make sure to download the base64 certificate and open the file in a text editor. Now open the “Settings” option in your GitHub organization. Enable the feature “Enable SAML authentication”, after doing this you can fill in the forms based on the information and certificate from Azure. Beneath the certificate field there is a text line, make sure it is set to “Your SAML provider is using the RSA-SHA256 Signature Method and the SHA256 Digest Method.”. You can do this by press the edit button in the end of the line and select both “SHA256” options.
Now click the “Test SAML configuration” button and login with any account with access to the GitHub application in Azure AD. If everything is setup fine you will see the message “Passed: Successfully authenticated your SAML SSO identity”. Now users should be able to go to https://github.com/orgs/<organizationname>/sso and login to access the GitHub resources. Even if you didn't add them to the users of the organization. Note that you cannot just go https://github.com/login and login with the Azure AD.</organizationname></p>

<p><img src="/assets/20200402/GitHub-Security.png" alt="picture" /></p>

<p>After a user logs in, I would have expected it could access the GitHub resources straightaway. Unfortunately this is not the case. When the user logs in for the first time GitHub asks to create a GitHub account or to login with an existing one. After this a linked identity is added to the account. So will this make sure you only have to be logged in to Azure AD? Unfortunately this is also not true. If you open a new browser and login in Azure AD it will redirect you to GitHub and ask for the password of the linked identity. This feels more like a double sign-on, then a single sign-on.</p>

<h2 id="group-synchronization">Group synchronization</h2>
<p>Also a feature with the Azure AD connection is group synchronization. I would have expected it to synchronize my Azure AD groups to my GitHub organization automatically. However this is not how it works. For example if you want to grant a specific Azure AD group to a specific repository you need to create a group in the organization and use the “Identity Provider Groups” feature. If you select the dropdown it will show all groups from Azure AD. After doing this you can add this group to the repository. Now users from the AD group will be able to access the repository. In my opinion it would have been better if I was able to select Azure AD groups straightaway. If needed this can also be configured with the <a href="https://developer.github.com/v3/teams/team_sync/">GitHub API</a>.</p>

<h2 id="summary">Summary</h2>
<p>Overall the single sign-on feature works fine on GitHub and could be used as additional security option. It’s also easy to configure. However some things could be a little bit better. For example the double login and group synchronization feature could be done differently.</p>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="GitHub" /><category term="Azure" /><category term="SSO" /><category term="Azure AD" /><summary type="html"><![CDATA[GitHub offers SAML single sign-on(SSO) in the enterprise plan. I created an enterprise account as a trial to see how this works together with Azure AD. GitHub offers documentation to help to set this up, but it’s quite a lot and also some things are not up to date anymore. In this post I will try to explain how to do it and what you could expect of it.]]></summary></entry><entry><title type="html">Deploy GitHub provisioned application to Azure</title><link href="https://blog.nijveldt.online//deploy-github-provisioned-application-to-azure/" rel="alternate" type="text/html" title="Deploy GitHub provisioned application to Azure" /><published>2020-02-11T18:30:00+00:00</published><updated>2020-02-11T18:30:00+00:00</updated><id>https://blog.nijveldt.online//deploy-github-provisioned-application-to-azure</id><content type="html" xml:base="https://blog.nijveldt.online//deploy-github-provisioned-application-to-azure/"><![CDATA[<p>In my <a href="/provision-github-setup/" target="_blank">last post</a> I described how we were able to provision an application into GitHub. The only problem then was there was no API for managing secrets in GitHub. Luckily two weeks ago <a href="https://developer.github.com/v3/actions/secrets/" target="_blank">the API</a> to manage secrets was released. So to finish the setup, I added a script to create several Azure resources, get credentials from Azure and save them as secret in Azure. In the end a GitHub Actions task can use the credentials to deploy the application to Azure.</p>

<p><img src="/assets/20200211/silas-kohler-C1P4wHhQbjM-unsplash.jpg" alt="picture" />
<em>Photo by Silas Köhler on <a href="https://unsplash.com/photos/C1P4wHhQbjM" target="_blank">Unsplash</a></em></p>

<h3 id="creating-the-azure-resources">Creating the Azure Resources</h3>
<p>I added the Create-AzureResources.ps1 which creates a ResourceGroup, AppPlan and a Web Application. This is all done with the most basic settings. Preferably I wanted to use the publish profile of the Web Application since it’s the first mentioned way to use the <a href="https://github.com/Azure/webapps-deploy" target="_blank">GitHub Action to deploy a Web App</a>. However the Azure Deploy task does only support XML while the <a href="https://docs.microsoft.com/en-us/cli/azure/webapp/deployment?view=azure-cli-latest#az-webapp-deployment-list-publishing-profiles" target="_blank">Azure CLI</a> only returns JSON. Another way to pass credentials to the deploy task is by using the <a href="https://github.com/Azure/login" target="_blank">Azure Login task</a> in combination with creating an Azure Service Principal. The returned result after creating the service principal needs to be stored as a secret inside of GitHub.</p>

<h3 id="storing-the-secret-inside-github">Storing the secret inside GitHub</h3>
<p>So when the credentials are generated with the Azure CLI, the next step is to pass the secret to the GitHub API. According to the documentation it’s advised to use <a href="https://libsodium.gitbook.io/doc/" target="_blank">LibSodium</a> for encrypting the secrets. The idea is to get the public key for the new created GitHub repository and encrypt the secret with this key with the help of LibSodium. Unfortunately there is no up-to-date(!) PowerShell library of LibSodium, so I had to improvise. To reuse the existing Sodium library I imported the .Net dll and used the exposed methods to encrypt my secret in the same way as the C# example of the API documentation.</p>

<figure class="highlight"><pre><code class="language-powershell" data-lang="powershell"><span class="nv">$PublicKeyBytes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="n">System.Convert</span><span class="p">]::</span><span class="n">FromBase64String</span><span class="p">(</span><span class="nv">$PublicKey</span><span class="p">)</span><span class="w">
</span><span class="nv">$EncryptedMessageBytes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="n">Sodium.SealedPublicKeyBox</span><span class="p">]::</span><span class="n">Create</span><span class="p">(</span><span class="nv">$Secret</span><span class="p">,</span><span class="w"> </span><span class="nv">$PublicKeyBytes</span><span class="p">)</span><span class="w">
</span><span class="nv">$EncryptedMessage</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="n">System.Convert</span><span class="p">]::</span><span class="n">ToBase64String</span><span class="p">(</span><span class="nv">$EncryptedMessageBytes</span><span class="p">)</span></code></pre></figure>

<p>So the public key(Base64 string) gets converted to a byte array. Then the SealedPublicKeyBox.Create method from Sodium with the secret (Credentials in JSON string) and the public key (byte array) is used returning a byte array. The byte array then needs to be converted to a Base64 string which can be used in the body to post to the API. Don’t forget to include the Id of the public key!</p>

<h3 id="deploy">Deploy</h3>
<p>When the secret is stored in GitHub the Action can be triggered. The Action is now updated with the following steps:</p>

<p><img src="/assets/20200211/dotnetcore.yml.png" alt="picture" /></p>

<p>After the Action is finished, the application should be deployed to the earlier created Azure resources. The complete code can be found <a href="https://github.com/thijslimmen/GitHub-InnovationDay">here on GitHub</a>. To summarize the scripts creates the following:</p>
<ul>
  <li>A repository in GitHub</li>
  <li>Resources in Azure</li>
  <li>Azure credentials as secret in GitHub</li>
  <li>Check-in application to the GitHub repo</li>
  <li>Triggering GitHub action to build and deploy the application</li>
  <li>Add an issue</li>
  <li>Add a collaborator</li>
</ul>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="GitHub" /><category term="PowerShell" /><category term="Automation" /><category term="DevOps" /><category term="Global DevOps Bootcamp" /><category term="Secrets" /><category term="Sodium" /><summary type="html"><![CDATA[In my last post I described how we were able to provision an application into GitHub. The only problem then was there was no API for managing secrets in GitHub. Luckily two weeks ago the API to manage secrets was released. So to finish the setup, I added a script to create several Azure resources, get credentials from Azure and save them as secret in Azure. In the end a GitHub Actions task can use the credentials to deploy the application to Azure.]]></summary></entry><entry><title type="html">Provision GitHub setup</title><link href="https://blog.nijveldt.online//provision-github-setup/" rel="alternate" type="text/html" title="Provision GitHub setup" /><published>2019-12-16T19:00:00+00:00</published><updated>2019-12-16T19:00:00+00:00</updated><id>https://blog.nijveldt.online//provision-github-setup</id><content type="html" xml:base="https://blog.nijveldt.online//provision-github-setup/"><![CDATA[<p>This year I was part of the team that organized the <a href="https://globaldevopsbootcamp.com/" target="_blank">Global DevOps Bootcamp</a>. An important part of the event was provisioning the setup for all teams. This consisted of creating an Azure DevOps project and Azure setup to have a complete pipeline for an application. During the last Xpirit’s innovation day, I researched the possibility of replacing Azure DevOps with GitHub together with my colleague <a href="https://www.linkedin.com/in/thijs-limmen/" target="_blank">Thijs</a>. In this post, I will share our findings.</p>

<p><img src="/assets/20191216/junior-ferreira-7esRPTt38nI-unsplash.jpg" alt="picture" />
<em>Photo by Júnior Ferreira on <a href="https://unsplash.com/photos/7esRPTt38nI" target="_blank">Unsplash</a></em></p>

<h3 id="goal">Goal</h3>
<p>Our goal was to create a basic setup inside of GitHub with the use of the GitHub API and PowerShell. We decided the following items should be included in our setup:</p>
<ul>
  <li>Create a repository</li>
  <li>Add collaborator(s) to the repository</li>
  <li>Add sample code to the repository</li>
  <li>Create and start a build based on GitHub Actions</li>
  <li>Create and start a release based on GitHub Actions</li>
  <li>Raise an issue</li>
</ul>

<h3 id="creating-the-resources">Creating the resources</h3>
<p><a href="https://developer.github.com/v3/repos/#create" target="_blank">Creating</a> a repository, <a href="https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator" target="_blank">adding collaborators</a> and <a href="https://developer.github.com/v3/issues/#create-an-issue" target="_blank">raising an issue</a> are really easy to do. Just call the corresponding API endpoints and you’re good to go. The <a href="https://developer.github.com/v3/" target="_blank">GitHub API documentation</a> is really clear and easy to follow.
From there the repository can be cloned locally and the sample code can be pushed to GitHub. For this part no API call is needed, just regular GIT commands can be used to achieve this. However you might want to <a href="https://developer.github.com/v3/repos/#get" target="_blank">get the repository</a> and use the clone_url property to make sure you have the right URL.</p>

<h3 id="github-actions">GitHub Actions</h3>
<p>With the Azure DevOps setup the Azure DevOps API was used to create and trigger builds and releases. However for GitHub there isn’t such an API as it seems. To achieve this it’s possible to add a <a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions" target="_blank">predefined yml file</a> inside the repository in a specific folder. So in our case we needed to add a yml file inside the /.github/workflows folder. In the yml file we included dotnet build and dotnet publish to create a package. In the end we included the <a href="https://github.com/Azure/webapps-deploy" target="_blank">Azure Web app deploy task</a>. This task deploys the sample code to Azure. We could have split up the build part and the release to Azure part, but for the time being we merged them. Obviously the Azure web app could also be provisioned as part of this whole setup, but is currently not included. Both improvements could be the next step.</p>

<p><img src="/assets/20191216/yml.png" alt="Publish Code Coverage Result Task" /></p>

<h3 id="secrets">Secrets</h3>
<p>To be able to release something to Azure a secret is needed. This secret should be included inside the repository to be reused and to be safe since it can be encrypted. Also this Azure deploy task uses a secret to deploy to Azure. Then we found out there is no API endpoint for storing secrets inside a repository which is a shame. According to <a href="https://github.community/t5/GitHub-Actions/Github-Apps-to-add-secrets/m-p/28259" target="_blank">this request</a> more GitHub users need this functionality. While writing this post someone from the GitHub team announced they’re currently working on this improvement, but no release date is given. Of course workarounds can be made, but that was not our goal for this tryout. I will follow this request and update this post as soon as it’s available somehow.</p>

<h3 id="the-result">The result</h3>
<p>In the end we have made a couple of PowerShell scripts that cover all planned resources. These scripts can be used to provision a basic setup for an application with a pipeline inside of GitHub. Unfortunately it was disappointing that it’s not possible to store secrets and be able to also automate releases to Azure. Altogether it was a lot of fun to work this out and investigate the possibilities with GitHub.</p>

<p><img src="/assets/20191216/result.png" alt="Publish Code Coverage Result Task" /></p>

<p>Some things for us to keep in mind:</p>
<ul>
  <li>No secret API available at the moment</li>
  <li>Private repositories only allow 4 collaborators to be added</li>
  <li>Builds and releases should be done by yml as it seems no API’s are available</li>
</ul>

<p>The code we made can be found here: <a href="https://github.com/thijslimmen/GitHub-InnovationDay" target="_blank">https://github.com/thijslimmen/GitHub-InnovationDay</a></p>

<p>UPDATE:
In the meantime GitHub launched the API for managing secrets, read about it in <a href="/deploy-github-provisioned-application-to-azure/">my other post</a>. Also private repositories are now able to have <a href="https://github.blog/2020-04-14-github-is-now-free-for-teams/">unlimited collaborators</a>.</p>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="GitHub" /><category term="PowerShell" /><category term="Automation" /><category term="DevOps" /><category term="Global DevOps Bootcamp" /><summary type="html"><![CDATA[This year I was part of the team that organized the Global DevOps Bootcamp. An important part of the event was provisioning the setup for all teams. This consisted of creating an Azure DevOps project and Azure setup to have a complete pipeline for an application. During the last Xpirit’s innovation day, I researched the possibility of replacing Azure DevOps with GitHub together with my colleague Thijs. In this post, I will share our findings.]]></summary></entry><entry><title type="html">Display OpenCover results in Azure DevOps</title><link href="https://blog.nijveldt.online//display-opencover-results-in-azure-devops/" rel="alternate" type="text/html" title="Display OpenCover results in Azure DevOps" /><published>2019-10-30T19:00:00+00:00</published><updated>2019-10-30T19:00:00+00:00</updated><id>https://blog.nijveldt.online//display-opencover-results-in-azure-devops</id><content type="html" xml:base="https://blog.nijveldt.online//display-opencover-results-in-azure-devops/"><![CDATA[<p>So with my first post I managed to run OpenCover in the build and measure the code coverage on my .Net API by end-2-end tests. Of course this is fun, but it would be much more of value if we could also show the results somewhere. So in this post I will explain how to update the build to make this happen. In the end the results will be displayed in an Azure DevOps dashboard or SonarQube/SonarCloud.</p>

<p><img src="/assets/20191025/joshua-earle-Dwheufds6kQ-unsplash.jpg" alt="picture" />
<em>Photo by Joshua Earle on <a href="https://unsplash.com/photos/Dwheufds6kQ" target="_blank">Unsplash</a></em></p>

<h3 id="coverage">Coverage</h3>
<p>To get the coverage attached to the build we can use the <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/test/publish-code-coverage-results?view=azure-devops" target="_blank">Publish Code Coverage Result Task</a>. Because this task needs Cobertura or JaCoCo as input we need to make sure we get this output from OpenCover. Out-of-the-box OpenCover is not able to create such a file. 
Also the OpenCover result file contains paths to probably folders which don’t exist anymore. So in order to fix that we need to replace the paths to the existing application source on the build agent:</p>

<figure class="highlight"><pre><code class="language-powershell" data-lang="powershell"><span class="nv">$content</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Get-Content</span><span class="w"> </span><span class="err">$</span><span class="p">(</span><span class="n">Build.SourcesDirectory</span><span class="p">)</span><span class="n">\opencover-reports\result.xml</span><span class="p">)</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'(\w\:)\\(\w+)\\(\d+)\\(\w+)'</span><span class="p">,</span><span class="w"> </span><span class="s1">'$(Build.SourcesDirectory)'</span><span class="p">;</span><span class="w"> 
</span><span class="p">[</span><span class="n">System.IO.File</span><span class="p">]::</span><span class="n">WriteAllLines</span><span class="p">(</span><span class="w"> </span><span class="s1">'$(Build.SourcesDirectory)\opencover-reports\result.xml'</span><span class="p">,</span><span class="w"> </span><span class="nv">$content</span><span class="p">)</span></code></pre></figure>

<p>After this is done, with <a href="https://github.com/danielpalme/ReportGenerator" target="_blank">ReportGenerator</a> OpenCover output can be transformed into one of the required formats. (and a lot of other formats) So with this command we can make sure we get the right format:</p>

<figure class="highlight"><pre><code class="language-powershell" data-lang="powershell"><span class="n">ReportGenerator.exe</span><span class="w"> </span><span class="s2">"-reports:</span><span class="si">$(</span><span class="n">Build.SourcesDirectory</span><span class="p">)</span><span class="n">\opencover-reports\result.xml</span><span class="s2">" "</span><span class="nt">-targetdir</span><span class="p">:</span><span class="nx">coveragereport</span><span class="s2">" -reporttypes:HTML;Cobertura;SonarQube</span></code></pre></figure>

<p>You could either set the targetdir to a file share or copy the report folder back to the build agent in the end.
ReportGenerator also has to capability to merge multiple coverage files into one file. So if you want to merge multiple test output files into one test result you can use this:</p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">ReportGenerator</span><span class="p">.</span><span class="nf">exe</span> <span class="s2">"-reports:OpenCover.xml;OpenCover2.xml"</span> <span class="s2">"-targetdir:coveragereport"</span> <span class="o">-</span><span class="n">reporttypes</span><span class="ss">:HTML</span><span class="p">;</span><span class="no">Cobertura</span><span class="p">;</span><span class="no">SonarQube</span></code></pre></figure>

<p><img src="/assets/20191025/task.png" alt="Publish Code Coverage Result Task" /></p>

<h3 id="publish-coverage">Publish coverage</h3>
<p>Now we’ve got our Cobertura file (and SonarQube file) we can use the publish code coverage task. Set the Cobertura file as ‘Summary file’ and we are good to go. After running the build you should be able to see the code coverage in the build results. As a final step we can add the <a href="https://marketplace.visualstudio.com/items?itemName=shanebdavis.code-coverage-dashboard-widgets" target="_blank">“Code Coverage Widgets”</a> to a dashboard in Azure Devops. When configuring this widget select our build and choose one of the coverage measurements. Small blocks will show as number/percentage and larger blocks will show graphs.</p>

<p><img src="/assets/20191025/graphs.png" alt="Code Coverage Widgets" /></p>

<h3 id="sonarqubesonarcloud">SonarQube/SonarCloud</h3>
<p>Beside Azure DevOps we can also supply the coverage to SonarQube. Therefore we need to set the ‘sonar.cs.opencover.reportsPaths’ property to the path of the SonarQube.xml created by ReportGenerator. Now the Sonarscanner should be able to upload the file to SonarQube.</p>

<p>For SonarCloud or a newer version of SonarQube you need to set the ‘sonar.coverageReportPaths’ property.</p>

<h3 id="result">Result</h3>
<p>Now code coverage will automatically be updated and published to the desired tool/dashboard. New tests or missing tests will immediately affect the results. By doing this, we avoid the need to publish this by hand and we are always able to get the latest state of coverage for different kinds of tests.</p>

<p>An example of how the pipeline could look like can be found <a href="https://github.com/NielsNijveldt/OpenCover-Scripts/blob/master/pipeline-example.yml" target="_blank">here</a></p>

<p>If you have any questions, feel free to contact me.</p>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="OpenCover" /><category term="Azure DevOps" /><category term="PowerShell" /><category term="IIS" /><category term="Code Coverage" /><category term="Test Automation" /><category term="SonarQube" /><category term="SonarCloud" /><summary type="html"><![CDATA[So with my first post I managed to run OpenCover in the build and measure the code coverage on my .Net API by end-2-end tests. Of course this is fun, but it would be much more of value if we could also show the results somewhere. So in this post I will explain how to update the build to make this happen. In the end the results will be displayed in an Azure DevOps dashboard or SonarQube/SonarCloud. [System.IO.File]::WriteAllLines( ‘$(Build.SourcesDirectory)\opencover-reports\result.xml’, $content)]]></summary></entry><entry><title type="html">Integrate OpenCover with Azure DevOps</title><link href="https://blog.nijveldt.online//integrate-opencover-with-azure-devops/" rel="alternate" type="text/html" title="Integrate OpenCover with Azure DevOps" /><published>2019-10-18T11:00:00+00:00</published><updated>2019-10-18T11:00:00+00:00</updated><id>https://blog.nijveldt.online//integrate-opencover-with-azure-devops</id><content type="html" xml:base="https://blog.nijveldt.online//integrate-opencover-with-azure-devops/"><![CDATA[<p><a href="https://github.com/OpenCover/opencover" target="_blank">OpenCover</a> is a code coverage tool that measures both branch and sequence points for a given .Net application. 
In my case, I wanted to measure code coverage of a .Net web API project. 
The idea is to start OpenCover, run end-2-end tests (or other tests invoking my API) and generate a coverage file. 
This setup gives you insight into how much of your API is covered by, for example, end-2-end tests.</p>

<p><img src="/assets/20191007/kai-dahms-217U8oxGoQ4-unsplash.jpg" alt="picture" />
<em>Photo by Kai Dahms on <a href="https://unsplash.com/photos/217U8oxGoQ4" target="_blank">Unsplash</a></em></p>

<p>To achieve this, I use <a href="https://github.com/OpenCover/opencover/tree/master/main/OpenCover.Console" target="_blank">OpenCover.Console.exe</a> and attach it to the IIS process of the backend application as described in the <a href="https://github.com/OpenCover/opencover/wiki/IIS-Support" target="_blank">wiki of OpenCover</a>. 
This works fine for manually starting OpenCover, but in my Azure DevOps pipeline everything should be automated. 
To do so, I created three PowerShell scripts. 
One to start OpenCover, one to Invoke the start script on another machine and one to close OpenCover and generate a report.</p>

<h3 id="starting-opencover">Starting OpenCover</h3>
<p>The start script stops the current running backend IIS application. After it is stopped the actual OpenCover.Console.exe can be started:</p>

<figure class="highlight"><pre><code class="language-powershell" data-lang="powershell"><span class="n">OpenCover.Console.exe</span><span class="w"> </span><span class="nt">-target</span><span class="p">:</span><span class="nx">C:\Windows\System32\inetsrv\w3wp.exe</span><span class="w"> </span><span class="nt">-targetargs</span><span class="p">:</span><span class="nt">-debug</span><span class="w"> </span><span class="nt">-targetdir</span><span class="p">:</span><span class="nx">C:\iisprojectdir</span><span class="w"> </span><span class="nt">-output</span><span class="p">:</span><span class="nx">C:\reports\opencover-result.xml</span><span class="w"> </span><span class="nt">-filter</span><span class="p">:</span><span class="o">+</span><span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="o">*</span><span class="w"> </span><span class="nt">-register</span><span class="p">:</span><span class="nx">user</span><span class="w"> </span></code></pre></figure>

<p>Once this is completed the backend application is running again and can be used for testing.
In the Task Manager you will now find two processes for the same application.
It might be useful to perform some warmup for the new running instance of your application.</p>

<p>Starting OpenCover should not be done with remote PowerShell.
Remote PowerShell will start a session, start OpenCover and when the task is finished it will close the session.
When the PowerShell session is ended OpenCover will be killed.
This can be avoided by using <a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/invoke-command?view=powershell-6#description" target="_blank">Invoke-Command</a> instead with the <strong>-InDisconnectedSession</strong> parameter:</p>

<figure class="highlight"><pre><code class="language-powershell" data-lang="powershell"><span class="n">Invoke-Command</span><span class="w"> </span><span class="nt">-ComputerName</span><span class="w"> </span><span class="nv">$server</span><span class="w"> </span><span class="nt">-Credential</span><span class="w"> </span><span class="nv">$credential</span><span class="w"> </span><span class="nt">-InDisconnectedSession</span><span class="w"> </span><span class="nt">-ScriptBlock</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">&lt;</span><span class="n">Insert</span><span class="w"> </span><span class="nx">OpenCover</span><span class="w"> </span><span class="nx">Start</span><span class="w"> </span><span class="nx">script</span><span class="err">&gt;</span><span class="w"> </span><span class="p">}</span></code></pre></figure>

<p><strong>Note</strong>: Be aware that the application will be running as the user running the script.</p>

<h3 id="stopping-opencover">Stopping OpenCover</h3>
<p>After testing is done it’s important to not end the OpenCover process itself but the new w3wp process. If the OpenCover process is ended first no coverage file will be generated after it.
Unfortunately, it’s not easy to find this process since OpenCover doesn’t return any information about that process.
To find the process any way we can use Get-WmiObject to get a process based on a name and command line. In this case the start script used the CommandLine <em>“C:\Windows\System32\inetsrv\w3wp.exe” -debug</em>
So in the second script the right w3wp process is searched for and when found the process gets killed. Now OpenCover will generate the coverage file after a couple of seconds. In the end the backend IIS application can be started again in IIS like it was initially running.</p>

<h3 id="pipeline">Pipeline</h3>
<p>Both scripts can be used inside an Azure DevOps pipeline with a test execution in between. When OpenCover is stopped correctly,  the generated result(xml) can be used for reporting. More about this subject will be covered in my next post. Stay tuned!
<img src="/assets/20191007/pipeline.png" alt="Azure Devops" /></p>

<p>The scripts can be found on my <a href="https://github.com/NielsNijveldt/OpenCover-Scripts" target="_blank">GitHub</a>.
Feel free to ask questions!</p>]]></content><author><name>Niels Nijveldt</name><email>niels.nijveldt@xebia.com</email></author><category term="OpenCover" /><category term="Azure DevOps" /><category term="PowerShell" /><category term="IIS" /><category term="Code Coverage" /><category term="Test Automation" /><summary type="html"><![CDATA[OpenCover is a code coverage tool that measures both branch and sequence points for a given .Net application. In my case, I wanted to measure code coverage of a .Net web API project. The idea is to start OpenCover, run end-2-end tests (or other tests invoking my API) and generate a coverage file. This setup gives you insight into how much of your API is covered by, for example, end-2-end tests.]]></summary></entry></feed>