DevOps Blazor WebAssembly Solution: Part 3 - CI/CD
Tags: devops, blazor, webassembly, azuredevops
Published: 2020-04-29 03:38:56

---
title: DevOps Blazor WebAssembly Solution: Part 3 - CI/CD
published: true
description: DevOps Blazor WebAssembly App
tags: DevOps,Blazor,WebAssembly,AzureDevOps
---

In the [previous article](https://dev.to/kenakamu/devops-blazor-webassembly-solution-part-2-add-more-complex-unit-tests-ij6), I added unit tests for Blazor Client. I know I should have done for server side as well, but I go ahead to configure CI/CD first.

> *Note: Don't directly push changes to master branch

>In this article, I push all the changes into master branch directly which triggers CI/CD pipeline. I do this to simplify the article. Don't do it in any real projects. You should follow the best practices for git workflow.

>Always create new branch for the task and create PR to review, validate build and merge.

# Create Web App

I simply create Azure App Service in Azure to host the application. Use globally unique name for WebApp.

```shell
az group create --location EastUS --name DevOpsBlazorRG
az appservice plan create --name DevOpsBlazorPlan -g DevOpsBlazorRG --sku FREE
az webapp create --name DevOpsBlazor-Test -g DevOpsBlazorRG --plan DevOpsBlazorPlan
```

# Create DevOps Project

Let's add Azure DevOps project and check-in the current solution.

1\. Go to [DevOps portal](https://dev.azure.com) and create new project.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6fvpyphdx2muq1bteygm.jpg)

2\. Go to Repos and find git address.

3\. Back to Visual Studio and enable source control.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/na9ydvdrxlwjmy9umpv5.jpg)

4\. Select "Remote URL" and enter the address.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2m44kf84vsnfvi0uvxf0.jpg)

5\. Back to Azure DevOps and refresh the page. Confirm all the files are checked-in.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/am72bwi1rx8btgcfuj5f.jpg)

# Create a CI/CD pipeline

Now I have source code in DevOps, let's create CI pipeline. This time, I use multi stage pipeline to separate build and deploy. As it's preview feature yet, refer to [Enable preview features](https://docs.microsoft.com/en-us/azure/devops/project/navigation/preview-features?view=azure-devops&tabs=new-account-enabled) to make sure the feature is turned on.

## Create build stage

Start from adding build stage.

1\. Go to Pipelines and create New Pipeline.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ejncpauij9q3id2pt592.jpg)

2\. Select Azure Repos Git and created repository
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/801ka3j6qohl6sdledxm.jpg)

3\. Click "Show more" and select "ASP.NET Core".
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nij2u9qgt4i65bjabcs7.jpg)

4\. To avoid automatic trigger when yml check-in, update trigger. See [CI triggers](https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#ci-triggers) for more options how to trigger the pipeline.

```yaml
trigger:
  branches:
    include:
    - master
  paths:
    exclude:
    - azure-pipelines.yml
```

5\. Update yaml so that it uses **stages**. Pools and jobs need to be moved inside stage. I also added **vmImageName** variable for pool.

```yaml
variables:
  buildConfiguration: 'Release'
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build stage

  jobs:
  - job: Build
    displayName: Build

    pool:
      vmImage: $(vmImageName)

    steps:

```

6\. Expand "show assistant" and select ".NET Core".
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/szgz6mn8ng9d3edphdbw.jpg)

7\. Select Build and specify server project. The server project has references to Client and Shared, so I don't need to separately specify them.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/da2a6ruc868kgfm1m4z2.jpg)

8\. Add another .NET Core task for test. Specify the test project.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7ews82kiusmmbv2opo7u.jpg)

9\. I added display name for each task. The final yml looks like below.

