Post

GitHub Actions: Deploying .NET to Azure App Service

In this post, I am going to outline a step by step guide to build and deploy an .Net Core application to an Azure App Service using GitHub Actions.

Before starting to create the GitHub Actions workflow to deploy the application, let’s create the required resources on Azure. For simplicity I will create these resources manually of course you can use any infrastructure tools like Terraform, Bicep, ect to create the required infrastructure.

Create Resources on Azure

We are going to deploy the app on an Azure App Service, so we need to create Web App resource on Azure. Follow the following steps:

  1. Sign in to Azure Portal
  2. From the home page, click on Create a resource, it will redirect you to Microsoft Azure Marketplace to select your desired resource Create a resource
  3. In the search bar, type web app, and click on it Select web app
  4. Fill in the required information to configure your web app resource
    • Select the desired subscription, if you have many
    • Choose the Resource Group, that the resources are going to be created inside. If you would to create a new one click on Create a new, and provide it’s name.
    • Enter a unique name for your web app. The system will check for name availability and validate it. If the name is already taken, you will need to choose another.
    • Select Publish option to Code
    • Select a run time stack, in my case I will select .NET 6
    • Select Select your app deployment region
    • Once finished all the resource details, click on Review + create
      Create web app
  5. It will take some time to finish the deployment of the resources
  6. After finishing, you can navigate to the resource group to we selected while creating the resources, and you can find all resources created successfully
  7. Click on the created App Service resource, and click on Browse to check it. As we haven’t deployed our app yet this is the default layout.

As we prepared our Azure Resources, now it is time to work on our GitHub Action workflow to build and deploy the application to the created Azure resources.

Create GitHub Action Workflow

I used a sample .NET app to be deployed, you can use your own or, if you would like to use the same app you can find the code in the following: GitHub Repo

source code

First, create a new repo, and push your code to it. You can setup your own workflow, or you can use a starter workflow provided by GitHub. These templates are pre-configured and can save time.

Choosing and using a starter workflow

  1. On GitHub.com, navigate to the main page of the repository.
  2. Under your repository name, click Actions.
  3. Search for .NET to filter the workflows, and select Deploy a .NET Core app to an Azure Web App template
  4. Click configure on the selected template This will create a new .yml file under the following location in your repo: .github/workflows

Workflow

Workflow

This is the final workflow, after making some changes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# This workflow will build and push a .NET Core app to an Azure Web App when a commit is pushed to your default branch.

name: Build and deploy ASP.Net Core app to an Azure Web App

env:
  AZURE_WEBAPP_NAME: web-app-github-actions   # set this to the name of your Azure Web App
  AZURE_WEBAPP_PACKAGE_PATH: '.'      # set this to the path to your web app project, defaults to the repository root
  DOTNET_VERSION: '6.0.x'                 # set this to the .NET Core version to use

on:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest

    defaults:
      run:
        working-directory: ./source/app-dotnet

    steps:
      - uses: actions/checkout@v4

      - name: Set up .NET Core
        uses: actions/setup-dotnet@v2
        with:
          dotnet-version: $

      - name: Set up dependency caching for faster builds
        uses: actions/cache@v3
        with:
          path: ~/.nuget/packages
          key: $-nuget-$
          restore-keys: |
            $-nuget-

      - name: Build with dotnet
        run: dotnet build --configuration Release

      - name: dotnet publish
        run: dotnet publish -c Release -o $/myapp

      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v3
        with:
          name: .net-app
          path: $/myapp

  deploy:
    permissions:
      contents: none
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: 'Development'
      url: $

    steps:
      - name: Download artifact from build job
        uses: actions/download-artifact@v3
        with:
          name: .net-app

      - name: Deploy to Azure Web App
        id: deploy-to-webapp
        uses: azure/webapps-deploy@v2
        with:
          app-name: $
          publish-profile: $
          package: $

Breakdown the workflow

The workflow consists of two jobs: build and deploy. Build job will restore dependencies, build the application and create the package (artifact), and then upload it to GitHub.

