<?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>Forem: Kurt</title>
    <description>The latest articles on Forem by Kurt (@kurtmkurtm).</description>
    <link>https://forem.com/kurtmkurtm</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%2F449427%2F6c607b9c-1ba3-4a0a-a46b-57a19dc347bc.png</url>
      <title>Forem: Kurt</title>
      <link>https://forem.com/kurtmkurtm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kurtmkurtm"/>
    <language>en</language>
    <item>
      <title>Uno Platform .NET WebAssembly apps on GitHub Pages </title>
      <dc:creator>Kurt</dc:creator>
      <pubDate>Wed, 31 Mar 2021 22:09:13 +0000</pubDate>
      <link>https://forem.com/kurtmkurtm/uno-platform-net-webassembly-apps-on-github-pages-5873</link>
      <guid>https://forem.com/kurtmkurtm/uno-platform-net-webassembly-apps-on-github-pages-5873</guid>
      <description>&lt;h1&gt;
  
  
  Uno Platform .NET WebAssembly apps on GitHub Pages
&lt;/h1&gt;

&lt;p&gt;In this post, I’m going to cover how you can build a .NET WebAssembly app using the &lt;a href="https://github.com/unoplatform/uno" rel="noopener noreferrer"&gt;Uno Platform&lt;/a&gt; and use GitHub actions to publish it to GitHub pages.&lt;/p&gt;

&lt;p&gt;The Uno Platform is C# based cross platform framework that utilizes XAML for building apps. For anyone acquainted with WPF, Xamarin or UWP, this will all look familiar.&lt;/p&gt;

&lt;p&gt;While the apps can be deployed on a number of different platforms and devices, the platform of interest to me is WebAssembly. In particular, being able to run C# on a static site hosted on GitHub Pages.&lt;/p&gt;

&lt;p&gt;GitHub pages allow you to host static sites for free, and because it is deployed straight from the repository, setting up an action to deploy is very easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;In order to run tests on GitHub we will need these prerequisites;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub account&lt;/strong&gt; You can &lt;a href="https://github.com/join" rel="noopener noreferrer"&gt;join here&lt;/a&gt; if you don't have an account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt; If you don’t have a repo, take a look at the following article to get setup: &lt;a href="https://help.github.com/en/enterprise/2.16/user/github/getting-started-with-github/create-a-repo" rel="noopener noreferrer"&gt;Create a repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository cloned locally&lt;/strong&gt; If you don’t already have a setup with favourite git client, try the official docs: &lt;a href="https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository" rel="noopener noreferrer"&gt;Cloning a repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VSCode&lt;/strong&gt; - IDE to edit and debug the app &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;https://code.visualstudio.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting up your Uno WebAssembly project
&lt;/h3&gt;

&lt;p&gt;First, install the project templates from Uno&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new -i Uno.ProjectTemplates.Dotnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create a new Uno project from a template with the following command.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have disabled a number of targets, if you intend to run this app on another platform, you can flip the respective &lt;code&gt;false&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new unoapp -o GitHub.UnoPages -wasm=true -android=false -macos=false -uwp=false -ios=false -skia-wpf=false -skia-gtk=false -st=false -v=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running this, you should see a new folder created call &lt;code&gt;GitHub.UnoPages&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To test the project is working&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;code&gt;GitHub.UnoPages&lt;/code&gt; folder in &lt;strong&gt;VSCode&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;GitHub.UnoPages.Shared&amp;gt;MainPage.xaml&lt;/strong&gt; and change the following line of XAML
From
&lt;code&gt;&amp;lt;TextBlock Text="Hello, world!" Margin="20" FontSize="30" /&amp;gt;&lt;/code&gt;
To
&lt;code&gt;&amp;lt;TextBlock Text="Hello, Pages!" Margin="20" FontSize="30" /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save the change&lt;/li&gt;
&lt;li&gt;Switch to the debug tab

