Build Artifacts in Azure DevOps – Publishing and Consuming Between CI/CD Stages
1. What is a Build Artifact?
A Build Artifact is the output generated after successfully building an application in a CI pipeline.
For an ASP.NET Core application, the artifact typically contains compiled DLL files, dependencies, configuration files, and other files required for deployment.
Main purpose:
-
Store successfully built application files.
-
Share build outputs between CI and CD pipelines.
-
Deploy the same application package to SIT, UAT, and Production.
-
Avoid rebuilding the application for each environment.
-
Support version tracking and deployment rollback.
Example:
ASP.NET Core Source Code
|
v
dotnet restore
|
v
dotnet build
|
v
dotnet test
|
v
dotnet publish
|
v
MyApp.API.zip
|
v
Pipeline Artifact
(drop)
|
v
CD Pipeline
|
+----> SIT
|
+----> UAT
|
+----> Production
Here, drop is the artifact name, and MyApp.API.zip is the deployable package.
2. How Do You Publish a Build Artifact?
In Azure DevOps, we commonly use PublishPipelineArtifact@1 to upload build outputs.
Step 1: Publish ASP.NET Core application
- task: DotNetCoreCLI@2
displayName: 'Publish ASP.NET Core API'
inputs:
command: 'publish'
publishWebProjects: false
projects: 'src/MyApp.API/MyApp.API.csproj'
arguments: >
--configuration Release
--output $(Build.ArtifactStagingDirectory)/publish
zipAfterPublish: true
modifyOutputPath: false
This creates a ZIP package inside the artifact staging directory.
Step 2: Publish the artifact to Azure DevOps
- task: PublishPipelineArtifact@1
displayName: 'Publish Artifact'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/publish'
artifact: 'drop'
publishLocation: 'pipeline'
Explanation:
|
Property |
Purpose |
|---|---|
|
|
Location of the files to upload |
|
|
Artifact name, here |
|
|
|
After successful execution, the artifact appears under the pipeline run's Artifacts section.
3. How Do You Consume Artifacts in a Deployment Stage?
The deployment stage downloads the artifact generated by the build stage.
We use DownloadPipelineArtifact@2 to download artifacts explicitly.
- task: DownloadPipelineArtifact@2
displayName: 'Download Build Artifact'
inputs:
buildType: 'current'
artifactName: 'drop'
targetPath: '$(Pipeline.Workspace)/drop'
Explanation:
-
buildType: currentdownloads artifacts from the current pipeline run. -
artifactName: dropspecifies the artifact to download. -
targetPathspecifies the download directory.
After downloading:
$(Pipeline.Workspace)/
|
+-- drop/
|
+-- MyApp.API.zip
The deployment task can now use MyApp.API.zip to deploy the application.
4. Complete Multi-Stage YAML Example
This example builds an ASP.NET Core application, publishes its artifact, and consumes it in a deployment stage targeting Azure App Service.
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
stages:
# ==========================
# STAGE 1: BUILD (CI)
# ==========================
- stage: Build
displayName: 'Build ASP.NET Core Application'
jobs:
- job: BuildJob
steps:
- checkout: self
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.0.x'
- script: dotnet restore MyApplication.sln
displayName: 'Restore Packages'
- script: >
dotnet build MyApplication.sln
--configuration $(buildConfiguration)
--no-restore
displayName: 'Build Solution'
- script: >
dotnet test tests/MyApp.Tests/MyApp.Tests.csproj
--configuration $(buildConfiguration)
--no-build
displayName: 'Run Unit Tests'
- task: DotNetCoreCLI@2
displayName: 'Publish Application'
inputs:
command: 'publish'
publishWebProjects: false
projects: 'src/MyApp.API/MyApp.API.csproj'
arguments: >
--configuration $(buildConfiguration)
--output $(Build.ArtifactStagingDirectory)/publish
zipAfterPublish: true
modifyOutputPath: false
- task: PublishPipelineArtifact@1
displayName: 'Publish Artifact'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/publish'
artifact: 'drop'
publishLocation: 'pipeline'
# ==========================
# STAGE 2: DEPLOY (CD)
# ==========================
- stage: DeploySIT
displayName: 'Deploy to SIT'
dependsOn: Build
jobs:
- deployment: DeployJob
environment: 'SIT'
strategy:
runOnce:
deploy:
steps:
# Download artifact
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'drop'
targetPath: '$(Pipeline.Workspace)/drop'
# Deploy to Azure App Service
- task: AzureWebApp@1
displayName: 'Deploy ASP.NET Core API'
inputs:
azureSubscription: 'MyAzureServiceConnection'
appType: 'webAppLinux'
appName: 'myapp-sit'
package: '$(Pipeline.Workspace)/drop/*.zip'
The example assumes an existing Azure service connection, a Linux Azure App Service, and an Azure DevOps environment named SIT. Deployment jobs can also automatically download artifacts; the explicit download task is included to demonstrate the process.
5. Build Artifacts vs Pipeline Artifacts
Azure DevOps supports two commonly encountered artifact mechanisms.
|
Feature |
Build Artifacts |
Pipeline Artifacts |
|---|---|---|
|
Publish task |
|
|
|
Download task |
|
|
|
Performance |
Older mechanism |
Generally faster and more efficient |
|
Classic Release Pipelines |
Supported |
Not directly supported |
|
YAML pipelines |
Supported |
Recommended for Azure DevOps Services |
|
Azure DevOps Server |
Supported |
Pipeline Artifacts tasks are not supported |
Recommendation: For new multi-stage YAML pipelines in Azure DevOps Services, prefer Pipeline Artifacts.
6. How Does the Same Artifact Move Between SIT, UAT, and Production?
A recommended CI/CD practice is to build once and deploy the same artifact across all environments.
Developer Pushes Code
|
v
CI Pipeline
|
v
Build + Test
|
v
Publish Artifact
|
v
drop.zip
|
v
Deploy to SIT
|
| Tests Passed
v
Deploy to UAT
|
| Approval
v
Deploy to Production
For example:
|
Environment |
Artifact |
Configuration |
|---|---|---|
|
SIT |
Build 105 – |
SIT database and API settings |
|
UAT |
Build 105 – |
UAT database and API settings |
|
Production |
Build 105 – |
Production database and API settings |
All environments use the same application binaries. Environment-specific configuration and secrets are supplied separately during deployment or at runtime.
This improves consistency and reduces the risk of introducing different code into Production.
7. Important Interview Questions
Q1. What is the difference between dotnet publish and PublishPipelineArtifact@1?
dotnet publish generates deployable application files, while PublishPipelineArtifact@1 uploads those files to Azure DevOps for storage and consumption by other stages.
Q2. Can multiple deployment stages consume the same artifact?
Yes. SIT, UAT, and Production stages can download the same artifact from the CI pipeline run.
Q3. Can a deployment pipeline consume artifacts from another pipeline?
Yes. We can use pipeline resources to reference another pipeline and download its artifacts.
Example:
resources:
pipelines:
- pipeline: ci
source: 'ASP.NET-Core-CI'
trigger: none
steps:
- download: ci
artifact: drop
Here, ASP.NET-Core-CI is the producing pipeline, and ci is its resource alias.
Q4. What happens if artifact publishing fails?
The publishing task fails, and the pipeline normally fails. Deployment stages depending on successful completion will not run.
Q5. Why should we not rebuild the application for every environment?
Rebuilding can introduce differences in binaries or dependencies. Reusing the same artifact ensures that the application tested in SIT and UAT is the one deployed to Production.
Q6. Can we download artifacts from previous pipeline runs?
Yes. Azure DevOps allows downloading artifacts from retained pipeline runs, which can help with redeployment and rollback.
8. Interview-Ready Answer
A build artifact is the deployable output generated by a successful CI pipeline. In ASP.NET Core applications, it usually contains compiled DLLs, dependencies, configuration files, and deployment packages.
In Azure DevOps, after restoring dependencies, building the solution, and running unit tests, I use
dotnet publishto generate the deployment files.I then use
PublishPipelineArtifact@1to upload those files to Azure DevOps, usually with an artifact name such asdrop.During deployment, I use
DownloadPipelineArtifact@2or the YAMLdownloadkeyword to retrieve the artifact and deploy it to SIT, UAT, and Production.The main advantage is that we build the application once and deploy the same tested artifact across all environments, ensuring consistency and reliability.
Key sequence to remember:
dotnet publish
|
v
PublishPipelineArtifact@1
|
v
Azure DevOps Artifact (drop)
|
v
DownloadPipelineArtifact@2
|
v
Deployment to SIT / UAT / PROD
Most important interview point: Publishing an application and publishing a pipeline artifact are two different operations. The first prepares the deployable files; the second stores and shares them between pipeline stages.