Build .NET Core Applications using GitLab CI
Tags: csharp, dotnet, gitlab, devops
Published: 2019-05-24 12:23:47

---
title: Build .NET Core Applications using GitLab CI
description: Utilize GitLab CI to build and test your .NET Core application
published: true
tags: csharp, dotnet, gitlab, devops
canonical_url: https://elliotdenolf.com/posts/build-net-core-applications-using-gitlab-ci/
---

> Originally posted on my blog at https://elliotdenolf.com/posts/build-net-core-applications-using-gitlab-ci

> 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.

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>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:

```sh
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
```

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>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

```yml
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:

```yml
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:

```yml
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:

```yml
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:

```yml
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:

```yml
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](https://elliotdenolf.com/media/pipeline-1.png)

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!

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Links

- **[Source code for this example](https://github.com/denolfe/blog-code-samples/tree/master/posts/build-net-core-using-gitlab-ci)**
- [GitLab CI](https://docs.gitlab.com/ee/ci/)
- [Dotnet CLI documentation](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x)