&lt;ul&gt;
&lt;li&gt;From the 'RUN AND DEBUG' menu select .NET Core Launch&lt;/li&gt;
&lt;li&gt;Press the green start button, or press F5&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--HGIKMNeG--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fke63yo92og0k4v98asjv.png" alt="Screenshot of VSCode debugging menu"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Once the project builds and starts running, you should see &lt;code&gt;Now listening on: http://localhost:5000&lt;/code&gt; in the console&lt;/li&gt;
&lt;li&gt;Open &lt;a href="http://localhost:5000/" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt; in the browser and you should see Hello, Pages!
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bFH7nRLj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fy2dkrfx99i4wdvfhum.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--bFH7nRLj--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fy2dkrfx99i4wdvfhum.png" alt="Screenshot of App in local browser"&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;With the app working, we can now stop debugging&lt;/li&gt;
&lt;li&gt;Commit your changes, and push to your GitHub Repository.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;For simplicity in this post, I am pushing directly to the &lt;code&gt;main&lt;/code&gt; branch, In practice it is advisable to protect your main branch, and create a feature branch, and subsequent PR&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Build Pipeline
&lt;/h3&gt;

&lt;p&gt;We are now going to set up a pipeline to automatically build and publish our app.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the main page of your GitHub repo, press the Actions tab.&lt;/li&gt;
&lt;li&gt;On the actions page, click *&lt;em&gt;set up a workflow yourself *&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Delete the pre populated Yaml&lt;/li&gt;
&lt;li&gt;Copy and Paste the following Yaml
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: UnoPages App
on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]   
  workflow_dispatch:  # Allows workflow to be ran via a button
jobs:
  build:
    runs-on: ubuntu-latest
    name: Build
    env:
      config: 'Release'
      framework: 'netstandard2.0'
    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 5.0.x
    - name: Restore Dependencies
      run: dotnet restore ./GitHub.UnoPages/GitHub.UnoPages.Wasm/GitHub.UnoPages.Wasm.csproj
    - name: Build 
      run: dotnet build ./GitHub.UnoPages/GitHub.UnoPages.Wasm/GitHub.UnoPages.Wasm.csproj --no-restore -f $framework -c $config
    - name: Publish Artifacts
      uses: actions/upload-artifact@v1.0.0
      if: github.event_name == 'workflow_dispatch' # Only deploy if Workflow manually ran
      with:
        name: pages
        path: ./GitHub.UnoPages/GitHub.UnoPages.Wasm/bin/${{env.config}}/${{env.framework}}/dist/        
  deploy:
    needs: build 
    runs-on: ubuntu-latest
    name: Deploy
    if: github.event_name == 'workflow_dispatch' # Only deploy if Workflow manually ran
    steps:
    - name: Download artifacts
      uses: actions/download-artifact@v2
      with:
        name: pages
        path: dist        
    - name: Deploy to GitHub Pages
      uses: crazy-max/ghaction-github-pages@v2
      with:
        target_branch: gh-pages
        build_dir: ./dist/
        jekyll: false
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save the workflow, with the following details - again for simplicity, I'm going to commit this directly to main.

&lt;ul&gt;
&lt;li&gt;Press the 'Start commit' button&lt;/li&gt;
&lt;li&gt;Add the description 'CI: Build workflow'&lt;/li&gt;
&lt;li&gt;Leave the options as 'Commit directly to the &lt;code&gt;main&lt;/code&gt; branch' (or create a new branch if required)&lt;/li&gt;
&lt;li&gt;Press the 'Commit new file' button&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Now, switch to the actions tab, and you should see your build that was triggered by the push to &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Take a look at the workflow by clicking on the run &lt;strong&gt;CI: Build workflow&lt;/strong&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t46cz5ik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i4e392ckp6a21wdwbhq9.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--t46cz5ik--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4e392ckp6a21wdwbhq9.png" alt="Screenshot of Build and Deploy Jobs inside an action, where only build has ran"&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You should now see that the build job ran, but not the deploy job. This in intentional, if you take another look at our workflow you can see that we have the condition on the event that triggered the build, which needs to be a workflow_dispatch.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deploy:
   needs: build 
   runs-on: ubuntu-latest
   name: Deploy
   if: github.event_name == 'workflow_dispatch' # Only deploy if Workflow manually ran
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Triggering a deployment
&lt;/h3&gt;

&lt;p&gt;As covered in the pipeline section, we are only deploying when a workflow dispatch event occurs.&lt;/p&gt;

