I have a .NET Core solution with two projects (proj1 and proj2). When I run a build in Azure DevOps, I use the DotNetCoreCLI#2 command like this:
- task: DotNetCoreCLI#2
displayName: 'Build output'
inputs:
command: 'build'
projects: '**/*.csproj'
arguments: '--output $(System.DefaultWorkingDirectory)/publish_output'
As is, all the artifacts from both builds end up in the publish_output directory. What I'd like is for there to be a proj1 and proj2 subdirectory created under publish_output and the artifacts from the projects placed appropriately.
Is this possible? I could not find a "currently being build project name" variable to append to the output directory.
Thank you Simply Ged. Posting your suggestions as answer to help other community members.
Add modifyOutputPath as a input as below and check
Here is the code
# Publish projects to specified folder.
- task: DotNetCoreCLI#2
displayName: 'dotnet publish'
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/*.csproj'
arguments: '-o $(Build.ArtifactStagingDirectory)/Output'
zipAfterPublish: true
modifyOutputPath: true
Follow the Publish Projects for further instructions.
Related
this is my pipeline:
pool:
vmImage: windows-latest
steps:
- task: NuGetToolInstaller#1
displayName: 'Install NuGet >=6.3.0-0'
inputs:
versionSpec: '>=6.3.0-0'
checkLatest: true
- task: UseDotNet#2
displayName: Use DotNet Version 7.0.x
inputs:
version: '7.0.x'
includePreviewVersions: true # Required for preview versions
- task: NuGetCommand#2
displayName: 'Nuget Restore Packages'
inputs:
command: 'restore'
restoreSolution: '**/*.sln'
feedsToUse: 'select'
vstsFeed: '11b33a23-a7bd-4e05-bce5-7383e054c4f4/3aef100d-2005-4893-9c82-65ed96a2b539'
- task: DotNetCoreCLI#2
displayName: 'Build Web API projects'
inputs:
command: build
projects: '**/*src/*.csproj'
arguments: '--configuration $(buildConfiguration)' # Update this to match your need
- task: DotNetCoreCLI#2
displayName: 'Build Database Migrator'
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/*tools/*DatabaseMigrator.csproj'
arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/App_Data/jobs/triggered -r win-x64 --self-contained false'
- task: DotNetCoreCLI#2
displayName: 'Build Frequently Operations'
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/*tools/*FrequentlyOperations.csproj'
arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/App_Data/jobs/continuous -r win-x64 --self-contained false'
- task: DotNetCoreCLI#2
displayName: 'Create Zip Build For Release'
inputs:
command: publish
publishWebProjects: True
arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
zipAfterPublish: true
# this code takes all the files in $(Build.ArtifactStagingDirectory) and uploads them as an artifact of your build.
- task: PublishPipelineArtifact#1
displayName: 'Publish Artifact(Zip File) For Release'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)'
artifactName: 'output'
when it is triggered it shows this error:
Starting: Build Web API projects
==============================================================================
Task : .NET Core
Description : Build, test, package, or publish a dotnet application, or run a custom dotnet command
Version : 2.210.0
Author : Microsoft Corporation
Help : https://docs.microsoft.com/azure/devops/pipelines/tasks/build/dotnet-core-cli
==============================================================================
C:\Windows\system32\chcp.com 65001
Active code page: 65001
Info: .NET Core SDK/runtime 2.2 and 3.0 are now End of Life(EOL) and have been removed from all hosted agents. If you're using these SDK/runtimes on hosted agents, kindly upgrade to newer versions which are not EOL, or else use UseDotNet task to install the required version.
Info: Azure Pipelines hosted agents have been updated and now contain .Net 5.x SDK/Runtime along with the older .Net Core version which are currently lts. Unless you have locked down a SDK version for your project(s), 5.x SDK might be picked up which might have breaking behavior as compared to previous versions. You can learn more about the breaking changes here: https://docs.microsoft.com/en-us/dotnet/core/tools/ and https://docs.microsoft.com/en-us/dotnet/core/compatibility/ . To learn about more such changes and troubleshoot, refer here: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/dotnet-core-cli?view=azure-devops#troubleshooting
##[error]Project file(s) matching the specified pattern were not found.
Finishing: Build Web API projects
this is my project:
Any suggestions ?
##[error]Project file(s) matching the specified pattern were not found.
Reproduce the same issue when the csproj file is not in the root node of the src folder.
For example:
-- src
--projectname
-- xxx.csproj
-- projectname1
Usually the src folder will contain multiple project folders.
To solve this issue, you need to check the src folder structure and define the folder path of the dotnet task.
For example:
- task: DotNetCoreCLI#2
displayName: 'Build Web API projects'
inputs:
command: build
projects: '**/*src/** or subfolder name/*.csproj'
arguments: '--configuration $(buildConfiguration)'
From the screenshot of your repo, I didn't see a csproj in your project.
You need to have a csproj in your project.
You could also use sln to restore and build your project.
steps:
- task: UseDotNet#2
displayName: 'Install .NET Core SDK'
inputs:
version: 5.0.x
performMultiLevelLookup: true
includePreviewVersions: true # Required for preview versions
- task: DotNetCoreCLI#2
inputs:
command: 'restore'
projects: '**/*.sln'
displayName: 'Restore Nuget Packages'
- task: DotNetCoreCLI#2
inputs:
command: 'build'
projects: '**/*.sln'
arguments: '--no-restore'
displayName: 'Build projects'
- task: DotNetCoreCLI#2
inputs:
command: 'publish'
publishWebProjects: true
arguments: '--configuration $(buildConfiguration) --output $(build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'
ArtifactName: 'api.chibebinam'
I have a .net core project with pipeline (YAML, multi-stage) pipeline set up in Azure DevOps. We have a bunch of unit tests that we execute at pipeline run time - everything is fine.
However - we would like to dig more deeper into our code coverage. So we have configured our task like this
- task: DotNetCoreCLI#2
displayName: Run UnitTests
enabled: true
inputs:
command: test
projects: '**/PM.UnitTests.csproj'
arguments: '--configuration $(buildConfiguration) --collect "Code coverage"'
The result is this
We can now see this in pipeline results:
This .coverage file can be downloaded and analyzed in e.g. Visual Studio.
However - we would really like to be able to see the results directly in Azure Pipelines. We have a Typescript project where we do this. The result is this:
Sadly, it is not at all apparent to me how to apply this to a .net core project.
Q1: Is it possible to have the same experience for .net core projects ... and how?
Additionally - we would like to be able to apply filtering on which parts of the code is used to calculate the code coverage percentage.
Q2: Is it correctly understood that this is done using a .runsettings file?
Thank you :-)
/Jesper
For reference, this is my complete YAML pipeline in my test .net core solution. The solution is super simple - a .net core class library and a .net core test class library
pool:
vmImage: vs2017-win2016
steps:
- task: DotNetCoreCLI#2
inputs:
command: 'restore'
feedsToUse: 'select'
vstsFeed: 'd12c137f-dac4-4ea7-bc39-59bd2b784537'
- task: DotNetCoreCLI#2
displayName: Build
inputs:
projects: '**/*.csproj'
arguments: --configuration $(BuildConfiguration) --no-restore
- task: DotNetCoreCLI#2
displayName: Run UnitTests
inputs:
command: test
projects: '**/Test.Coverage/Test.Coverage.csproj'
arguments: '--configuration $(BuildConfiguration) --collect:"XPlat Code Coverage" '
- script: 'dotnet tool install -g dotnet-reportgenerator-globaltool '
displayName: 'Install dotnet-reportgenerator-globaltool'
- script: 'reportgenerator -reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml -targetdir:$(build.sourcesdirectory) -reporttypes:"Cobertura"'
displayName: 'Executes reportgenerator'
- task: PublishCodeCoverageResults#1
displayName: 'Publish code coverage from $(build.sourcesdirectory)/Cobertura.xml'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(build.sourcesdirectory)/Cobertura.xml'
You could use the dotnet-reportgenerator-globaltool package to generate the HTML Code Coverage Report.
Here is an example:
- task: DotNetCoreCLI#2
displayName: Test
inputs:
command: test
projects: '$(Parameters.TestProjects)'
arguments: '--configuration $(BuildConfiguration) --collect:"XPlat Code Coverage" '
- script: 'dotnet tool install -g dotnet-reportgenerator-globaltool '
displayName: 'Command Line Script'
- script: 'reportgenerator -reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml -targetdir:$(build.sourcesdirectory) -reporttypes:"Cobertura"'
displayName: 'Command Line Script'
- task: PublishCodeCoverageResults#1
displayName: 'Publish code coverage from $(build.sourcesdirectory)/Cobertura.xml'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(build.sourcesdirectory)/Cobertura.xml'
Result:
What you're looking for is a tool that can generate a report based on the coverage information. You're looking for a ReportGenerator.
ReportGenerator converts coverage reports generated by coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov into human readable reports in various formats.
There are quite a few examples out there working with the dotnet-reportgenerator-globaltool for .NET Core projects.
You might find this Learn -> Usage page helpful.
Coverlet might also be an interesting addition to your toolbelt.
My code for the azure pipeline
I have Problems using the azure pipeline, which will automatically pack my libraries on azure devops git and push it as a nugetpackage to artifacts.
I get the error ##[error]No packages matched the search pattern.
at dotnet push
Until that step everything works. I want to pack it as a nuget so i can use it in other projects.
Its a API Client i wrote for my own API.
Try using the artifact path from artifact staging directory
- task: DotNetCoreCLI#2
displayName: 'dotnet build'
inputs:
command: 'build'
arguments: '--configuration $(buildConfiguration)'
projects: '**/*.csproj'
- task: DotNetCoreCLI#2
displayName: "dotnet pack"
inputs:
command: 'pack'
arguments: '--configuration $(buildConfiguration)'
packagesToPack: '**/*.csproj'
nobuild: true
versioningScheme: 'off'
- task: NuGetCommand#2
displayName: 'nuget push'
inputs:
command: 'push'
feedsToUse: 'select'
packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
nuGetFeedType: 'internal'
publishVstsFeed: '<Name of Your Feed>'
versioningScheme: 'off'
allowPackageConflicts: true
https://medium.com/#gstvribs/how-to-use-and-deploy-azure-devops-artifacts-on-azure-pipelines-with-dotnet-dockerized-8cebd724f752
Please add to dotnet pack for instance setting like this to your inputs:
packDirectory: "$(Build.ArtifactStagingDirectory)/packages"
And then to dotnet push setting like this:
packagesToPush: '$(Build.ArtifactStagingDirectory)/packages/*.*nupkg'
In your approach it simply try to find packages in defualt folder but you didn't put packages there.
Consider the following project structure:
MyProject.Api.a
MyProject.Api.b
MyProject.Data, referenced by a and b
I've set up a pipeline in Azure devOps that performs a restore, build and publish like this:
jobs:
- job: api-a
steps:
- task: DotNetCoreCLI#2
displayName: Restore
inputs:
command: restore
projects: "MyProject.Api.a.csproj"
- task: DotNetCoreCLI#2
displayName: Build
inputs:
command: build
projects: "MyProject.Api.a.csproj"
arguments: "--configuration $(buildConfiguration)"
- task: DotNetCoreCLI#2
displayName: Publish
inputs:
command: publish
projects: "MyProject.Api.a.csproj"
publishWebProjects: false
arguments: "--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/project-api-a-publish"
- task: PublishPipelineArtifact#1
displayName: Publish release Artifact
inputs:
targetPath: "$(Build.ArtifactStagingDirectory)/project-api-a-publish"
artifactName: "a-publish"
- job: api-b
steps:
- task: DotNetCoreCLI#2
displayName: Restore
inputs:
command: restore
projects: "MyProject.Api.b.csproj"
- task: DotNetCoreCLI#2
displayName: Build
inputs:
command: build
projects: "MyProject.Api.b.csproj"
arguments: "--configuration $(buildConfiguration)"
- task: DotNetCoreCLI#2
displayName: Publish
inputs:
command: publish
projects: "MyProject.Api.b.csproj"
publishWebProjects: false
arguments: "--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)/project-api-b-publish"
- task: PublishPipelineArtifact#1
displayName: Publish release Artifact
inputs:
targetPath: "$(Build.ArtifactStagingDirectory)/project-api-b-publish"
artifactName: "b-publish"
problem is that MyProject.Data is not buildable from source, it needs an external tool to run first that generates some C# classes. Before this step, the project won't be able to build.
So I added this:
- task: DotNetCoreCLI#2
displayName: "Restore tools"
inputs:
workingDirectory: "MyProject.Data"
command: custom
custom: tool
arguments: restore --interactive --configfile ../NuGet.config
- task: DotNetCoreCLI#2
displayName: my-codegen-tool
inputs:
workingDirectory: "MyProject.Data"
command: custom
custom: tool
arguments: run my-codegen-tool
This all works, but the codegen tool needs to run on each API project job I'm running, making my build quite slow.
I was hoping there would be some way to only run the codegen tool once, and then all API projects could use the binaries from the data project where the files were generated?
Ideally, I would have to be able to prebuild the data project in a separate job, publish the dll's as an artifact, and then use those dll's in my subsequent API builds. I'm guessing this would be possible with dotnet build --no-dependencies, but that would implicate I need to build everything else separately as well, which is undesirable from a maintainability point of view.
You can try to combine multiple jobs into one job. First generate the required C # classes through the first two tasks, and then build with wildcards (e.g. **/*.csproj for all .csproj files in all subfolders) in the dotnet build task.
You can consider removing restore tasks, because dotnet restore is run implicitly in dotnet build.
This is stated here : You don't have to run dotnet restore because it's run implicitly by all commands that require a restore to occur, such as dotnet new, dotnet build, dotnet run, dotnet test, dotnet publish, and dotnet pack. To disable implicit restore, use the --no-restore option.
- job:
steps:
- task: DotNetCoreCLI#2
displayName: "Restore tools"
inputs:
workingDirectory: "MyProject.Data"
command: custom
custom: tool
arguments: restore --interactive --configfile ../NuGet.config
- task: DotNetCoreCLI#2
displayName: my-codegen-tool
inputs:
workingDirectory: "MyProject.Data"
command: custom
custom: tool
arguments: run my-codegen-tool
- task: DotNetCoreCLI#2
displayName: Build
inputs:
command: build
projects: "**/*.csproj"
arguments: "--configuration $(buildConfiguration)"
Is it possible to specify the target framework for a ClassLibrary project using Azure Devops Build Pipelines and the DotNetCoreCLI#2 task? Or do we have to revert to using a script and manually calling the dotnet publish command?
A snippet from my pipeline YAML
variables:
buildConfiguration: 'Debug'
steps:
- task: DotNetCoreCLI#2
inputs:
command: 'publish'
publishWebProjects: false # Required when command == Publish
projects: 'TestProject/Test/Test.csproj'
configuration: '$(BuildConfiguration)'
And from my .csproj:
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;net45</TargetFrameworks>
</PropertyGroup>
I'm using the documentation here for the DotNetCoreCLI#2 task but it's not always great.
EDIT: I should add that at the moment the Build completely fails because:
The 'Publish' target is not supported without specifying a target framework.
The current project targets multiple frameworks, please specify the framework
for the published application.
The DotNetCoreCLI#2 task could be extended with the arguments property, on which you could specify the framework (as well as the build configuration):
steps:
- task: DotNetCoreCLI#2
inputs:
command: 'publish'
publishWebProjects: false # Required when command == Publish
projects: 'TestProject/Test/Test.csproj'
arguments: '--configuration $(BuildConfiguration) --framework netcoreapp2.1'