Publishing VS Code extension via Azure DevOps - visual-studio-code

After reading VSCode Publish Extension docs, I've succeeded to publish a VSCode extension manually with vsce.
I'm wondering if there is a way to publish extensions automatically via Azure DevOps pipelines (build or release) instead of doing it manually.
I've tried to use vsce there but I'm getting an authentication error
Resource not available for anonymous access. Client authentication required.
Using vsce publish -p <access_token> is not possible because the pipeline is public and everyone can see the access token...
So, is there a way to publish a Visual Studio Code extension automatically via Azure DevOps Pipeline or even Travis CI?

You can add the Personal Access Token as a secret variable, then nobody can couldn't see it.
Go to Azure DevOps to your pipeline and click on "Edit", not in the top left click on "Variables":
Now click on the + icon and add the variable, mark the checkbox "Keep this value secret":
Now you can use it in this way: $(PAT), for example:
vsce publish -p $(PAT)
The variable value will not appear in the YAML :)

Is there a way to publish a Visual Studio Code extension automatically
via Azure DevOps Pipeline?
Of course yes!
To have a good experience for CI/CD in Azure Devops, I recommend you store the source code in Azure Devops or Github.
Build \ CI
In build, most of work is update the version which in manifest of VSIX, build\create package. For the version increased, here I use the counter expression feature which supported in VSTS to achieve that:
counter('name', seed)
Use this expression in variable declaration bloc. For detailed and completed build process, refer to my sample YAML code:
trigger:
- '*'
pool:
vmImage: 'windows-2019'
variables:
VersionPatch: $[counter('versioncount', 24)]
solution: '**/*.sln'
BuildPlatform: 'Any CPU'
BuildConfiguration: 'Release'
name: 2.0.$(VersionPatch)
steps:
- task: UseDotNet#2
inputs:
packageType: 'sdk'
version: '3.0.100'
includePreviewVersions: true
- task: NuGetToolInstaller#1
inputs:
versionSpec: 5.1.0
- task: PowerShell#2
displayName: Update version
inputs:
filePath: 'Build\VersionUpdate.ps1'
arguments: '$(Build.BuildNumber)'
pwsh: true
- task: NuGetCommand#2
inputs:
command: 'restore'
- task: DotNetCoreCLI#2
displayName:
inputs:
command: 'restore'
projects: 'tests/**/*.csproj'
vstsFeed: '{My feed ID}'
includeNuGetOrg: false
- task: VSBuild#1
inputs:
solution: '**\*.sln'
maximumCpuCount: true
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
- task: VSTest#2
inputs:
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
- task: CopyFiles#2
inputs:
SourceFolder: '$(Build.SourcesDirectory)'
Contents: |
Build/**
**/*.vsix
**/*.nupkg
README.md
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishPipelineArtifact#0
inputs:
artifactName: 'ExtensionDrop'
targetPath: '$(Build.ArtifactStagingDirectory)'
In UpdateVersion.ps1 file:
$VerbosePreference="Continue"
$version = $args[0]
if (!$version) {
$version = "0.0.0"
}
Write-Host "This Version is: $version"
$FullPath = Resolve-Path $PSScriptRoot\..\src\Merlin.Compiler.Vsix\source.vsixmanifest
Write-Host $FullPath
[xml]$content = Get-Content $FullPath
$content.PackageManifest.Metadata.Identity.Version = $version
$content.Save($FullPath)
Release\ CD
After build succeed, set the release pipeline for this repos. In release, use powershell script and VsixPublisher.exe to publish the vsix file.
$PAToken = $args[0]
$VsixPath = "$PSScriptRoot\..\src\Merlin.Compiler.Vsix\bin\Release\Merlin.Compiler.Vsix"
$ManifestPath = "$PSScriptRoot\ExtensionManifest.json"
$Installation = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -format json | ConvertFrom-Json
$Path = $Installation.installationPath
$VsixPublisher = Join-Path -Path $Path -ChildPath "VSSDK\VisualStudioIntegration\Tools\Bin\VsixPublisher.exe" -Resolve
& $VsixPublisher publish -payload $VsixPath -publishManifest $ManifestPath -personalAccessToken $PAToken -ignoreWarnings "VSIXValidatorWarning01,VSIXValidatorWarning02,VSIXValidatorWarning08"
In CD, use VsixPublisher.exe which exist in VS to publish the vsix file.
You can set the PAToken in Variable tab, then set it as secret. Thus it would not be public for others. Here PAT token is a necessary one which could not be replaced by others. And also, when generate the token, need choose All accessible organizations. Or it will cause the permission error.

Further #Shayki's answer there are some more steps because you can't just run vsce publish -p $(PAT).
The vsce should be installed (can be in devDependencies)
Add a "deploy" (or name it as you like) script to the package.json scripts.
"deploy": "vsce publish -p"
Add a "publish" step in the azure-pipeline.yml file. the condition is for running the publish script only on master so Pull Requests will not publish. Also run it only in Linux's build, in case you configured multiple platforms. If you configured only one (for example, windows) replace Linux with that platform
- bash: |
echo ">>> Publish"
yarn deploy $(token)
displayName: Publish
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['Agent.OS'], 'Linux'))
Example azure-pipeline.yml

Related

How to .pfx sign code using local machine in Azure Devops Pipelines?

We have developed for the client Microsoft Office extension, and they do require to be code signed.
For development I have made a .pfx in VS -> Project properties -> Signing -> Create Test Certificate. Put empty password, dumped .pfx into source control and it was building for the whole company while developing.
For the release of the addon, things are different, we need to sign an extension with the clients .pfx and they want to add a step in the Azure DevOps build a pipeline to do it automatically. The thing is they can't use cloud solutions, so as I understand Azure Key Vault is out of the picture. They do have a local trusted machine that we could put their .pfx for signing.
I couldn't find a way how to do a signing in Azure Pipelines, that would not involve Azure Key Vault, or Azure Secure Files but I would expect there to be a mechanism for this as it seems like a quite common thing to do.
What is the preferred solution to .pfx sign code using local machine in Azure Devops Pipelines?
We ended up with following:
Added .pfx on local build machine.
Added hidden variable to Azure build pipeline pfxPassword
Then added following build steps tp Azure build pipeline:
trigger:
- main
pool:
name: 'XXX Build Pool'
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
#change to actual directory where signtool is.
pathToSignTool: "\"C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x64\\signtool.exe\""
pathToPfx: "C:\\XXX\\Install\\XXX_Applications.pfx"
pathToBuildDirectory: "\\XXXYYY\\bin\\Release\\"
pathToMageTool: "\"C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v10.0A\\bin\\NETFX 4.8 Tools\\mage.exe\""
pathToContinousDeployment: "C:\\ContinousDeployment\\YYY\\"
name: $(MajorVersion).$(MinorVersion).$(date:yy)$(DayOfYear)$(rev:.r)
steps:
- task: Assembly-Info-NetFramework#2
inputs:
Path: '$(Build.SourcesDirectory)'
FileNames: |
**\AssemblyInfo.cs
InsertAttributes: true
FileEncoding: 'auto'
WriteBOM: false
VersionNumber: '$(Build.BuildNumber)'
FileVersionNumber: '$(Build.BuildNumber)'
InformationalVersion: '$(Build.BuildNumber)'
LogLevel: 'verbose'
FailOnWarning: false
DisableTelemetry: false
- task: VSBuild#1
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: VSTest#2
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- script:
$(pathToMageTool) -s $(Build.Repository.LocalPath)$(pathToBuildDirectory)XXXYYY.vsto -cf $(pathToPfx) -pwd %MAPPEDPASS%
env:
MAPPEDPASS: $(pfxPassword)
- script:
$(pathToMageTool) -s $(Build.Repository.LocalPath)$(pathToBuildDirectory)XXXYYY.dll.manifest -cf $(pathToPfx) -pwd %MAPPEDPASS%
env:
MAPPEDPASS: $(pfxPassword)
- script:
$(pathToSignTool) sign /f $(pathToPfx) /p %MAPPEDPASS% $(Build.Repository.LocalPath)$(pathToBuildDirectory)XXXYYY.dll
env:
MAPPEDPASS: $(pfxPassword)
- task: CopyFiles#2
inputs:
SourceFolder: '$(Build.Repository.LocalPath)$(pathToBuildDirectory)'
Contents: '**'
TargetFolder: '$(pathToContinousDeployment)'
OverWrite: true

How to deploy multiple apps (monorepo) with Azure and NX

I'm using NX tools to manage a monorepo with multiple apps and I'm struggling to understand how to deploy using Azure and release pipelines.
Disclaimer : I'm very new to Azure and devops in general.
My understanding is this :
I create a pipeline (not a release pipeline, just a "regular one" if that make any sense) and plug a yml to it. Also, the pipeline is linked to a repo on Azure Repos, which means that every time I push to this repo, it will trigger the pipeline and run the yaml commands.
On this commands, I run lint, test and builds.
This is what I can do and can understand, the following become more obscure :
The build job is supposed to create an artifact if I'm pusing/merging on master which I can conditioned.
Now I can create a release pipeline which will be trigger when to repo it is linked to will create an artifact. This release pipeline can then send this artifact to an app service which is a slot where an app will live.
Okay, but I'm using a monorepo, which means the build will produce multiple applications and each one of these apps should be deploy to the correct app service.
After some research, I found that the general idea is to create one release pipeline for each app. These release pipelines are all linked to the same monorepo, but they have a filter which is a build tag. The build tag is added while building the apps using the yml file.
So these are basically my understanding of all of this. Now here are the questions :
What exactly is a build tag and where does it live? Is it somehow linked to an artifact?
The idea is to create one build tag per artifact, right?
I failed to create a build tag, how can I do so?
What is the correct way to zip and publish the artifacts?
Here is the yaml I'm using :
jobs:
- job: Lint
steps:
- task: NodeTool#0
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: Npm#1
displayName: 'Npm install'
- pwsh: 'npm run nx affected -- --target=lint --parallel --base=origin/master --maxParallel=4'
displayName: 'Running lint'
- job: Test
steps:
- task: NodeTool#0
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: Npm#1
displayName: 'npm install'
- pwsh: 'npm run nx affected -- --target=test --parallel --code-coverage --base=origin/master --maxParallel=4'
displayName: 'Running tests'
- job: Build
steps:
- task: NodeTool#0
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: Npm#1
displayName: 'npm install'
- pwsh: 'npm run nx affected -- --target=build --parallel --base=origin/master --prod'
displayName: 'Running build'
- pwsh: |
npm run nx affected:apps -- --base=HEAD~1 --head=HEAD | grep -E '( - )(\w|-|\d|_)+' | sed -E 's/ - /##vso[build.addbuildtag]/g'
displayName: 'Adding build tags'
When running this, test, lint and builds are working, but I don't think it adds a build tag, here is the log :
It appears like nothing happens... How can I correctly add the tag and make the release pipeline to be triggered?
I've also found this snippet to zip and publish the artifact, but I don't know if I can use that since in a monorepo we should - I think - create multiple artifacts.
5) So the last question is : how can I create multiple artifacts and is it even the good thing to do?
Many many thanks in advance for the help, I know this is a long boring post and helping a noob can be boring but I'm stuck with this for way to long...
1, You can add tags for a build from the UI page(Build summary page, see below) or using Rest api. It can be used to filter between builds. If your build pipeline generated multiple artifacts, build tags will not be able to filter the artifacts which generated in one build.
2, So you can think about how to separate the build artifacts for each app in your pipeline.
You can use Archive files task to zip your build artifacts and publish using publish build artifacts task.
See below yaml example: I used two archive files task to package the build artifacts for app1 and app2 separately. And save the zipped artifacts in folder $(Build.ArtifactStagingDirectory).
Then the publish build artifacts task will publish the artifacts to azure devops cloud. (Release pipeline will download the artifacts to deploy to your app server)
- task: ArchiveFiles#2
inputs:
rootFolderOrFile: $(system.defaultworkingdirectory)/app1/dist
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/app1/dist1.zip'
includeRootFolder: false
enabled: true
- task: ArchiveFiles#2
inputs:
rootFolderOrFile: $(system.defaultworkingdirectory)/app2/dist
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/app2/dist2.zip'
includeRootFolder: false
enabled: true
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/
artifactName: build
3, Then you can use multiple stages in your release pipeline and use Azure App Service Deploy task. For below example:
In stage one add Azure App Service Deploy task and set the package to $(System.DefaultWorkingDirectory)/**/app1/dist1.zip to deploy app1. And in stage two set it to $(System.DefaultWorkingDirectory)/**/app2/dist2.zip to deploy app2.
Another workaround to deploy multiple apps in monorepo is to create multiple build/release pipeline, one for each app. And in the build pipeline using path filter to let the build pipeline only be triggered when it corresponding app is updated.
trigger:
paths:
include:
- root/app1/*
Hope above helps!
#levi Lu-MSFT answered helped me a ton and is basically how we are doing it, but they didn't really give full yaml code.
The way we have the release pipeline set up is one release pipeline per application, looking at the build tags for the release trigger. We are currently bundling all apps together inside one artifact, so the downside is when an app's main branch is triggered, the release process will download all the apps.
The way I added my build tags dynamically started with this nx command:
npx nx affected:apps --base=origin/main --plain
which prints out a list of apps that have changed. From there, I loop through the apps and create the build tags dynamically.
Here I have two jobs, one that runs on PR's and one that runs on main branch.
trigger:
branches:
include:
- main
pool:
name: My-Pool
demands: Agent.OS -equals Windows_NT
jobs:
- job: NX_AFFECTED_PR
pool:
name: WBOmega-Pool
demands: Agent.OS -equals Windows_NT
condition: eq(variables['Build.Reason'], 'PullRequest')
steps:
- task: Npm#1
displayName: 'npm install'
inputs:
command: 'install'
verbose: true
- powershell: |
npx nx affected:apps --base=origin/main --plain | Tee-Object -Variable output
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
foreach ($appName in ($output -replace '\s+', ' ').Split()) {
Write-Host "this is the app-name: $appName"
if($appName.Trim() -eq ""){
Write-Host "App name is blank"
} else {
$url="https://dev.azure.com/YOUR_ORG/$(System.TeamProject)/_apis/build/builds/$(build.buildid)/tags/" + $appName + "?api-version=6.0"
Write-Host $url
$result = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Bearer $(System.AccessToken)"} -Method Put
}
}
name: set_build_tags
- powershell: |
npx nx affected --target=build --base=origin/main --parallel --max-parallel=3
name: build
- powershell: |
npx nx affected --target=lint --base=origin/main --parallel --max-parallel=3
name: lint
- powershell: |
npx nx affected --target=test --base=origin/main --parallel --max-parallel=3
name: test
- job: NX_AFFECTED_MAIN
pool:
name: My-Pool
demands: Agent.OS -equals Windows_NT
condition: ne(variables['Build.Reason'], 'PullRequest')
steps:
- checkout: self
persistCredentials: true
- powershell: |
npx nx affected:apps --base=HEAD~1 --plain | Tee-Object -Variable output
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
foreach ($appName in ($output -replace '\s+', ' ').Split()) {
Write-Host "this is the app-name: $appName"
if($appName.Trim() -eq ""){
Write-Host "App name is blank"
} else {
$url="https://dev.azure.com/YOUR_ORG/$(System.TeamProject)/_apis/build/builds/$(build.buildid)/tags/" + $appName + "?api-version=6.0"
Write-Host $url
$result = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Bearer $(System.AccessToken)"} -Method Put
}
}
name: set_build_tags
- powershell: |
npx nx affected --target=build --base=HEAD~1 --parallel --max-parallel=3
name: build
- powershell: |
npx nx affected --target=lint --base=HEAD~1 --parallel --max-parallel=3
name: lint
- powershell: |
npx nx affected --target=test --base=HEAD~1 --parallel --max-parallel=3
name: test
- task: CopyFiles#2
displayName: 'Copy Files to: $(build.artifactstagingdirectory)\apps\'
inputs:
SourceFolder: '$(Build.SourcesDirectory)\dist\apps\'
TargetFolder: '$(build.artifactstagingdirectory)\apps\'
CleanTargetFolder: true
OverWrite: true
- task: PublishBuildArtifacts#1
displayName: 'Publish Artifact'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)\apps'
ArtifactName: 'Apps'

I have a build pipeline in Azure DevOps for my github repo - where are the binaries?

Here is the (unedited from template) YAML definition of the pipeline:
# .NET Desktop
# Build and run tests for .NET Desktop or Windows classic desktop solutions.
# Add steps that publish symbols, save build artifacts, and more:
# https://learn.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
trigger:
- master
pool:
vmImage: 'windows-latest'
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
steps:
- task: NuGetToolInstaller#1
- task: NuGetCommand#2
inputs:
restoreSolution: '$(solution)'
- task: VSBuild#1
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: VSTest#2
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
This pipeline triggers when code is pushed to the master branch of my repo as intended - however I can't find the binaries that it built! How do I access them so I can share them with folks? Are the binaries unavailable because some of my unit tests failed, causing the build to fail, or something?
You need to publish those somewhere. It's up to you to choose what to keep at what stage of the pipeline. You can copy files into a directory, or just grab the whole $(Build.SourcesDirectory). You can also instruct the VsBuild task to redirect output to a specific directory by passing in the /p:OutputPath=$(Build.ArtifactStagingDirectory) commandline argument.
You then have a few options:
GitHub Release task - Creates a release in GitHub and associates the files you want to it.
# GitHub Release
# Create, edit, or delete a GitHub release
- task: GitHubRelease#0
inputs:
gitHubConnection:
#repositoryName: '$(Build.Repository.Name)'
#action: 'create' # Options: create, edit, delete
#target: '$(Build.SourceVersion)' # Required when action == Create || Action == Edit
#tagSource: 'auto' # Required when action == Create# Options: auto, manual
#tagPattern: # Optional
#tag: # Required when action == Edit || Action == Delete || TagSource == Manual
#title: # Optional
#releaseNotesSource: 'file' # Optional. Options: file, input
#releaseNotesFile: # Optional
#releaseNotes: # Optional
#assets: '$(Build.ArtifactStagingDirectory)/*' # Optional
#assetUploadMode: 'delete' # Optional. Options: delete, replace
#isDraft: false # Optional
#isPreRelease: false # Optional
#addChangeLog: true # Optional
#compareWith: 'lastFullRelease' # Required when addChangeLog == True. Options: lastFullRelease, lastRelease, lastReleaseByTag
#releaseTag: # Required when compareWith == LastReleaseByTag
Publish Pipeline Artifact (Azure DevOps) - Links the selected files to the build as an artifact. You can download them from the pipeline's summary page in Azure DevOps. Works well in both Build and Release pipelines.
# Publish pipeline artifact
# Publish (upload) a file or directory as a named artifact for the current run
- task: PublishPipelineArtifact#1
inputs:
targetPath: '$(Pipeline.Workspace)'
artifact: 'Output'
Publish Build Artifact (Azure DevOps and TFS) - Similar to Publish Pipeline Artifact, but less efficient in its transfers and specific to build pipelines. Can also publish to a file share instead of an attachment to the pipeline summary.
# Publish build artifacts
# Publish build artifacts to Azure Pipelines or a Windows file share
- task: PublishBuildArtifacts#1
inputs:
#pathtoPublish: '$(Build.ArtifactStagingDirectory)'
#artifactName: 'drop'
#publishLocation: 'Container' # Options: container, filePath
#targetPath: # Required when publishLocation == FilePath
#parallel: false # Optional
#parallelCount: # Optional
You are missing the task of "copy and publish artifact" task. This task will copy the resulting compiled binaries as artifact to be downloaded later.
For more information about this copy and publish artifact, visit the official documentation: https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/copy-and-publish-build-artifacts?view=azure-devops
UPDATE: the copy and publish artifact task is deprecated in Azure DevOps, please use the newest one: https://learn.microsoft.com/en-us/azure/devops/pipelines/artifacts/build-artifacts?view=azure-devops&tabs=yaml
Use this in your YAML: PublishBuildArtifacts#1

ReportGenerator missing Code Coverage tab (Azure DevOps Server 2019.0.1)

I follow the steps of Computing code coverage for a .NET Core project with Azure DevOps and Coverlet.
Build run like expected and every step ends successfully.
The Artefact-Explorer shown the uploaded report and In summary I get the Code Coverage result.
But I missing the Code Coverage tab next to Tests tab to take a look to the detailed report.
Configuration YAML:
- task: NuGetToolInstaller#0
displayName: 'Use NuGet 5.0.2'
inputs:
versionSpec: 5.0.2
checkLatest: true
- task: NuGetCommand#2
displayName: 'NuGet restore'
inputs:
restoreSolution: '$(Parameters.solution)'
- task: VSBuild#1
displayName: 'Projektmappe **\*.sln erstellen'
inputs:
solution: '$(Parameters.solution)'
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
- task: VisualStudioTestPlatformInstaller#1
displayName: 'Installer für Visual Studio Test-Plattform'
enabled: false
- task: VSTest#2
displayName: 'VsTest - testAssemblies'
inputs:
testAssemblyVer2: |
**\$(BuildConfiguration)\*test*.dll
!**\obj\**
codeCoverageEnabled: true
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
- powershell: ./'D:\AzureDevOpsData\Skripte\PowerShell\CodeCoverage.ps1'
displayName: 'PowerShell Test Code Coverage'
- task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator#4
displayName: ReportGenerator
inputs:
reports: coverage.cobertura.xml
targetdir: '$(Build.SourcesDirectory)/CodeCoverage'
- task: PublishCodeCoverageResults#1
displayName: 'Code Coverage veröffentlichen von $(Build.SourcesDirectory)/CodeCoverage/Cobertura.xml'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(Build.SourcesDirectory)/CodeCoverage/Cobertura.xml'
reportDirectory: '$(Build.SourcesDirectory)/CodeCoverage'
The PowerShell Script contains:
#TEST CSPROJ
$csproj = "FrameworkA_Tests"
#SEARCH TEST CSPROJ.DLL
"`nrun tests:"
$unitTestFile = gci -Recurse | ?{ $_.FullName -like "*bin\*$csproj.dll" }
Write-Host "`$unitTestFile value: $unitTestFile"
#GET COVERLET.EXE
$coverlet = "D:\AzureDevOpsData\Tools\coverlet\coverlet.exe"
#RUN COVERLET.EXE
"calling $coverlet for $($unitTestFile.FullName)"
&$coverlet $unitTestFile.FullName --target "dotnet" --targetargs "vstest $($unitTestFile.FullName) --logger:trx" --format "cobertura"
Do I forget something?
Please try to enable "Boards" in the project settings:
This issue was fixed for Azure DevOps but may still exist in Azure DevOps Server.
See:
https://developercommunity.visualstudio.com/content/problem/385331/code-coverage-results-not-rendered-in-build-result.html
https://developercommunity.visualstudio.com/content/problem/398209/build-results-tab-code-coverage-does-not-show-up.html
ReportGenerator missing Code Coverage tab (Azure DevOps Server 2019.0.1)
This should be a known issue on the Developer Community:
Code coverage tab missing in Azure DevOps Server
MS team reply: A fix for this issue has been internally implemented and is being prepared for release.
As workaround, you can try the method provided by jingzhu yan:
you can add copy files and publish build results steps , then you can
download coverage result file from Artifacts.
Hope this helps.

How to capture and retain the artifact package version for Universal artifacts in azure pipelines for cd

I have this azure devops ci/cd pipeline using yaml. My yaml has two stages CI and CD. My CI stage has one job called BuildandDeploy. The CD stage has one deployment job. I am using universal artifacts to publish and downloading the same. In the CD phase I am using UniversalPackages devops task to download the artifact. The task has a input variable called vstsPackageVersion which is the package version that is shown in universal artifacts. I have known of two other variables that could be used $(Build.BuildId) and $(Build.BuildNumber). As a temporary work around I am hard coding the package version for the universal artifact.
I wasn't able to download the artifact with either of the built-in variables. Since the CI and CD are in the same pipeline, is there any way to store and retrieve the package version of the artifact? Is there a identifier like latest that I could use to get the latest artifact from universal package.
# specific branch build with batching
trigger:
batch: true
branches:
include:
- master
stages:
- stage: CI
jobs:
- job: BuildAndPublish
pool:
vmImage: 'Ubuntu-16.04'
steps:
-
script: |
docker build -t $(dockerId).azurecr.io/$(imageName):$(version) .
docker login -u $(dockerId) -p $(pswd) $(dockerId).azurecr.io
docker push $(dockerId).azurecr.io/$(imageName):$(version)
- task: Bash#3
displayName: Initialize Helm Client - create local repo
inputs:
targetType: 'inline'
script: '
helm init --client-only
'
- task: HelmDeploy#0
displayName: Package helm chart
inputs:
connectionType: 'Kubernetes Service Connection'
command: 'package'
chartPath: 'my-helm-dir'
- task: UniversalPackages#0
displayName: Publish helm package to my-company-artifacts
inputs:
command: 'publish'
publishDirectory: '$(Build.ArtifactStagingDirectory)'
feedsToUsePublish: 'internal'
vstsFeedPublish: '$(my-feed-guid)'
vstsFeedPackagePublish: 'my-artifact-name'
versionOption: patch
packagePublishDescription: 'My helm package descrition'
- stage: CD
jobs:
- deployment: DeployJob
displayName: Deploy Job
pool:
vmImage: Ubuntu-16.04
environment: dev
strategy:
runOnce:
deploy:
steps:
- task: UniversalPackages#0
displayName: 'Universal download'
inputs:
command: download
vstsFeed: '$(my-feed-name)'
vstsFeedPackage: 'my-artifact-name'
vstsPackageVersion: 0.0.32
- task: ExtractFiles#1
displayName: 'Extract files '
inputs:
archiveFilePatterns: '*.tgz'
destinationFolder: 'my-folder'
cleanDestinationFolder: true
The Universal Packages task based on az artifacts universal cli that not support "latest version", but only specific version (by the way, this cli is on preview).
As workaround, you can use the Rest API to retrieve the latest version and set a new variable, then, in the download task use this variable.
For example, add a PowerShell task that get the version number and set the variable:
- powershell: |
$head = #{ Authorization = "Bearer $env:TOKEN" }
$url = "https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feed-name}/packages/{package-guid}?api-version=5.0-preview.1"
$package = Invoke-RestMethod -Uri $url -Method Get -Headers $head -ContentType application/json
$latestVersion = ($package.versions.Where({ $_.isLatest -eq $True })).version
Write-Host "The latest version is $latestVersion"
Write-Host "##vso[task.setvariable variable=latestVersion]$latestVersion"
env:
TOKEN: $(system.accesstoken)
Now, in the download task use it:
vstsPackageVersion: $(latestVersion)