Devops
Handy default Netlify toml file settings

Handy default Netlify toml file settings

With Netlify it's quite easy to quickly spin up a new website with a lot of good default out the box, but there's a few options that are good to set for both security and seo reasons.

Firstly it's good practice to have some headers set to improve security. For example setting X-Content-Type-Options to nosniff will disable sniffing of mime types. Setting X-Frame-Options to DENY will prevent the website being rendered in a frame on another site and Referrer-Policy of same-origin will reduce the amount of referrer information sent to other websites.

It's also a good idea to setup a redirect on the Netlify subdomain that Netlify will have created for your site. If you don't, then you could find the wrong URL ending up in Google.

1[[headers]]
2 for = "/*"
3 [headers.values]
4 Referrer-Policy = "same-origin"
5 Strict-Transport-Security = "max-age=15768000"
6 X-Content-Type-Options = "nosniff"
7 X-Frame-Options = "DENY"
8 X-XSS-Protection = "1; mode=block"
9[[redirects]]
10 from = "https://example.netlify.app"
11 to = "https://example.com/"
12 status = 301
13 force = true
How to setup CI with Azure App Service using GitHub Actions and deployment slots

How to setup CI with Azure App Service using GitHub Actions and deployment slots

Today I'm going to go through how you can setup automatic deployments when using a combination of Azure App Service (e.g. a Web App), deployment slots on the App Service and GitHub Actions. This is a setup to achieve zero downtime.

What are GitHub Actions?

GitHub Actions are the continuous integration and continuous delivery (CI/CD) platform from GitHub. If you're working with the Microsoft tech stack you may have used tools such as Team City or Azure Dev Opps in the past and this is just GitHubs version. Like the newer Azure Devops pipelines GitHub Actions define the pipeline in yaml files and while they are not the same they are very similar.

What are App Service Deployment Slots?

Deployment slots solve two issues; Firstly they allow zero downtime deployments by deploying the application to a separate instance to production, warming up that instance and then swapping it. Secondly, they can also be used as separate environments to preview changes without affecting the production code.

One thing to note is that although they are separate from the production code, they do share the same resources. So if your change has a processor-hungry bug, then that will have an affect your live environment. For this reason its also best to not leave them running all the time.

Configure App Service Deployment Slows

As a pre-requisite you need an App Service configured in Azure. Once you have this head to the Deployment slots section in the left nav.

Click the Add Slot button, and create a slot named staging.

Create Azure Deployment Slot

Auto Swap Slots

At this point you could setup a deployment pipeline that deploys to the staging slot and then performs a slot swap, to change which one is in production. However Azure has a nifty setting that will do this all for you.

Click into the Deployment slot you just created and then go to Configuration, in the left-hand nav.

Switch to the General settings tab.

App Service - Configuration (General Settings tab)

Scroll down to a section called Deployment Slot, and turn on auto swap. Within the drop-down select production.

Auto Deployment Swap setting

Now when a deployment is made to the staging slot it will warm up and then automatically swap with the production slot.

Configure GitHub Action

To configure the GitHub Action first make sure you are still in the staging deployment slot and select Deployment Center in the left nav.

From the source drop-down select GitHub.

Deployment Center - Selecting Source

Next select the Organization, Repository and branch to deploy for. This will give you the option to add a workflow. You may need to edit this file to get the build to work as needed but, this will provide the basics for building a .NET application and configuring the publish profile to get it into Azure.

Deployment Center - configure GitHub Action
SonarCloud: Fixing unexpected unknown at-rule @tailwind

SonarCloud: Fixing unexpected unknown at-rule @tailwind

I'm a big fan of using SonarCloud. Not only does it help to maintain the quality of your projects but the error descriptions are good enough to provide a nice training aspect to developers.

However at some point your going to receive bug reports for things that just aren't bugs.

For example if you are using Tailwind, you may get a Unexpected unknown at-rule "@tailwind" bug reported if you use @tailwind in your code.

Unexpected unknown at-rule "@tailwind"

You know your code is correct, it's just that SonarCloud doesn't know about Tailwind.

Fortunately Sonar allows you to extend all of the built in rules so that you can add customizations to work around things like this.

Fixing unexpected unknown at-rule @tailwind in Sonar

In Sonar, go to the Quality Profiles section.

The Quality Profiles screen lists out to collections of rules which are applied during analysis. From here you can make completely new collections, extend collections and change the defaults ones. With multiple profiles configured you could even have different collections per project.

Filter by the language CSS and then use the settings menu at the end of the Sonar way profile to extend the profile.

