<p>Can I suggest building and publishing the artefacts in <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&amp;tabs=yaml" rel="noreferrer">separate jobs</a>? That would mean that each job is simpler (no need to specify an artefact subfolder), and might give you some speed-up by running them in parallel. Something like this:</p>

<pre class="lang-yaml prettyprint-override"><code>jobs:
  - job: web_api
    displayName: Web API Build and Artifact
    steps:
      - checkout: self

      - task: DotNetCoreCLI@2
        displayName: 'Build'
        inputs:
          command: 'build'
          projects: '**/DevOpsApi.csproj'
          arguments: '--configuration $(buildConfiguration)'
      
      - task: DotNetCoreCLI@2
        inputs:
          command: 'test'
          projects: '**/*Tests.csproj'
          arguments: '--configuration $(buildConfiguration)'
          testRunTitle: 'Unit Tests'
      
      # Publish the artifact
      - task: DotNetCoreCLI@2
        inputs:
          command: 'publish'
          # This need to be false in order for the specific project to be published
          publishWebProjects: False
          projects: '**/DevOpsApi.csproj'
          arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
          zipAfterPublish: True
      
      # Publish the artifact for the pipelines to use
      - task: PublishBuildArtifacts@1
        displayName: 'Publishing WebAPI Artifact'
        inputs:
          pathtoPublish: '$(Build.ArtifactStagingDirectory)' 
          artifactName: 'TestWebApi-Wip'
  
  - job: web_app
    displayName: Web APP Build and Artifact
    dependsOn: []
    steps:
      - checkout: self

      - task: DotNetCoreCLI@2
        displayName: 'Build'
        inputs:
          command: 'build'
          projects: '**/DevOpsApp.csproj'
          arguments: '--configuration $(buildConfiguration)'
      
      # Publish the artifact
      - task: DotNetCoreCLI@2
        inputs:
          command: 'publish'
          # This need to be false in order for the specific project to be published
          publishWebProjects: False
          projects: '**/DevOpsApp.csproj'
          arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
          zipAfterPublish: True
      
      # Publish the artifact for the pipelines to use
      - task: PublishBuildArtifacts@1
        displayName: 'Publishing WebAPP Artifact'
        inputs:
          pathtoPublish: '$(Build.ArtifactStagingDirectory)' 
          artifactName: 'TestWebApp-Wip'
</code></pre>
<p>Also: if each job tends to have a similar set of tasks, you could refactor them into a <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops" rel="noreferrer">template</a> to keep the pipeline code terser.</p>

CC BY-SA 4.0
2022-01-19T10:19:19.360Z
I know that name Vince Bowdren, think I've worked with you in the past, :) Cheers
Andrew
CC BY-SA 4.0
2021-12-18T19:59:02.793Z
2021-12-18T19:59:02.793Z
Vince Bowdren
<p>I managed to get Erik's approach working which is great.</p>
<p>I then wondered if I could simplify it so instead of deleting the content how about put each artifact in a sub folder of the <strong>$(Build.ArtifactStagingDirectory)</strong> So by just appending /Api or /App I could create specific publish folders that I could then push onto the azure pipeline.</p>
<p>You can then have as many artifacts as you need :)</p>
<p>The important parts to take from this are that <strong>publishWebProjects</strong> needs to be set to <strong>false</strong> or it defaults to true and then ignores the projects line below, and the <strong>output</strong> path puts the content in a sub folder.</p>
<pre><code> # This need to be false in order for the specific project to be published
 publishWebProjects: False
 projects: '**/DevOpsApp.csproj'
 arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/App'
</code></pre>
<p>and <strong>pathtoPublish</strong> need to then point to the sub folder</p>
<pre><code>pathtoPublish: '$(Build.ArtifactStagingDirectory)/App'
</code></pre>
<p>Full example file below</p>
<pre><code># ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core

trigger:
- develop

pool:
  vmImage: 'ubuntu-latest'

variables:
    buildConfiguration: 'Release'
    versionNumber: 1.0.0

name: $(versionNumber)-wip-$(Rev:r)

