2019-04-16 12:38:55 +00:00
|
|
|
param(
|
|
|
|
[Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where NuGet packages to be checked are stored
|
|
|
|
[Parameter(Mandatory=$true)][string] $ExtractPath, # Full path to directory where the packages will be extracted during validation
|
|
|
|
[Parameter(Mandatory=$true)][string] $SymbolToolPath # Full path to directory where dotnet symbol-tool was installed
|
|
|
|
)
|
|
|
|
|
|
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
2019-11-22 13:41:58 +00:00
|
|
|
. $PSScriptRoot\pipeline-logging-functions.ps1
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
function FirstMatchingSymbolDescriptionOrDefault {
|
|
|
|
param(
|
|
|
|
[string] $FullPath, # Full path to the module that has to be checked
|
2019-11-22 13:41:58 +00:00
|
|
|
[string] $TargetServerParameter, # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols
|
2019-04-18 12:32:06 +00:00
|
|
|
[string] $SymbolsPath
|
2019-04-16 12:38:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
$FileName = [System.IO.Path]::GetFileName($FullPath)
|
|
|
|
$Extension = [System.IO.Path]::GetExtension($FullPath)
|
|
|
|
|
|
|
|
# Those below are potential symbol files that the `dotnet symbol` might
|
|
|
|
# return. Which one will be returned depend on the type of file we are
|
|
|
|
# checking and which type of file was uploaded.
|
|
|
|
|
|
|
|
# The file itself is returned
|
2019-11-22 13:41:58 +00:00
|
|
|
$SymbolPath = $SymbolsPath + '\' + $FileName
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
# PDB file for the module
|
2019-11-22 13:41:58 +00:00
|
|
|
$PdbPath = $SymbolPath.Replace($Extension, '.pdb')
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
# PDB file for R2R module (created by crossgen)
|
2019-11-22 13:41:58 +00:00
|
|
|
$NGenPdb = $SymbolPath.Replace($Extension, '.ni.pdb')
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
# DBG file for a .so library
|
2019-11-22 13:41:58 +00:00
|
|
|
$SODbg = $SymbolPath.Replace($Extension, '.so.dbg')
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
# DWARF file for a .dylib
|
2019-11-22 13:41:58 +00:00
|
|
|
$DylibDwarf = $SymbolPath.Replace($Extension, '.dylib.dwarf')
|
2019-04-18 12:32:06 +00:00
|
|
|
|
2019-11-22 13:41:58 +00:00
|
|
|
.\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParameter $FullPath -o $SymbolsPath | Out-Null
|
2019-04-18 12:32:06 +00:00
|
|
|
|
2019-04-16 12:38:55 +00:00
|
|
|
if (Test-Path $PdbPath) {
|
2019-11-22 13:41:58 +00:00
|
|
|
return 'PDB'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
elseif (Test-Path $NGenPdb) {
|
2019-11-22 13:41:58 +00:00
|
|
|
return 'NGen PDB'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
elseif (Test-Path $SODbg) {
|
2019-11-22 13:41:58 +00:00
|
|
|
return 'DBG for SO'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
elseif (Test-Path $DylibDwarf) {
|
2019-11-22 13:41:58 +00:00
|
|
|
return 'Dwarf for Dylib'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
elseif (Test-Path $SymbolPath) {
|
2019-11-22 13:41:58 +00:00
|
|
|
return 'Module'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return $null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function CountMissingSymbols {
|
|
|
|
param(
|
|
|
|
[string] $PackagePath # Path to a NuGet package
|
|
|
|
)
|
|
|
|
|
|
|
|
# Ensure input file exist
|
|
|
|
if (!(Test-Path $PackagePath)) {
|
|
|
|
throw "Input file does not exist: $PackagePath"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Extensions for which we'll look for symbols
|
2019-11-22 13:41:58 +00:00
|
|
|
$RelevantExtensions = @('.dll', '.exe', '.so', '.dylib')
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
# How many files are missing symbol information
|
|
|
|
$MissingSymbols = 0
|
|
|
|
|
|
|
|
$PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath)
|
2019-04-18 12:32:06 +00:00
|
|
|
$PackageGuid = New-Guid
|
|
|
|
$ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid
|
2019-11-22 13:41:58 +00:00
|
|
|
$SymbolsPath = Join-Path -Path $ExtractPath -ChildPath 'Symbols'
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
[System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath)
|
|
|
|
|
|
|
|
# Makes easier to reference `symbol tool`
|
|
|
|
Push-Location $SymbolToolPath
|
|
|
|
|
|
|
|
Get-ChildItem -Recurse $ExtractPath |
|
|
|
|
Where-Object {$RelevantExtensions -contains $_.Extension} |
|
|
|
|
ForEach-Object {
|
2019-11-22 13:41:58 +00:00
|
|
|
if ($_.FullName -Match '\\ref\\') {
|
2019-04-18 12:32:06 +00:00
|
|
|
Write-Host "`t Ignoring reference assembly file" $_.FullName
|
|
|
|
return
|
|
|
|
}
|
2019-04-16 12:38:55 +00:00
|
|
|
|
2019-11-22 13:41:58 +00:00
|
|
|
$SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--microsoft-symbol-server' -SymbolsPath $SymbolsPath
|
|
|
|
$SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault -FullPath $_.FullName -TargetServerParameter '--internal-server' -SymbolsPath $SymbolsPath
|
2019-04-18 12:32:06 +00:00
|
|
|
|
|
|
|
Write-Host -NoNewLine "`t Checking file" $_.FullName "... "
|
2019-04-16 12:38:55 +00:00
|
|
|
|
|
|
|
if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) {
|
2019-11-22 13:41:58 +00:00
|
|
|
Write-Host "Symbols found on MSDL (${$SymbolsOnMSDL}) and SymWeb (${$SymbolsOnSymWeb})"
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
$MissingSymbols++
|
|
|
|
|
|
|
|
if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) {
|
2019-11-22 13:41:58 +00:00
|
|
|
Write-Host 'No symbols found on MSDL or SymWeb!'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ($SymbolsOnMSDL -eq $null) {
|
2019-11-22 13:41:58 +00:00
|
|
|
Write-Host 'No symbols found on MSDL!'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
else {
|
2019-11-22 13:41:58 +00:00
|
|
|
Write-Host 'No symbols found on SymWeb!'
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Pop-Location
|
|
|
|
|
|
|
|
return $MissingSymbols
|
|
|
|
}
|
|
|
|
|
|
|
|
function CheckSymbolsAvailable {
|
|
|
|
if (Test-Path $ExtractPath) {
|
2019-04-18 12:32:06 +00:00
|
|
|
Remove-Item $ExtractPath -Force -Recurse -ErrorAction SilentlyContinue
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Get-ChildItem "$InputPath\*.nupkg" |
|
|
|
|
ForEach-Object {
|
|
|
|
$FileName = $_.Name
|
2019-11-22 13:41:58 +00:00
|
|
|
|
2019-04-18 12:32:06 +00:00
|
|
|
# These packages from Arcade-Services include some native libraries that
|
|
|
|
# our current symbol uploader can't handle. Below is a workaround until
|
|
|
|
# we get issue: https://github.com/dotnet/arcade/issues/2457 sorted.
|
2019-11-22 13:41:58 +00:00
|
|
|
if ($FileName -Match 'Microsoft\.DotNet\.Darc\.') {
|
2019-04-18 12:32:06 +00:00
|
|
|
Write-Host "Ignoring Arcade-services file: $FileName"
|
|
|
|
Write-Host
|
|
|
|
return
|
|
|
|
}
|
2019-11-22 13:41:58 +00:00
|
|
|
elseif ($FileName -Match 'Microsoft\.DotNet\.Maestro\.Tasks\.') {
|
2019-04-18 12:32:06 +00:00
|
|
|
Write-Host "Ignoring Arcade-services file: $FileName"
|
|
|
|
Write-Host
|
|
|
|
return
|
|
|
|
}
|
2019-11-22 13:41:58 +00:00
|
|
|
|
2019-04-16 12:38:55 +00:00
|
|
|
Write-Host "Validating $FileName "
|
|
|
|
$Status = CountMissingSymbols "$InputPath\$FileName"
|
|
|
|
|
|
|
|
if ($Status -ne 0) {
|
2019-11-22 13:41:58 +00:00
|
|
|
Write-PipelineTelemetryError -Category 'CheckSymbols' -Message "Missing symbols for $Status modules in the package $FileName"
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
2019-04-18 12:32:06 +00:00
|
|
|
|
|
|
|
Write-Host
|
2019-04-16 12:38:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckSymbolsAvailable
|