~/blog|
Published on

Build .NET Core Applications using GitLab CI

Authors

Updated for .NET 5

GitLab CI has the ability to utilize any docker container in order to build and deploy an application. This makes it an extremely flexible tool. This article will go through building out a GitLab CI pipeline for a .NET Core application.

Create Basic Application

First, let's build out our basic application and test suite using the dotnet CLI. Create a new directory for your project and go through the following commands:

mkdir MyApp MyApp.Tests
cd MyApp
dotnet new webapi
cd ../MyApp.Tests
dotnet new nunit
cd ..
dotnet new sln
dotnet sln add **/*.csproj

We've now built out a basic application and test suite to use in our pipeline.

Before we move forward, here is our simplified project structure:

.
|-- MyApp
|   |-- MyApp.csproj
|   |-- Program.cs
|   `-- Startup.cs
|-- MyApp.Tests
|   |-- MyApp.Tests.csproj
|   `-- UnitTest1.cs
`-- MyApp.sln

Create Pipeline

GitLab CI is driven by having a .gitlab-ci.yml file at the root of the project. Create this file now. The first thing we will put into this file is our base image

image: mcr.microsoft.com/dotnet/sdk:5.0

This is the official dotnet core image from Microsoft. It includes the latest .NET Core SDK, which provides everything needed to build out an application. A container running this image will be where our scripts will run and application code cloned into. The version can also be changed to build previous dotnet versions.

Next, we define our stages. We will be building out 3 distinct stages: build, test, and release. Those are added by adding this block:

stages:
  - build
  - test
  - release

Now that our stages are set up, we can add build steps and associate them with our defined stages. We just happen to want a single step for each of the build and test stages.

Let's add the build step that will build via the dotnet CLI:

build:
  stage: build
  script:
    - dotnet build

The top-level value can be named anything you'd like. If you only have one step per stage, keeping them the same name keeps things simple. However, the stage value must specify one of the listed stages from above. This is how GitLab CI knows what stage to run this step on.

If the build stage succeeds, we want our unit tests to run. The following block will run the test command via the dotnet CLI:

test:
  stage: test
  script:
    - dotnet test

The release step will be more complex than the previous because we will be using the dotnet publish command along with capturing the generated artifacts. This is the release block:

release:
  stage: release
  only:
    - master
  artifacts:
    paths:
      - publish/
  script:
    - dotnet publish -c Release -o ../publish MyApp/MyApp.csproj

Let's break down each piece of this step.

  • The only section specifies that this step will only run on our master branch. This is to avoid generating artifacts for feature branches
  • The artifacts path points to our intended output directory
  • The dotnet publish command outputs into a publish directory at our project root. Make note of the ../ before publish as the dotnet publish command outputs relative to the csproj file that is specified, so we want the artifacts to be output one directory up at the root.

Our full .gitlab-ci.yml file should now look like this:

image : mcr.microsoft.com/dotnet/sdk:5.0

stages:
  - build
  - test
  - release

build:
  stage: build
  script:
    - dotnet build

test:
  stage: test
  script:
    - dotnet test

release:
  stage: release
  only:
    - master
  artifacts:
    paths:
      - publish/
  script:
    - dotnet publish -c Release -o ../publish MyApp/MyApp.csproj

If we commit this code and navigate to CI/CD -> Pipelines in our GitLab repository, we will be able to see a pipeline that ran for the commit. If successful, each step will have a green check and artifacts will be available for download. If there was a failure, it will be a red X that can be clicked on to see more detail.

GitLab CI Pipeline

Additional steps can be added beyond what I've provided, but they would differ greatly based upon your environment. This application could easily be put into a Docker image and pushed either to the GitLab image registry or your Kubernetes cluster. However, that would warrant an entire article on its own. You now have a basic CI pipeline for your .NET Core application!