&lt;p&gt;Switching back to main Actions tab:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select from the workflow list &lt;strong&gt;UnoPages App&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You should see a &lt;strong&gt;Run workflow&lt;/strong&gt; drop down button, click this&lt;/li&gt;
&lt;li&gt;From the drop down panel, click the &lt;strong&gt;Run workflow&lt;/strong&gt; button, and keep the branch as &lt;code&gt;Main&lt;/code&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--Xuhq0bbp--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0askr5iss9rtxe1lmqq.png" alt="Screenshot of GitHub workflow"&gt;
&lt;/li&gt;
&lt;li&gt;Wait for the workflow to complete, and you should now see the deploy job ran too&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--0QdmUNND--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhfj3dgxbp4m5zl0eys8.PNG" alt="Screenshot of Build and Deploy Jobs inside an action"&gt;
&lt;/li&gt;
&lt;li&gt;This deployment should have built our Uno Wasm app, and pushed it to a branch called &lt;code&gt;gh-pages&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With our app built, and pipeline in place, there's one final step covered in the next section &lt;a href="https://dev.to/kurtmkurtm/uno-platform-net-webassembly-apps-on-github-pages-3k0g-temp-slug-7308227?preview=7447fa303478740a2037ed5d9d1ac08f8817f7723479a1e895c531d7ef77e36c2a9ca81db997d445e7cfecb86319e5cc4a5dca0f65b04f5b8e613c64#enabling-github-pages"&gt;Enabling GitHub Pages&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling GitHub Pages
&lt;/h3&gt;

&lt;p&gt;In order to use pages, you will need to enable it for your repo.&lt;/p&gt;

&lt;p&gt;On your repo:&lt;/p&gt;

&lt;p&gt;Click Settings, then on the Options page, scroll right down until you see the &lt;strong&gt;GitHub Pages&lt;/strong&gt; header&lt;/p&gt;

&lt;p&gt;In the source panel,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select from the branch dropdown &lt;code&gt;gh-pages&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Leave the folder as &lt;code&gt;/(root)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Press Save&lt;/li&gt;
&lt;li&gt;After the page refreshes you should now see your GitHub pages url&lt;/li&gt;
&lt;li&gt;Click the link and you should see your deployed app!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RDUihkjG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmeg4owka849aqwmrr9n.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--RDUihkjG--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmeg4owka849aqwmrr9n.png" alt="Screenshot of GitHub pages settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sample deployed version here:&lt;br&gt;
&lt;a href="https://kurtmkurtm.github.io/UnoPages/" rel="noopener noreferrer"&gt;https://kurtmkurtm.github.io/UnoPages/&lt;/a&gt;&lt;br&gt;
Full Repository here: &lt;a href="https://github.com/kurtmkurtm/UnoPages" rel="noopener noreferrer"&gt;https://github.com/kurtmkurtm/UnoPages&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>github</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Testing .NET Core Apps with GitHub Actions</title>
      <dc:creator>Kurt</dc:creator>
      <pubDate>Sun, 09 Aug 2020 08:19:50 +0000</pubDate>
      <link>https://forem.com/kurtmkurtm/testing-net-core-apps-with-github-actions-3i76</link>
      <guid>https://forem.com/kurtmkurtm/testing-net-core-apps-with-github-actions-3i76</guid>
      <description>&lt;p&gt;In the following post I’m going to cover how you can run and publish results for your .NET Core Tests using GitHub actions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Updated 2021 to replace deprecated 'set-env' usage with new command&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In particular we will be setting up a CI pipeline action to publish test results in Markdown format as both a comment on pull requests (PR), and a build artifact. Running tests automatically on PRs is a good way to make sure you don’t push code that breaks your project.&lt;/p&gt;

&lt;p&gt;To make the most of .NET Core’s cross platform builds, and while maximizing GitHub Actions free tier, we will be using the Linux (Ubuntu) runner. At the time of writing this, the GitHub free tier gives you 2000 minutes per month on Linux runners, if you use Windows this drops to 1000 minutes, and macOS only 200 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;In order to run tests on GitHub we will need these prerequisites;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub account&lt;/strong&gt; You can &lt;a href="https://github.com/join"&gt;join here&lt;/a&gt; if you don't have an account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt; 
If you don’t have a repo, take a look at the following article to get setup: &lt;a href="https://help.github.com/en/enterprise/2.16/user/github/getting-started-with-github/create-a-repo"&gt;Create a repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository cloned locally&lt;/strong&gt; 
If you don’t already have a setup with favorite git client, try the official docs: &lt;a href="https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository"&gt;Cloning a repository&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting up your .NET Core test project
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The following commands should be ran in your project folder, so make sure to open up the command prompt in the directory you have checked out your project to.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Optional Step.&lt;/strong&gt; If you already have a test project you can skip to Step 1. &lt;br&gt;
Otherwise, we will create a new test project now with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xunit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a newly created test project&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1. Add the Markdown logger to your test project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will be utilizing the &lt;strong&gt;LiquidTestReports.Markdown&lt;/strong&gt; VS Test logger to generate a test report in the Markdown format (disclaimer: I am the creator of this library)&lt;/p&gt;

