Build a .NET web app using GitHub Actions
This content is an excerpt from the eBook, DevOps for ASP.NET Core Developers, available on .NET Docs or as a free downloadable PDF that can be read offline.
GitHub Actions allow you to automate workflows in response to events that are triggered in GitHub. A common workflow is Continuous Integration (CI), but Actions can automate other processes. For example, sending welcome emails when people join a repository.
To explore moving code to the cloud, you'll build a GitHub Actions workflow file. The workflow file will be used for the Simple Feed Reader app you've already deployed to Azure App Service.
In this article, you will:
- Learn the basic structure of a GitHub Action workflow YAML file.
- Use a template to create a basic build workflow that builds the .NET app and executes unit tests.
- Publish the compiled app so that it's ready for deployment.
Workflows are defined in YAML files, and contain several common nodes:
- a trigger, defined by an
- one or more
jobsections composed of one or more
- optional attributes such as
Jobs are run on runners. You can use hosted runners, which are spun up by GitHub during the workflow and then thrown away. Hosted runners are great because you don't have to maintain your own build infrastructure. For workflows that require a specific build environment, or for running workflows on a private network, you can also use private runners. To create a private runner, install the runner on any machine that supports .NET.
job will specify what runner GitHub should use to execute the
steps. You can also specify dependencies between jobs using the
needs attribute. Deployment jobs can also specify an
environment to target.
steps node can be as easy as inline commands, or they can be actions. Most CI workflows will have a combination of
run steps (for executing scripts) and actions. Individual actions are pulled into the workflow by referencing the GitHub Action repository (and optionally a tag or commit hash for specific versions) and specifying any parameters using the
For more information, see GitHub Actions YAML syntax.
From a workflow file, you're able to
run any of the available .NET CLI commands. For example, if you're required to build, test, and deploy an ASP.NET Core Blazor WebAssembly app with Ahead-of-Time (AoT) compilation, you'd use the following commands:
The .NET SDK is a workflow necessity
All .NET workflows require the .NET SDK, and this can be set up by the
actions/setup-dotnet GitHub Action. This action sets up a .NET CLI environment for use in actions. Some GitHub hosted runners have the .NET SDK preinstalled, but that's subject to change. As a best practice, use the
actions/setup-dotnet action to ensure the proper version is available.
Create a basic build workflow
A primary principle of effective DevOps is to "build once, and deploy many times". You'll start by creating a workflow to build a basic .NET app. In the next step, you'll publish the output to prepare for deployment.
Navigate to your GitHub repository and select the Actions tab.
GitHub detects that there's .NET code in the repository and suggests a .NET workflow template. Select Set up this workflow to create a new YAML workflow file:
Figure 1: Creating a new workflow.
Commit the file onto the
mainbranch. Since you've defined a trigger condition for commits to main, this commit should trigger the workflow to run.
Figure 2: Commit the YAML file.
Select the Actions tab again. You should see a running workflow. Once the workflow has completed, you should see a successful run.
Figure 3: Successful build view.
Opening the logs, you can see that the .NET build succeeded and the tests ran and passed.
Figure 4: Checking the logs.
If any of the tests fail, the workflow will fail.
Dissect the workflow file
Let's examine the workflow YAML file you have so far:
name: .NET on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x - name: Restore dependencies run: dotnet restore - name: Build run: dotnet build --no-restore - name: Test run: dotnet test --no-build --verbosity normal
Notice the following things:
- There's a
namethat names the workflow.
onobject specifies when this workflow should run. This workflow has two events that trigger it:
main. Each time someone commits to
mainor creates a pull request (PR) to
main, this workflow will execute.
- There's a single
build. This build should run on a hosted agent.
ubuntu_latestspecifies the most recent Ubuntu hosted agent.
- There are five steps:
actions/checkout@v3is an action that checks out the code in the repository onto the runner.
actions/setup-dotnet@v3is an action that sets up the .NET CLI. This step also specifies a
nameattribute for the logs and the
dotnet-versionparameter within the
runsteps that execute
dotnet build, and
nameattributes are also specified for these
runsteps to make the logs look pretty.
Publish the output
Now that you've successfully built and tested the code, add steps that publish the output so you can deploy the web app.
Navigate to the .github/workflows/dotnet.yml file and select the pencil icon to edit it.
Figure 5: Edit the YAML file.
Add the following
Publishstep below the
Teststep. The step runs the
dotnet publishcommand to publish the web app:
- name: Test run: dotnet test --no-build --verbosity normal # <-- this is the current bottom line - name: Publish run: dotnet publish SimpleFeedReader/SimpleFeedReader.csproj -c Release -o website
This publishes the web app to a folder on the hosted agent. Now you'll want to upload the site as a build artifact that can be deployed to Azure. To complete this activity, you'll use an existing action.
On the list of actions in the Actions Helper pane on the right, search for
artifact. Select on the
Upload a Build Artifact (By actions)action.
Figure 6: Accessing the snippet helper.
Edit the version to
v2.2.2to display a sample snippet. Select the clipboard icon to copy the snippet and paste it into the workflow below the publish step.
Figure 7: Copying a snippet.
Edit the YAML for this step to look as follows:
- name: Upload a Build Artifact uses: actions/upload-artifact@v3 with: name: website path: SimpleFeedReader/website/** if-no-files-found: error
Commit the file.
Once the workflow completes, you'll see the artifact from the Home tab:
Figure 8: Viewing artifacts in the summary page.
Final workflow file
The final workflow file should look something like this:
name: .NET on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x - name: Restore dependencies run: dotnet restore - name: Build run: dotnet build --no-restore - name: Test run: dotnet test --no-build --verbosity normal - name: Publish run: dotnet publish SimpleFeedReader/SimpleFeedReader.csproj -c Release -o website - name: Upload a Build Artifact uses: actions/upload-artifact@v3 with: name: website path: SimpleFeedReader/website/** if-no-files-found: error