• CI/CD for Visual Studio extensions with GitHub Actions

    An inclement weekend has given me a chance to spend some time improving the build and publish story for one of my Visual Studio extensions - Show Missing, and along the way I’ve learned a lot about using GitHub Actions to implement a nice CI/CD story.

    I previously had set up AppVeyor and Azure Pipelines configurations to build this project. I thought this would be a good opportunity to consolidate automated build and deployment using GitHub Actions and add some nice enhancements to the process along the way.

    The project source is located in this repository on GitHub. I’m going to blog about each of the changes I made. At this stage I’m planning to cover:

    1. Building with GitHub Actions
    2. Optimise build with caching
    3. Adding Dependabot
    4. Create releases
    5. Attach binary to release
    6. Create new GitHub Action for deleting release assets
    7. Publish release to the Visual Studio Marketplace

    I’ll add links to subsequent posts as they are published.

  • Work from home update

    I started working from home back on March 16th, so it’s been around 14 weeks since I’ve worked in our office in Adelaide CBD.

    My normal weekday routine is getting up (usually earlier than I’d prefer), breakfast, shower and some stretches and exercises. The exercises were given to me by the physiotherapist after I injured my back last year playing basketball. While I haven’t returned to playing competitively, I figure it’s worth it for my own health to keep them up. A friend on Facebook was challenging folks to try and do 30 push ups a day for 30 days. I usually ignore these kinds of things (and don’t repost them), but in this case I figured it was worth adding to my list. I’ve slowly been building up and hope to keep doing it for the long term.

    Tree with drop of dew hanging

    Around the time of the school run (or a bit before) I head out for a morning walk. Most days I’ve been doing a 5km loop around the neighbourhood (weather permitting), which takes around 60 minutes. It takes the place of my walk to the bus and commute into town that I would previously have done. A great chance to get some fresh air and get the blood circulating, listen to podcasts (Daily Audio Bible followed by various technical podcasts), and prepare for the day ahead.

    Cold hands.

    The mornings can be chilly when I’m out walking, so my pullover with these sleeves that let you put your thumb through the collar are handy. I originally thought the hole was a defect, but later I realised it was intended all along and is a handy feature!

    Work follows mostly business hours, though a few weeks ago we did have a number of evening conference calls and training sessions. That is an ongoing challenge working for a global company - finding a time that’s convenient for most people to attend.

    Sandwich with mandarin and apple

    I usually take my own lunch to work, but it is extra nice to be able to put a bit of extra effort into a homemade sandwich! Yes, that fruit is home grown too.

    Being able to focus with less interruptions is a big bonus. I can also choose to put some background music on. Double J Radio is my station of choice.

    Wrap up the work day around 5-6pm and then see what’s happening with the rest of the family. It is nice to be home when they all get home from school. Sometimes there’s some hot chips as an after-school treat so it’s nice to be around to enjoy that!

    There’s been some discussions about returning to the office in the future. South Australia has had a total of 440 cases of COVID (with just 4 deaths) and no new cases in the last 4 weeks which is very encouraging.

    I’m in no particular rush though. I’ve generally enjoyed my time working at home. I don’t miss the 2 hours I was spending commuting each day. I feel like I think I’d like to keep doing it going forward (maybe going in to the office 1 day a week)

  • Roslyn Analyser backwards compatibility

    I recently created a Roslyn Code Analyzer project in Visual Studio 2019 16.6, but discovered that the package references used by the template aren’t suitable if you need the analyzer to run against older projects.

    Using the latest template might result in an error like this:

    error NU1202: Package Microsoft.CodeAnalysis.CSharp.Workspaces 3.3.1 is not compatible with net45 (.NETFramework,Version=v4.5). Package Microsoft.CodeAnalysis.CSharp.Workspaces 3.3.1 supports: netstandard2.0 (.NETStandard,Version=v2.0)
    

    So I spun up an instance of Visual Studio 2017 (on an Azure VM) to compare the projects.

    Here’s the analyzer csproj (after I did minor package updates)

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFramework>netstandard1.3</TargetFramework>
        <IncludeBuildOutput>false</IncludeBuildOutput>
        <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
      </PropertyGroup>
    
      <PropertyGroup>
        <PackageId>Analyzer2</PackageId>
        <PackageVersion>1.0.0.0</PackageVersion>
        <Authors>dgardiner</Authors>
        <PackageLicenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</PackageLicenseUrl>
        <PackageProjectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</PackageProjectUrl>
        <PackageIconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</PackageIconUrl>
        <RepositoryUrl>http://REPOSITORY_URL_HERE_OR_DELETE_THIS_LINE</RepositoryUrl>
        <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
        <Description>Analyzer2</Description>
        <PackageReleaseNotes>Summary of changes made in this release of the package.</PackageReleaseNotes>
        <Copyright>Copyright</Copyright>
        <PackageTags>Analyzer2, analyzers</PackageTags>
        <NoPackageAnalysis>true</NoPackageAnalysis>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="2.6.1" PrivateAssets="all" />
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="2.9.0" PrivateAssets="all" />
        <PackageReference Update="NETStandard.Library" PrivateAssets="all" />
      </ItemGroup>
    
      <ItemGroup>
        <Compile Update="Resources.Designer.cs" DesignTime="True" AutoGen="True" DependentUpon="Resources.resx" />
        <EmbeddedResource Update="Resources.resx" Generator="ResXFileCodeGenerator" LastGenOutput="Resources.Designer.cs" />
      </ItemGroup>
    
      <ItemGroup>
        <None Update="tools\*.ps1" CopyToOutputDirectory="Always" Pack="true" PackagePath="" />
        <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
      </ItemGroup>
    
    </Project>
    

    and the test csproj

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFramework>netcoreapp2.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="2.6.1" />
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="2.9.0" />
        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.2" />
        <PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
        <PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
      </ItemGroup>
    
      <ItemGroup>
        <ProjectReference Include="..\Analyzer2\Analyzer2.csproj" />
      </ItemGroup>
    
    </Project>
    

    The older test project also contains helper and verifier classes (the equivalent of these have moved to Nuget packages in 2019 templates).

    The older projects still compile and work in 2019. Obviously if you’re using a newer C# language / SDK version then using the newer template is preferred.

    If you’re looking for a nice overview of analyzers, you might want to check out the recording of Jason Bock’s presentation ‘Using the Compiler API in Real World Scenarios’