#----------------------------------------------------------
# Web API Build and Artifact
#----------------------------------------------------------

steps:
- task: DotNetCoreCLI@2
  displayName: 'Build'
  inputs:
    command: 'build'
    projects: '**/DevOpsApi.csproj'
    arguments: '--configuration $(buildConfiguration)'

- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    projects: '**/*Tests.csproj'
    arguments: '--configuration $(buildConfiguration)'
    testRunTitle: 'Unit Tests'

# Publish the artifact
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    # This need to be false in order for the specific project to be published
    publishWebProjects: False
    projects: '**/DevOpsApi.csproj'
    arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/Api'
    zipAfterPublish: True

# Publish the artifact for the pipelines to use
- task: PublishBuildArtifacts@1
  displayName: 'Publishing WebAPI Artifact'
  inputs:
    pathtoPublish: '$(Build.ArtifactStagingDirectory)/Api' 
    artifactName: 'TestWebApi-Wip'

#----------------------------------------------------------
# Web APP Build and Artifact
#----------------------------------------------------------

- task: DotNetCoreCLI@2
  displayName: 'Build'
  inputs:
    command: 'build'
    projects: '**/DevOpsApp.csproj'
    arguments: '--configuration $(buildConfiguration)'

# Publish the artifact
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    # This need to be false in order for the specific project to be published
    publishWebProjects: False
    projects: '**/DevOpsApp.csproj'
    arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/App'
    zipAfterPublish: True

# Publish the artifact for the pipelines to use
- task: PublishBuildArtifacts@1
  displayName: 'Publishing WebAPP Artifact'
  inputs:
    pathtoPublish: '$(Build.ArtifactStagingDirectory)/App' 
    artifactName: 'TestWebApp-Wip'
</code></pre>

CC BY-SA 4.0
2021-01-14T08:37:50.973Z
2021-01-14T08:37:50.973Z
Andrew
<p>Here is my YAML for multiple artifacts from a single build.</p>

<pre><code>pool:
  name: Hosted Windows 2019 with VS2019
  demands:
  - msbuild
  - visualstudio
  - vstest
  - npm

steps:
- task: NuGetToolInstaller@0
  displayName: 'Use NuGet 4.4.1'
  inputs:
    versionSpec: 4.4.1

- task: NuGetCommand@2
  displayName: 'NuGet restore'
  inputs:
    restoreSolution: '$(Parameters.solution)'

- task: VSBuild@1
  displayName: 'Build solution WebApi'
  inputs:
    solution: '$(Parameters.solution)'
    msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactstagingdirectory)\\"'
    platform: '$(BuildPlatform)'
    configuration: '$(BuildConfiguration)'
    msbuildArchitecture: x64

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: WebApi'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
    ArtifactName: 'dotnet-webapi'
  condition: succeededOrFailed()

- task: DeleteFiles@1
  displayName: 'Delete build.artifactstagingdirectory for Angular'
  inputs:
    SourceFolder: '$(build.artifactstagingdirectory)'
    Contents: '**'

- task: Npm@1
  displayName: 'npm install'
  inputs:
    workingDir: project/ClientApp
    verbose: false

- task: Npm@1
  displayName: 'npm run prod-build'
  inputs:
    command: custom
    workingDir: project/ClientApp
    verbose: false
    customCommand: 'run prod-build'

- task: Npm@1
  displayName: 'npm run dev-build'
  inputs:
    command: custom
    workingDir: project/ClientApp
    verbose: false
    customCommand: 'run prod-dev'
  enabled: false

- task: CopyFiles@2
  displayName: 'Copy Angular/Dist to build.artifactstagingdirectory'
  inputs:
    SourceFolder: project/ClientApp/dist/ClientApp
    Contents: |
     **
     !config.json
    TargetFolder: '$(build.artifactstagingdirectory)'

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: Angular'
  inputs:
    ArtifactName: angular

</code></pre>

