Lately I am learning ASP.net Blazor – the relatively new UI framework from Microsoft. Blazor is just awesome – the ability to write c# code both in server and client side is extremely productive for .net developers. From Blazor documentations:
I am using GitHub as my source repository for free (in a private repository). Today wanted to create a pipeline that will continuously deploy my Blazor app to the storage account. Azure Pipelines seems to have pretty nice integration with GitHub and it’s has a free tier as well . If either our GitHub repository or pipeline is private, Azure Pipeline still provide a free tier. In this tier, one can run one free parallel job that can run up to 60 minutes each time until we’ve used 1800 minutes per month. That’s pretty darn good for my use case.
I also wanted to build the project many times in my local machine (while developing) in the same way it gets built in the pipeline. Being a docker fan myself, that’s quite no-brainer. Let’s get started.
I have performed few steps before I ran after the pipeline – that are beyond the scope of this post.
- I have created an Azure Subscription
- Provisioned resource groups and storage account
- I have created a Service Principal and granted Contributor role to the storage account
Publishing in Docker
I have created a docker file that will build the app, run unit tests and if all goes well, it will publish the app in a folder. All of these are standard dotnet commands.
Once, we have the application published in a folder, I have taken the content of that folder to a Azure CLI docker base image (where CLI is pre-installed) and thrown away the rest of the intermediate containers.
Here’s our docker file:
|FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base|
|# Build the app|
|FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build|
|COPY . .|
|RUN dotnet restore "BlazorApp.csproj"|
|RUN dotnet build "BlazorApp.csproj" -c Release -o /app|
|# Run the unit tests|
|RUN dotnet restore "BlazorAppTest.csproj"|
|RUN dotnet build "BlazorAppTest.csproj"|
|RUN dotnet test "BlazorAppTest.csproj"|
|# Publish the app|
|FROM build AS publish|
|RUN dotnet publish "BlazorApp.csproj" -c Release -o /app|
|FROM microsoft/azure-cli AS final|
|COPY –from=publish /app .|
|RUN az login –service-principal –username $AppID –password $AppSecret –tenant $TenantID|
|RUN az storage blob delete-batch –account-name $StorageAccountName –source "\$web"|
|RUN az storage blob upload-batch –account-name $StorageAccountName -s . -d "\$web"|
The docker file expects few arguments (basically the service principal ID, the password of the service principal and the Azure AD tenant ID – these are required for Azure CLI to sign-in to my Azure subscription). Here’s how we can build this image now:
|–build-arg AppID=<APP GUID>|
|–build-arg TenantID=<Azure AD TENANT ID>|
|-t blazor-app .|
Azure Pipeline as code
We have now the container, time to run it every time a commit has been made to the GitHub repository. Azure Pipeline has a yaml format to define pipeline-as-code – which is another neat feature of Azure Pipelines.
Let’s see how the pipeline-as-code looks like:
|name: Hosted Ubuntu 1604|
|– task: Docker@0|
|displayName: 'Build and release Blazor to Storage Account'|
I have committed this to the same repository into the root folder.
Creating the pipeline
We need to login to Azure DevOps and create a project (if there’s none). From the build option we can create a new build definition.
The steps to create build definition is very straightforward. It allows us to directly point to a GitHub repository that we want to build.
Almost there. We need to supply the service principal ID, password, tenant ID and storage account names to this pipeline – because both our docker file and the pipeline-as-code expected them as dependencies. However, we can’t just put their values and commit them to GitHub. They should be kept secret.
Azure Pipeline Secret variables
Azure Pipeline allows us to define secret variable for a pipeline. We need to open the build definition in “edit” mode and then go to the top-right ellipses button as below:
Now we can define the values of these secret and keep them hidden (there’s a lock icon there).
That’s all what we need. Ready to deploy the code to Azure storage via this pipeline. If we now go an make a change in our repository it will trigger the pipeline and sure enough it will build-test-publish-deploy to Azure storage as a Static SPA.
Thanks for reading!