&lt;p&gt;You can add the library either by getting it from &lt;a href="https://www.nuget.org/packages/LiquidTestReports.Markdown"&gt;nuget&lt;/a&gt;, or running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LiquidTestReports.Markdown&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2. Run the tests locally&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make sure the tests will run on your machine with the test logger attached, by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;liquid.md&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You output should look similar to the image below, note the “Saved report” line. If you check in your project directory you should have a new TestResults folder with the newly created &lt;strong&gt;TestReport.md&lt;/strong&gt; file (preview shown below).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VS code showing dotnet test console and report preview:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4BpBQpN8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gipq1r7vmcx4j2nuda57.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4BpBQpN8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gipq1r7vmcx4j2nuda57.PNG" alt="VS Test console output showing report generation&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can delete the report for now, as we want to generate them inside the actions each time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Step 3. Commit and Push your code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that your test project is ready from the previous steps, it’s time to get it onto GitHub itself. &lt;/p&gt;

&lt;p&gt;To do this, &lt;strong&gt;commit&lt;/strong&gt; your local changes including the test project referencing the markdown logger. And &lt;strong&gt;push&lt;/strong&gt; your branch to your remote GitHub repository. &lt;/p&gt;

&lt;p&gt;Once again, leaning on the official GitHub help docs, for more info, take a look at &lt;a href="https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project"&gt;Committing and reviewing changes to your project&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating your first PR
&lt;/h3&gt;

&lt;p&gt;With your code now pushed to the remote, jump back on your GitHub repo, and you should now see a panel saying your branch has recent pushes, click the green 'Compare &amp;amp; pull request' button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C6N7o2jR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ti5erkmwv283fzu7new7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C6N7o2jR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ti5erkmwv283fzu7new7.PNG" alt="branch push notification and green 'Compare &amp;amp; pull request' button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should now see the create pull request page. &lt;br&gt;
Add a comment describing the changes e.g. 'Add new test project' and press the green 'Create pull request' button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PIMqr2QK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2peeljdmlhto2y114msy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PIMqr2QK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2peeljdmlhto2y114msy.PNG" alt="Create pull request page with green button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should now see the pull request page. For simplicity, we will just go straight to pressing the green 'Merge pull request' button&lt;br&gt;
followed by the 'Confirm merge' button.&lt;/p&gt;

&lt;p&gt;To keep things clean you can also press the 'Delete branch' button. &lt;/p&gt;

&lt;p&gt;With this all done, we are ready to move on to setting up the action.&lt;/p&gt;


&lt;h3&gt;
  
  
  Setting up the Github Action
&lt;/h3&gt;

&lt;p&gt;In your browser &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to your GitHub repo and click the ‘Actions’ tab&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the Actions tab, you will see lots of workflow options, at the top click ‘Skip this and set up a workflow yourself’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will now see the yaml editor with a default CI pipeline.  Delete the contents of this, so we can start the pipeline from scratch&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  The GitHub Action
&lt;/h4&gt;