CC BY-SA 4.0
2020-04-10T00:19:39.950Z
In a release pipeline, how would you specify which Build Artifact to use?
Dbloom
CC BY-SA 4.0
2020-07-08T22:10:08.937Z
@Dbloom Both artifacts are available when you select a folder/archive/package in the  release pipeline task.  So I just select the one I need for the correct release task.
Erik Philips
CC BY-SA 4.0
2019-11-20T17:33:18.283Z
2019-11-20T17:33:18.283Z
Erik Philips
<p>I'm a little confused on the Azure Pipeline steps.  My solutions has many projects and one <em>UI</em> project that contains both an ASP.Net-Core WebApi/MVC with Angular.</p>

<p>the <code>Build Solution</code> builds similar to the</p>

<pre><code>steps:
- task: VSBuild@1
  displayName: 'Build solution'
  inputs:
    solution: '$(Parameters.solution)'
    msbuildArgs: '/p:DeployOnBuild=true 
      /p:WebPublishMethod=Package 
      /p:PackageAsSingleFile=true 
      /p:SkipInvalidConfigurations=true 
      /p:PackageLocation="$(build.artifactstagingdirectory)\\"'
    platform: '$(BuildPlatform)'
    configuration: '$(BuildConfiguration)'

</code></pre>

<p>The default <code>Publish Artifact</code> is:</p>

<pre><code>steps:
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: drop'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
  condition: succeededOrFailed()

</code></pre>

<p>I'd like to do something with 2 artifacts (this doesn't work):</p>

<pre><code>steps:
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: webapi'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)\\MVCProject\bin\$(BuildConfiguration)\netcorapp2.2'
    ArtifactName: webapi
  condition: succeededOrFailed()

steps:
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: angular'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)\\MVCProject\clientapp\dist'
    ArtifactName: angular
  condition: succeededOrFailed()

</code></pre>

<p>What am I missing / What the <em>right/better</em> way to do this.
(moving angular out of the project does not solve this problem, and we aren't ready for that yet)</p>

CC BY-SA 4.0
2019-11-07T11:58:05.483Z
Did you solve this? I've ran into a similar decision. FWIW I went the other way, that is: a single artifact with multiple packages.

I ran into all sorts of issues with this as it seems to confuse the release pipeline and it's any persons' guess as to which application is deployed where...
Ste Pammenter
CC BY-SA 4.0
2019-11-20T01:23:45.637Z
@StePammenter Yes I did (finally).  Answer incoming.
Erik Philips
CC BY-SA 4.0
2019-11-20T10:50:19.710Z
Thanks for getting back. As it turned out for me, my fault was in copying the same Azure function settings, not with the pipeline itself!
Ste Pammenter
<azure-devops><azure-pipelines><artifacts>
Single Build with Multiple Artifacts
Erik Philips
# Single Build with Multiple Artifacts

(Asked by: username_0 on 2019-09-12)

I'm a little confused on the Azure Pipeline steps.  My solutions has many projects and one UI project that contains both an ASP.Net-Core WebApi/MVC with Angular.
the Build Solution builds similar to the
steps:
- task: VSBuild@1
  displayName: 'Build solution'
  inputs:
    solution: '$(Parameters.solution)'
    msbuildArgs: '/p:DeployOnBuild=true 
      /p:WebPublishMethod=Package 
      /p:PackageAsSingleFile=true 
      /p:SkipInvalidConfigurations=true 
      /p:PackageLocation="$(build.artifactstagingdirectory)\\"'
    platform: '$(BuildPlatform)'
    configuration: '$(BuildConfiguration)'


The default Publish Artifact is:
steps:
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: drop'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
  condition: succeededOrFailed()


I'd like to do something with 2 artifacts (this doesn't work):
steps:
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: webapi'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)\\MVCProject\bin\$(BuildConfiguration)\netcorapp2.2'
    ArtifactName: webapi
  condition: succeededOrFailed()

steps:
- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: angular'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)\\MVCProject\clientapp\dist'
    ArtifactName: angular
  condition: succeededOrFailed()