```yaml
# ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core

trigger:
  branches:
    include:
    - master
  paths:
    exclude:
    - azure-pipelines.yml

variables:
  buildConfiguration: 'Release'
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build stage

  jobs:
  - job: Build
    displayName: Build

    pool:
      vmImage: $(vmImageName)

    steps:
    - task: DotNetCoreCLI@2
      displayName: Build Server
      inputs:
        command: 'build'
        projects: '**/DevOpsBlazor.Server.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: Run Unit Tests
      inputs:
        command: 'test'
        projects: '**/DevOpsBlazor.UnitTests.csproj'
```

10\. Click "Save and run". I directly committed the yml file to master branch. Once the pipeline completed, I can see build result as well as test result.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7sbq1w1t5geot9ypz0f4.jpg)

11\. See the test results as well.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dv0z7lfq120gog7n6r5o.jpg)

## Add release stage

Next, add release stage for the pipeline.

1\. Add new stage for release.

```yaml
- stage: Release
  displayName: Release stage

  jobs:
  - job: Release
    displayName: Release to Azure

    pool:
      vmImage: $(vmImageName)

    steps:
```

2\. Add .NET Core task and select publish.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/j9ioyjzo83ya1f4r6cqi.jpg)

3\. From Tasks pane, select "Azure App Service deploy"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/68q1payzuzb5rmhwjsdq.jpg)

4\. Follow the wizard to authorize Azure Subscription and select created App Service.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f9e0yp6nsx3ahdmqoz4y.jpg)

Final yaml looks like this:

```yaml
trigger:
  branches:
    include:
    - master
  paths:
    exclude:
    - azure-pipelines.yml

variables:
  buildConfiguration: 'Release'
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build stage

  jobs:
  - job: Build
    displayName: Build

    pool:
      vmImage: $(vmImageName)

    steps:
    - task: DotNetCoreCLI@2
      displayName: Build Server
      inputs:
        command: 'build'
        projects: '**/DevOpsBlazor.Server.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: Run Unit Tests
      inputs:
        command: 'test'
        projects: '**/DevOpsBlazor.UnitTests.csproj'
    
- stage: Release
  displayName: Release stage

  jobs:
  - job: Release
    displayName: Release to Azure

    pool:
      vmImage: $(vmImageName)

    steps:
    - task: DotNetCoreCLI@2
      displayName: Publish the project
      inputs:
        command: 'publish'
        publishWebProjects: true
        
    - task: AzureRmWebAppDeployment@4
      inputs:
        ConnectionType: 'AzureRM'
        azureSubscription: '<your subscription info>'
        appType: 'webApp'
        WebAppName: 'DevOpsBlazor-Test'
        packageForLinux: '$(System.DefaultWorkingDirectory)/**/*.zip'
```

5\. Save the change and run the pipeline. Now I see two stages.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/r06657bjzx7ncwgvlbq5.jpg)

6\. Wait until all stages complete.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/r4z213a8dinsl0rze2g2.jpg)

7\. Once release completed, access to the site. Well.. it seems something went wrong.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tsh1sgamb0ilq271qnmi.jpg)

After I debug, I found solution [here](https://github.com/dotnet/aspnetcore/issues/19828). This is good opportunity to test CI/CD.

# Test CI/CD

Let's change the code and try CI/CD at the same time.

1\. Open DevOpsBlazor.Client.csproj and add following in Property group.

```xml
<BlazorCacheBootResources>false</BlazorCacheBootResources>
```

2\. From solution explorer, commit the change. I can commit and sync at the same time.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k8rjdalhh9eo7ytsmk4n.jpg)

3\. Go back to Azure DevOps and confirm the pipeline is triggered.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s4syqp532b3ab3gixpgo.jpg)

4\. Once the pipeline complete, check the website.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uel1evavtwug51pol5hw.jpg)

# Summary

In this article, I configure CI/CD pipeline by using multi-stage with yaml file. I will add end to end UI testing in the next article.

[Go to next article](https://dev.to/kenakamu/devops-blazor-webassembly-solution-part-4-end-to-end-ui-test-1b3g)