Using dotnet restore, build, test, and publish in Azure CI Pipelines
1. What are these commands?
In an ASP.NET Core CI pipeline, four important .NET CLI commands automate the process of preparing, compiling, testing, and packaging an application.
|
Command |
Purpose |
|---|---|
|
|
Downloads required NuGet packages |
|
|
Compiles the application and checks for compilation errors |
|
|
Executes automated tests |
|
|
Generates deployable application files |
These commands are generally executed sequentially in Azure Pipelines.
2. How do they work?
Developer Pushes Code
|
v
Azure DevOps CI Pipeline
|
v
1. dotnet restore
Download NuGet Dependencies
|
v
2. dotnet build
Compile the Application
|
v
3. dotnet test
Execute Automated Tests
|
v
4. dotnet publish
Generate Deployment Files
|
v
Publish Pipeline Artifact
|
v
Available for CD Pipeline
3. Explanation of Each Command
A. dotnet restore
Purpose: Restore all NuGet dependencies required by the application.
dotnet restore MyApplication.sln
How it works:
-
Reads project files and NuGet configuration.
-
Resolves package dependencies.
-
Downloads missing packages from configured NuGet feeds.
-
Uses the local NuGet cache when packages are already available.
-
Generates or updates dependency information in
obj/project.assets.json.
For example, if the ASP.NET Core application uses Entity Framework Core and Serilog, restore ensures the required packages are available.
Important: If package restoration fails, the pipeline stops.
B. dotnet build
Purpose: Compile the source code and validate that the application builds successfully.
dotnet build MyApplication.sln --configuration Release --no-restore
How it works:
-
Compiles C# source code.
-
Checks compilation errors.
-
Builds referenced projects in dependency order.
-
Generates assemblies such as
.dllfiles. -
Reports compiler warnings and errors.
Example output:
MyApp.Domain.dll
MyApp.Application.dll
MyApp.Infrastructure.dll
MyApp.API.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Important: --no-restore avoids repeating the restore step.
C. dotnet test
Purpose: Execute automated tests to verify application functionality.
dotnet test tests/MyApp.Tests/MyApp.Tests.csproj \
--configuration Release \
--no-build
How it works:
-
Discovers tests from the test project.
-
Executes unit tests using the configured test framework, such as xUnit, NUnit, or MSTest.
-
Reports passed, failed, and skipped tests.
-
Returns a failure status when tests fail.
Example output:
Total tests: 25
Passed: 24
Failed: 1
Skipped: 0
Test Run Failed.
Important: --no-build avoids recompiling the test project, assuming it was built in the previous step.
D. dotnet publish
Purpose: Prepare the application for deployment.
dotnet publish src/MyApp.API/MyApp.API.csproj \
--configuration Release \
--no-build \
--output ./publish
How it works:
-
Collects compiled application assemblies.
-
Includes required runtime dependencies.
-
Copies applicable configuration and content files.
-
Generates deployment-specific files.
-
Places everything in the specified output directory.
Example output:
publish/
│
├── MyApp.API.dll
├── MyApp.API.deps.json
├── MyApp.API.runtimeconfig.json
├── appsettings.json
├── appsettings.Production.json
├── web.config (for IIS targets)
└── Other dependencies
The exact output depends on the deployment target and publish settings.
Important: --no-build is appropriate when the application has already been built using compatible settings. dotnet publish otherwise performs a build automatically.
4. Azure Pipelines YAML Example
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
# Step 1: Checkout
- checkout: self
# Step 2: Install .NET SDK
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.0.x'
# Step 3: Restore
- script: dotnet restore MyApplication.sln
displayName: 'Restore Packages'
# Step 4: Build
- script: >
dotnet build MyApplication.sln
--configuration $(buildConfiguration)
--no-restore
displayName: 'Build Solution'
# Step 5: Test
- script: >
dotnet test tests/MyApp.Tests/MyApp.Tests.csproj
--configuration $(buildConfiguration)
--no-build
displayName: 'Run Unit Tests'
# Step 6: Publish
- script: >
dotnet publish src/MyApp.API/MyApp.API.csproj
--configuration $(buildConfiguration)
--no-build
--output $(Build.ArtifactStagingDirectory)/publish
displayName: 'Publish Application'
# Step 7: Publish Artifact
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/publish'
artifact: 'drop'
publishLocation: 'pipeline'
The pipeline generates an artifact named drop, containing the published ASP.NET Core application files.
5. Important Differences
|
Feature |
Restore |
Build |
Test |
Publish |
|---|---|---|---|---|
|
Downloads NuGet dependencies |
Yes |
Implicitly* |
Implicitly* |
Implicitly* |
|
Compiles application |
No |
Yes |
By default |
By default |
|
Executes unit tests |
No |
No |
Yes |
No |
|
Generates deployable output |
No |
No |
No |
Yes |
|
Common CI order |
1 |
2 |
3 |
4 |
--no-restore. Test and publish can also skip building when configured appropriately.
6. Interview Questions and Answers
Q1. Why do we execute dotnet restore before dotnet build?
To ensure all required NuGet packages are available before compilation.
Q2. Does dotnet build automatically execute dotnet restore?
Yes. By default, dotnet build performs an implicit restore unless --no-restore is specified.
Q3. What is the difference between dotnet build and dotnet publish?
dotnet build compiles the application, while dotnet publish prepares the compiled application and dependencies for deployment.
Q4. Does dotnet test build the project automatically?
Yes, by default. We can use --no-build when the test project has already been compiled.
Q5. Why do we use --no-build and --no-restore in CI pipelines?
To avoid repeating operations that have already completed successfully, reducing unnecessary build time.
Q6. What happens if dotnet test fails?
The CI pipeline normally stops, and the publish and artifact-generation steps are skipped.
Q7. Is dotnet publish the same as publishing an Azure Pipeline Artifact?
No. dotnet publish generates deployable application files. PublishPipelineArtifact@1 uploads those files to Azure DevOps for later use.
7. Interview-Ready Answer
In Azure DevOps CI pipelines, I use four main .NET CLI commands to build and prepare ASP.NET Core applications.
First,
dotnet restoredownloads the required NuGet dependencies. Next,dotnet buildcompiles the entire solution in Release mode.After successful compilation,
dotnet testexecutes automated unit tests. If any test fails, the pipeline stops.Finally,
dotnet publishgenerates the deployment-ready application files. These files are then uploaded to Azure DevOps using the Publish Pipeline Artifact task.I use
--no-restoreand--no-buildwhere appropriate to avoid repeating operations and improve pipeline performance.
Remember this sequence:
dotnet restore
↓
dotnet build
↓
dotnet test
↓
dotnet publish
↓
PublishPipelineArtifact@1
↓
Deployment Artifact
Key interview point: dotnet publish creates the deployable files, whereas PublishPipelineArtifact@1 stores those files in Azure DevOps.