What am I missing / What the right/better way to do this.
(moving angular out of the project does not solve this problem, and we aren't ready for that yet)

**Tags:** azure-devops, azure-pipelines, artifacts

> **Comments:**
> **username_1**: Did you solve this? I've ran into a similar decision. FWIW I went the other way, that is: a single artifact with multiple packages.  I ran into all sorts of issues with this as it seems to confuse the release pipeline and it's any persons' guess as to which application is deployed where...  
> **username_0**: @StePammenter Yes I did (finally).  Answer incoming.  
> **username_1**: Thanks for getting back. As it turned out for me, my fault was in copying the same Azure function settings, not with the pipeline itself!  

---

## 3 answers

### Answer by username_0 on 2019-11-20. Score: 12 | Accepted answer

Here is my YAML for multiple artifacts from a single build.
pool:
  name: Hosted Windows 2019 with VS2019
  demands:
  - msbuild
  - visualstudio
  - vstest
  - npm

steps:
- task: NuGetToolInstaller@0
  displayName: 'Use NuGet 4.4.1'
  inputs:
    versionSpec: 4.4.1

- task: NuGetCommand@2
  displayName: 'NuGet restore'
  inputs:
    restoreSolution: '$(Parameters.solution)'

- task: VSBuild@1
  displayName: 'Build solution WebApi'
  inputs:
    solution: '$(Parameters.solution)'
    msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactstagingdirectory)\\"'
    platform: '$(BuildPlatform)'
    configuration: '$(BuildConfiguration)'
    msbuildArchitecture: x64

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: WebApi'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
    ArtifactName: 'dotnet-webapi'
  condition: succeededOrFailed()

- task: DeleteFiles@1
  displayName: 'Delete build.artifactstagingdirectory for Angular'
  inputs:
    SourceFolder: '$(build.artifactstagingdirectory)'
    Contents: '**'

- task: Npm@1
  displayName: 'npm install'
  inputs:
    workingDir: project/ClientApp
    verbose: false

- task: Npm@1
  displayName: 'npm run prod-build'
  inputs:
    command: custom
    workingDir: project/ClientApp
    verbose: false
    customCommand: 'run prod-build'

- task: Npm@1
  displayName: 'npm run dev-build'
  inputs:
    command: custom
    workingDir: project/ClientApp
    verbose: false
    customCommand: 'run prod-dev'
  enabled: false

- task: CopyFiles@2
  displayName: 'Copy Angular/Dist to build.artifactstagingdirectory'
  inputs:
    SourceFolder: project/ClientApp/dist/ClientApp
    Contents: |
     **
     !config.json
    TargetFolder: '$(build.artifactstagingdirectory)'

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: Angular'
  inputs:
    ArtifactName: angular

> **Comments:**
> **username_4**: In a release pipeline, how would you specify which Build Artifact to use?  
> **username_0**: @username_4 Both artifacts are available when you select a folder/archive/package in the  release pipeline task.  So I just select the one I need for the correct release task.  

---

### Answer by username_3 on 2021-01-14. Score: 9

I managed to get Erik's approach working which is great.
I then wondered if I could simplify it so instead of deleting the content how about put each artifact in a sub folder of the $(Build.ArtifactStagingDirectory) So by just appending /Api or /App I could create specific publish folders that I could then push onto the azure pipeline.
You can then have as many artifacts as you need :)
The important parts to take from this are that publishWebProjects needs to be set to false or it defaults to true and then ignores the projects line below, and the output path puts the content in a sub folder.
 # This need to be false in order for the specific project to be published
 publishWebProjects: False
 projects: '**/DevOpsApp.csproj'
 arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/App'

and pathtoPublish need to then point to the sub folder
pathtoPublish: '$(Build.ArtifactStagingDirectory)/App'

Full example file below
# ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core

trigger:
- develop

pool:
  vmImage: 'ubuntu-latest'

variables:
    buildConfiguration: 'Release'
    versionNumber: 1.0.0

name: $(versionNumber)-wip-$(Rev:r)

#----------------------------------------------------------
# Web API Build and Artifact
#----------------------------------------------------------

