Modern software development is all about delivering features quickly without compromising quality. Manually building, testing, and deploying applications is time-consuming, error-prone, and difficult to scale.

This is where Continuous Integration (CI) and Continuous Deployment (CD) come into play. GitLab provides an integrated DevOps platform that enables developers to automate the entire software delivery lifecycle—from code commit to production deployment.

In this guide, you'll learn how to create a CI/CD pipeline for an ASP.NET Core application using GitLab.


What is CI/CD?

Continuous Integration (CI)

Continuous Integration is the practice of automatically building and testing your code whenever developers push changes to the repository.

Benefits include:

  • Early bug detection
  • Automated testing
  • Faster feedback
  • Improved code quality
  • Easier team collaboration

CI Workflow

Developer
    │
    ▼
Git Push
    │
    ▼
GitLab Repository
    │
    ▼
Build Application
    │
    ▼
Run Unit Tests
    │
    ▼
Generate Artifacts

Continuous Deployment (CD)

Continuous Deployment extends CI by automatically deploying successful builds to development, staging, or production environments.

Deployment workflow:

Build Success
      │
      ▼
Deploy to Development
      │
      ▼
Run Smoke Tests
      │
      ▼
Deploy to Staging
      │
      ▼
Manual Approval
      │
      ▼
Production

Why Choose GitLab for CI/CD?

GitLab combines source control, issue tracking, CI/CD, security scanning, and deployment tools into one platform.

Advantages

  • Built-in CI/CD
  • Docker integration
  • Kubernetes support
  • Security scanning
  • Container Registry
  • Infrastructure as Code support
  • Pipeline visualization
  • Merge Request validation

Prerequisites

Before you begin, ensure you have:

  • GitLab account
  • ASP.NET Core project
  • Git installed
  • .NET SDK
  • Docker (optional)
  • GitLab Runner

Understanding GitLab Runners

A GitLab Runner executes pipeline jobs.

The process looks like this:

Git Push
      │
      ▼
GitLab Server
      │
      ▼
GitLab Runner
      │
      ▼
Build
Test
Deploy

Runner types include:

  • Shared Runners
  • Group Runners
  • Project-specific Runners

GitLab CI/CD Pipeline Stages

A typical ASP.NET Core pipeline contains the following stages:

Restore
   │
Build
   │
Test
   │
Publish
   │
Package
   │
Deploy

Creating the .gitlab-ci.yml File

GitLab uses a YAML configuration file stored in the root of your repository.

Example:

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

stages:
  - restore
  - build
  - test
  - publish

restore:
  stage: restore
  script:
    - dotnet restore

build:
  stage: build
  script:
    - dotnet build --configuration Release --no-restore

test:
  stage: test
  script:
    - dotnet test --configuration Release --no-build

publish:
  stage: publish
  script:
    - dotnet publish -c Release -o publish
  artifacts:
    paths:
      - publish/

Whenever code is pushed, GitLab automatically executes these stages.


Building an ASP.NET Core Application

The build job compiles the application.

build:
  stage: build
  script:
    - dotnet build MyWebApp.csproj -c Release

Running Unit Tests

Automated tests ensure new code doesn't break existing functionality.

test:
  stage: test
  script:
    - dotnet test

You can also generate test reports for integration with GitLab's reporting features.


Publishing Build Artifacts

Artifacts allow later pipeline stages to reuse the published application.

publish:
  stage: publish
  script:
    - dotnet publish -c Release -o publish
  artifacts:
    paths:
      - publish/

Deploying to IIS

Example deployment using PowerShell:

deploy:
  stage: deploy
  script:
    - powershell ./Deploy.ps1

Example Deploy.ps1:

Stop-WebAppPool "MyAppPool"

Copy-Item publish\* "C:\inetpub\wwwroot\MyApp" -Recurse -Force

Start-WebAppPool "MyAppPool"

Deploying with Docker

Build Docker image:

docker-build:
  stage: publish
  script:
    - docker build -t myapp .

Push image:

docker-push:
  stage: deploy
  script:
    - docker push registry.gitlab.com/project/myapp:latest

Using Environment Variables

Never store secrets directly in your repository.

Use GitLab CI/CD Variables for:

  • Database connection strings
  • API keys
  • JWT secrets
  • Azure credentials
  • AWS credentials

Example:

script:
  - echo $DATABASE_CONNECTION

Branch-Based Deployment

Deploy only specific branches.

deploy-production:
  stage: deploy
  only:
    - main

Deploy development branch separately:

deploy-dev:
  stage: deploy
  only:
    - develop

Pipeline Example

Developer Push
      │
      ▼
GitLab Repository
      │
      ▼
Restore Packages
      │
      ▼
Build
      │
      ▼
Unit Tests
      │
      ▼
Publish
      │
      ▼
Create Docker Image
      │
      ▼
Push Registry
      │
      ▼
Deploy Production

Best Practices

  • Keep pipelines fast by caching NuGet packages.
  • Run unit tests on every commit.
  • Separate development, staging, and production environments.
  • Store secrets using GitLab CI/CD Variables.
  • Use Docker for consistent deployments.
  • Add code quality and security scanning jobs.
  • Enable merge request pipelines to validate changes before merging.
  • Use artifacts instead of rebuilding the application in later stages.
  • Version your application using Git tags or semantic versioning.
  • Monitor pipeline duration and optimize slow jobs.

Common CI/CD Challenges

Challenge Solution
Long build times Cache dependencies and run jobs in parallel
Deployment failures Add health checks and rollback strategies
Secret management Use GitLab protected variables
Environment differences Deploy with Docker containers
Flaky tests Stabilize tests and isolate external dependencies

Real-World Workflow

Imagine a team working on an ASP.NET Core Web API:

  1. A developer pushes code to a feature branch.
  2. GitLab automatically restores packages.
  3. The project is built.
  4. Unit tests execute.
  5. Code quality checks run.
  6. A Docker image is created.
  7. The image is pushed to the GitLab Container Registry.
  8. The staging environment is updated automatically.
  9. After approval, the application is deployed to production.

This automated workflow reduces manual effort, catches issues earlier, and ensures consistent deployments.


Conclusion

GitLab CI/CD simplifies the software delivery process by automating builds, tests, and deployments within a single platform. For ASP.NET Core developers, integrating GitLab pipelines into your workflow improves code quality, accelerates releases, and reduces deployment errors.

Start with a simple pipeline that restores, builds, tests, and publishes your application. As your project grows, enhance it with Docker, security scanning, environment-specific deployments, and monitoring to create a robust DevOps pipeline.


Interview Questions 

What is the difference between CI and CD?

Continuous Integration (CI) focuses on automatically building and testing code changes, while Continuous Deployment (CD) automates the release of successful builds to target environments.

Do I need a GitLab Runner?

Yes. A GitLab Runner is responsible for executing your pipeline jobs. You can use GitLab-hosted shared runners or install your own self-hosted runner.

Can GitLab deploy ASP.NET Core applications to IIS?

Yes. You can automate IIS deployments using PowerShell scripts, Web Deploy, or deployment tools executed by a Windows-based GitLab Runner.

Can GitLab work with Docker and Kubernetes?

Absolutely. GitLab has excellent support for Docker image builds, its integrated Container Registry, and Kubernetes deployments.

Is GitLab CI/CD free?

GitLab offers a free tier with CI/CD capabilities. Advanced enterprise features such as enhanced security, compliance, and portfolio management are available in paid plans