Deploy job starts by downloading the build artifact from GitHub. This is necessary because the deploy job runs on a different runner machine than the build job, then deploy the app to the created Azure resource.

Let’s breakdown the workflow to understand it:

  1. Name and Environment Variables
    • name: The name of the workflow.
    • env: Defines environment variables used throughout the workflow, including the Azure Web App name, package path, and .NET version (replace these values with your own)

Don’t forget to replace AZURE_WEBAPP_NAME variable with the name of your web app created on Azure, also make sure the .NET version matches the version used in your application.

  1. Trigger

    • on: workflow_dispatch: This allows the workflow to be triggered manually from the GitHub Actions tab.
  2. Permissions

    • permissions: contents: read: Sets read permissions for repository contents.
  3. Jobs

    • Build Job

      • runs-on: ubuntu-latest: Specifies the runner for the job.
      • defaults: Sets the default working directory for the steps within this job. As my code is inside source directory I put it to : ./source/app-dotnet
      • steps:
        • actions/checkout@v4: Checks out the code from the repository.
        • actions/setup-dotnet@v2: Sets up the .NET environment based on the specified version on the environment variables.
        • actions/cache@v3: Caches the NuGet packages to speed up subsequent builds.
        • dotnet build –configuration Release: Builds the .NET project in Release mode.
        • dotnet publish -c Release -o $/myapp: Publishes the project to the specified directory.
        • actions/upload-artifact@v3: Uploads the published project as an artifact to GitHub.
    • Deploy Job

      • deploy: The second job that deploys the application to Azure.
      • runs-on: ubuntu-latest: Specifies the runner for the job.
      • needs: build: Specifies that this job depends on he build job. As the deploy job use the created package from the build job to deploy it to Azure, so the deploy job needs build job to be completed successfully first. Then it will start.
      • environment: Defines deployment environment details.
      • steps:
        • actions/download-artifact@v3: Downloads the build artifact.
        • azure/webapps-deploy@v2: Deploys the downloaded artifact to the Azure Web App.

By default jobs run in parallel in GitHub Actions, if we need to create dependencies between jobs to run sequentially use needs keyword.

Generate Deployment Credentials

As our GitHub Action workflow deploys to Azure App Service, so GitHub needs to authenticate with it.

There are many ways to authenticate with Azure App Services for GitHub Actions such as OpenID connect, publish profile, service principle, and User-assigned Managed Identity.

In our workflow we used publish profile as shown here: publish-profile: $ in azure/webapps-deploy@v2.

Publish profile is a configuration file that contains all the information and credentials needed to publish an application to an Azure App Service.

Publish profile requires basic authentication to be enabled.

Basic auth disabled

Enable web app basic authentication

To enable the basic authentication for your web app

  1. Navigate to web app Settings section
  2. Click on Configuration
  3. Select On for SCM Basic Auth Publishing Credentials
  4. Click Save

Enable basic auth

Download publish profile

Navigate to the overview section of the web app, then click Download publish profile

Download publish profile

Add the Publish Profile to GitHub Secrets

  1. In your repository select Settings
  2. Under Secrets and variables section, select Actions
  3. Click on New repository secret
  4. For the name of the secret, put the same name we used on our workflow AZURE_WEBAPP_PUBLISH_PROFILE in the webapps-deploy action
  5. Copy the content of the downloaded publish profile file and paste it in secret New repo secret Add Secret

Run Workflow

We are ready now to run our workflow, navigate to Actions on your repo, under the All workflows section you will find a workflow with the name: Build and deploy ASP.Net Core app to an Azure Web App, then click on Run workflow.

The workflow will build and deploy the app as discussed, automating the entire process from code to deployment on Azure.

Verify the deployment

Navigate to web app, and refresh it. You should see now the web app deployed successfully.

You can find the downloaded artifact from the build job on the workflow run summary as the following image

This post is licensed under CC BY 4.0 by the author.