steps:
- task: DotNetCoreCLI@2
  displayName: 'Build'
  inputs:
    command: 'build'
    projects: '**/DevOpsApi.csproj'
    arguments: '--configuration $(buildConfiguration)'

- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    projects: '**/*Tests.csproj'
    arguments: '--configuration $(buildConfiguration)'
    testRunTitle: 'Unit Tests'

# Publish the artifact
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    # This need to be false in order for the specific project to be published
    publishWebProjects: False
    projects: '**/DevOpsApi.csproj'
    arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/Api'
    zipAfterPublish: True

# Publish the artifact for the pipelines to use
- task: PublishBuildArtifacts@1
  displayName: 'Publishing WebAPI Artifact'
  inputs:
    pathtoPublish: '$(Build.ArtifactStagingDirectory)/Api' 
    artifactName: 'TestWebApi-Wip'

#----------------------------------------------------------
# Web APP Build and Artifact
#----------------------------------------------------------

- task: DotNetCoreCLI@2
  displayName: 'Build'
  inputs:
    command: 'build'
    projects: '**/DevOpsApp.csproj'
    arguments: '--configuration $(buildConfiguration)'

# Publish the artifact
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    # This need to be false in order for the specific project to be published
    publishWebProjects: False
    projects: '**/DevOpsApp.csproj'
    arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/App'
    zipAfterPublish: True

# Publish the artifact for the pipelines to use
- task: PublishBuildArtifacts@1
  displayName: 'Publishing WebAPP Artifact'
  inputs:
    pathtoPublish: '$(Build.ArtifactStagingDirectory)/App' 
    artifactName: 'TestWebApp-Wip'


---

### Answer by username_2 on 2021-12-18. Score: 6

Can I suggest building and publishing the artefacts in separate jobs? That would mean that each job is simpler (no need to specify an artefact subfolder), and might give you some speed-up by running them in parallel. Something like this:
jobs:
  - job: web_api
    displayName: Web API Build and Artifact
    steps:
      - checkout: self

      - task: DotNetCoreCLI@2
        displayName: 'Build'
        inputs:
          command: 'build'
          projects: '**/DevOpsApi.csproj'
          arguments: '--configuration $(buildConfiguration)'
      
      - task: DotNetCoreCLI@2
        inputs:
          command: 'test'
          projects: '**/*Tests.csproj'
          arguments: '--configuration $(buildConfiguration)'
          testRunTitle: 'Unit Tests'
      
      # Publish the artifact
      - task: DotNetCoreCLI@2
        inputs:
          command: 'publish'
          # This need to be false in order for the specific project to be published
          publishWebProjects: False
          projects: '**/DevOpsApi.csproj'
          arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
          zipAfterPublish: True
      
      # Publish the artifact for the pipelines to use
      - task: PublishBuildArtifacts@1
        displayName: 'Publishing WebAPI Artifact'
        inputs:
          pathtoPublish: '$(Build.ArtifactStagingDirectory)' 
          artifactName: 'TestWebApi-Wip'
  
  - job: web_app
    displayName: Web APP Build and Artifact
    dependsOn: []
    steps:
      - checkout: self

      - task: DotNetCoreCLI@2
        displayName: 'Build'
        inputs:
          command: 'build'
          projects: '**/DevOpsApp.csproj'
          arguments: '--configuration $(buildConfiguration)'
      
      # Publish the artifact
      - task: DotNetCoreCLI@2
        inputs:
          command: 'publish'
          # This need to be false in order for the specific project to be published
          publishWebProjects: False
          projects: '**/DevOpsApp.csproj'
          arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
          zipAfterPublish: True
      
      # Publish the artifact for the pipelines to use
      - task: PublishBuildArtifacts@1
        displayName: 'Publishing WebAPP Artifact'
        inputs:
          pathtoPublish: '$(Build.ArtifactStagingDirectory)' 
          artifactName: 'TestWebApp-Wip'

Also: if each job tends to have a similar set of tasks, you could refactor them into a template to keep the pipeline code terser.

> **Comments:**
> **username_3**: I know that name username_2, think I've worked with you in the past, :) Cheers  

---