&lt;p&gt;Starting with the setup, we will add something similar to the default dotnet workflow. Here we are setting up the environment, restoring the nuget dependencies, and building the project. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may notice the 'on' conditions at the top, there are two scenarios that we want to trigger a build&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A PR has been created to merge into the master branch&lt;/li&gt;
&lt;li&gt;A push to the master branch, created by a merge commit
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.NET Core Build with Tests&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;master&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;master&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# use ubuntu for more build minutes&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="c1"&gt;# use release mode for all steps&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Release'&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup .NET Core&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-dotnet@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;dotnet-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.1.101&lt;/span&gt;    

      &lt;span class="c1"&gt;# restore dependencies  &lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet restore&lt;/span&gt;

      &lt;span class="c1"&gt;# build project&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet build --configuration $config --no-restore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, we will be conditionally setting some variables to set the test report name and title, for both cases, we want to include the run number, so we know which build the test results are for. If it is a pull request, then we additionally want to know the pull request number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="c1"&gt;# set pr number, if it's a pr build&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;set pr build number&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PRNUMBER&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event_name == 'pull_request' }}&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kkak10/pr-number-action@v1.3&lt;/span&gt;

      &lt;span class="c1"&gt;# set report file and title &lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set Test Title&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt; 
            &lt;span class="s"&gt;if ${{ github.event_name == 'pull_request' }}&lt;/span&gt;
            &lt;span class="s"&gt;then&lt;/span&gt;
              &lt;span class="s"&gt;echo "title=Test Run for PR #${{steps.PRNUMBER.outputs.pr}} (${{github.run_number}})" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
              &lt;span class="s"&gt;echo "file_name=TestReport.${{steps.PRNUMBER.outputs.pr}}.${{github.run_number}}.md" &amp;gt;&amp;gt; $GITHUB_ENV              &lt;/span&gt;
            &lt;span class="s"&gt;else&lt;/span&gt;
              &lt;span class="s"&gt;echo "title=Test Run ${{github.run_number}}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
              &lt;span class="s"&gt;echo "file_name=TestReport.${{github.run_number}}.md" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
            &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this set, we can now move on to running the tests, this is using the same &lt;code&gt;dotnet test&lt;/code&gt; method as earlier in the post, but now passing in some parameters for the title, and file name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# run tests with built project&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test PR&lt;/span&gt;      
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet test --no-restore --no-build --configuration $config --logger:"liquid.md;LogFileName=${{github.workspace}}/${{env.file_name}};Title=${{env.title}};"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the report is generated, we want to store it, this next step will attach the markdown file as a build artifact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# upload report as build artifact&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload a Build Artifact&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v2&lt;/span&gt;
  &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{always()}}&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Run'&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{github.workspace}}/${{env.file_name}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we want to add one final step, for pull requests. This step will attach the contents of the markdown report as a comment to your pull request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# add report as PR comment (if PR)&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;comment PR&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;machine-learning-apps/pr-comment@master&lt;/span&gt;
  &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event_name == 'pull_request' }}&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{env.file_name}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A complete copy of the workflow is available &lt;a href="https://gist.github.com/kurtmkurtm/286b579242c14f523f904183daeeb38c"&gt;here on a gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time to commit&lt;/strong&gt;&lt;br&gt;
Pressing the green "start commit" button &lt;/p&gt;

&lt;p&gt;There's two options here, commit to &lt;code&gt;master&lt;/code&gt; branch, or create a branch. &lt;/p&gt;

&lt;p&gt;I'm going to: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;select the '&lt;strong&gt;new branch&lt;/strong&gt;' option&lt;/li&gt;
&lt;li&gt;set the branch name to &lt;code&gt;ci/test-workflow&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;press the green 'Propose new file' button&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ENZ81xu9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zvcbxxftkb0fcjejnp5t.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ENZ81xu9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zvcbxxftkb0fcjejnp5t.PNG" alt="Create new branch for commit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should now see the familiar 'Open a pull request' page. Once again, press the green button to create the pull request.&lt;/p&gt;

&lt;p&gt;With the pull request created, switch over to the 'Actions' tab. You should now see your workflow, and after a minute or so of running, a green tick next to the workflow result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4AoZmfXx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/80t25xx4pnvph6r3lzkm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4AoZmfXx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/80t25xx4pnvph6r3lzkm.PNG" alt="Workflow result with green tick"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, switch back to your pull request, and you should notice a new comment on it containing your test report.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--85HltQlV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x5jqv41cdc25wtlczxg9.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--85HltQlV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x5jqv41cdc25wtlczxg9.PNG" alt="PR comment report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, merge this PR, and you will have test reports included in your builds and PRs from now on.&lt;/p&gt;

&lt;p&gt;A complete working sample is available here:&lt;br&gt;
&lt;a href="https://github.com/kurtmkurtm/.net-core-workflow/actions"&gt;https://github.com/kurtmkurtm/.net-core-workflow/actions&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>github</category>
      <category>devops</category>
      <category>csharp</category>
    </item>
  </channel>
</rss>