Sonar Cloud Quality Profiles screen filtered to CSS

Your new profile will appear under the Sonar way one. Now set it as the default using the settings drop down again. From now on our extended profile will be used during analysis and because its an extension of the Sonar Way, we haven't lost any existing rules. Equally as new rules are added to the default, our extended profile will pick these up too.

Sonar quality profile, set as default.

To update the rule causing unexpected unknown at-rule @tailwind go to the Rules section and filter by CSS.

Sonar CSS Rules

Pick the rule that needs updating. In our case this is "at-rules" should be valid.

At the bottom of this page you will see our Extended profile and the Sonar way profile.

Sonar Rule profile

Click the change button on the Extended profile.

You will get the rule definition. Simply add tailwind to this list of values.

Sonar Edit Rule

Once you save, the profiles on the rules will show that the extended rule has been changed.

Sonar rule updated

That's it. Now when your analysis next runs your extended profile will be used and @Tailwind in your code will no longer fail the at-rule.

SonarQube for .NET Framework with GitHub Actions

SonarQube for .NET Framework with GitHub Actions

If you haven't tried SonarQube or SonarCloud out then I suggest you do. The cloud version is quite straightforward to setup and from my experience the stuff it finds can be quite insightful. Like all these tools, at times you'll disagree with what they say, but there's always the option to change the rules.

What I particularly like with SonarQube is the examples you get with each bug that clearly explains why there's an issue and what you need to do in order to fix it.

What I didn't like however were the instructions for setting a project using .NET Framework. There are instructions labelled .NET, but this heavily assumes your using .NET Core, which while that might be our general preference, products like Sitecore could force your hand back to .NET Framework and all those legacy projects didn't just go away.

How to setup SonarQube using GitHub Actions for .NET Framework

The GitHub setup instructions (https://docs.sonarqube.org/latest/analysis/github-integration/) will give you the following code to create your GitHub Action with. This is also the same code you will get if you follow the wizard in SonarQube.

1name: Build
2on:
3 push:
4 branches:
5 - master # or the name of your main branch
6 pull_request:
7 types: [opened, synchronize, reopened]
8jobs:
9 build:
10 name: Build
11 runs-on: windows-latest
12 steps:
13 - name: Set up JDK 11
14 uses: actions/setup-java@v1
15 with:
16 java-version: 1.11
17 - uses: actions/checkout@v2
18 with:
19 fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
20 - name: Cache SonarQube packages
21 uses: actions/cache@v1
22 with:
23 path: ~\sonar\cache
24 key: ${{ runner.os }}-sonar
25 restore-keys: ${{ runner.os }}-sonar
26 - name: Cache SonarQube scanner
27 id: cache-sonar-scanner
28 uses: actions/cache@v1
29 with:
30 path: .\.sonar\scanner
31 key: ${{ runner.os }}-sonar-scanner
32 restore-keys: ${{ runner.os }}-sonar-scanner
33 - name: Install SonarQube scanner
34 if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
35 shell: powershell
36 run: |
37 New-Item -Path .\.sonar\scanner -ItemType Directory
38 dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
39 - name: Build and analyze
40 env:
41 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
42 shell: powershell
43 run: |
44 .\.sonar\scanner\dotnet-sonarscanner begin /k:"example" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="${{ secrets.SONAR_HOST_URL }}"
45 dotnet build
46 .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"

There's two aspects to notice with this. Firstly the Build and analyze section is running a command dotnet build which is fine if your running .Net Core, but for .Net Framework it isn't going to work.

Secondly it's highly likely your solution will use NuGet packages and there's no step in here to restore them.

To setup and restore NuGet packages add in the following steps before the Build and analyze step. Be sure to put your solution filename in the restore command.

1 - name: Setup Nuget
2 uses: Nuget/setup-nuget@v1.0.5
3
4 - name: Restore nuget packages
5 run: nuget restore MySolution.sln

To do a build that will compile your .Net Framework code you will need to use MsBuild rather than dotnet. However if you just swap them over you'll get an invalid command error. First you need to add msbuild to PATH. Change your build steps as follows.

1 - name: Add msbuild to PATH
2 uses: microsoft/setup-msbuild@v1.0.2
3
4 - name: Build and analyze
5 env:
6 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
7 shell: powershell
8 run: |
9 .\.sonar\scanner\dotnet-sonarscanner begin /k:"example" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="${{ secrets.SONAR_HOST_URL }}"
10 dotnet build
11 .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"

With that now in place you can now compile some .Net Framework code and have the results sent back to your SonarQube instance.