PowerShell/test/tools/CodeCoverageAutomation/Start-CodeCoverageRun.ps1
Aditya Patwardhan 5cd0e85d12 Fixed passing common test modules path to unelevated Powershell (#4313)
- Fixed the way common test modules are passed to elevated and unelevated powershell. Earlier, only elevated powershell got those through inheritance as a child process. Now we add them to the startup of the process.
- Fixed error reported by PSScriptAnalyzer about ? / Where-Object
- Converted all the parameters passed to powershell.exe to be a base64 encoded string to avoid complications with quotes.
- Removed code which was updated $env:PSModulePath as we do it in startup args for powershell process instead. 
- Added a way to disable -Quiet for Pester.
- Opencover.console.exe gets confused when the base64 encoded parameter is given with '&' invoke.
Writing to a ps1 file and invoking the script works around the issue.
This also makes it similar to how unelevated tests are invoked.
2017-08-04 09:16:17 -07:00

272 lines
9.9 KiB
PowerShell

param(
[Parameter(Mandatory = $true, Position = 0)] $coverallsToken,
[Parameter(Mandatory = $true, Position = 1)] $codecovToken,
[Parameter(Position = 2)] $azureLogDrive = "L:\",
[switch] $SuppressQuiet
)
# Read the XML and create a dictionary for FileUID -> file full path.
function GetFileTable()
{
$files = $script:covData | Select-Xml './/File'
foreach($file in $files)
{
$script:fileTable[$file.Node.uid] = $file.Node.fullPath
}
}
# Get sequence points for a particular file
function GetSequencePointsForFile([string] $fileId)
{
$lineCoverage = [System.Collections.Generic.Dictionary[string,int]]::new()
$sequencePoints = $script:covData | Select-Xml ".//SequencePoint[@fileid = '$fileId']"
if($sequencePoints.Count -gt 0)
{
foreach($sp in $sequencePoints)
{
$visitedCount = [int]::Parse($sp.Node.vc)
$lineNumber = [int]::Parse($sp.Node.sl)
$lineCoverage[$lineNumber] += [int]::Parse($visitedCount)
}
return $lineCoverage
}
}
#### Convert the OpenCover XML output for CodeCov.io JSON format as it is smaller.
function ConvertTo-CodeCovJson
{
param(
[string] $Path,
[string] $DestinationPath
)
$Script:fileTable = [ordered]@{}
$Script:covData = [xml] (Get-Content -ReadCount 0 -Raw -Path $Path)
$totalCoverage = [PSCustomObject]::new()
$totalCoverage | Add-Member -MemberType NoteProperty -Name "coverage" -Value ([PSCustomObject]::new())
## Populate the dictionary with file uid and file names.
GetFileTable
$keys = $Script:fileTable.Keys
$progress=0
foreach($f in $keys)
{
Write-Progress -Id 1 -Activity "Converting to JSON" -Status 'Converting' -PercentComplete ($progress * 100 / $keys.Count)
$fileCoverage = GetSequencePointsForFile -fileId $f
$fileName = $Script:fileTable[$f]
$previousFileCoverage = $totalCoverage.coverage.${fileName}
##Update the values for the lines in the file.
if($null -ne $previousFileCoverage)
{
foreach($lineNumber in $fileCoverage.Keys)
{
$previousFileCoverage[$lineNumber] += [int]::Parse($fileCoverage[$lineNumber])
}
}
else ## the file is new, so add the values as a new NoteProperty.
{
$totalCoverage.coverage | Add-Member -MemberType NoteProperty -Value $fileCoverage -Name $fileName
}
$progress++
}
Write-Progress -Id 1 -Completed -Activity "Converting to JSON"
$totalCoverage | ConvertTo-Json -Depth 5 -Compress | out-file $DestinationPath -Encoding ascii
}
function Write-LogPassThru
{
Param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true, Position = 0)]
[string] $Message,
$Path = "$env:Temp\CodeCoverageRunLogs.txt"
)
$message = "{0:d} - {0:t} : {1}" -f ([datetime]::now),$message
Add-Content -Path $Path -Value $Message -PassThru -Force
}
function Push-CodeCovData
{
param (
[Parameter(Mandatory=$true)]$file,
[Parameter(Mandatory=$true)]$CommitID,
[Parameter(Mandatory=$false)]$token,
[Parameter(Mandatory=$false)]$Branch = "master"
)
$VERSION="64c1150"
$url="https://codecov.io"
$query = "package=bash-${VERSION}&token=${token}&branch=${Branch}&commit=${CommitID}&build=&build_url=&tag=&slug=&yaml=&service=&flags=&pr=&job="
$uri = "$url/upload/v2?${query}"
$response = Invoke-WebRequest -Method Post -InFile $file -Uri $uri
if ( $response.StatusCode -ne 200 )
{
Write-LogPassThru -Message "Upload failed for upload uri: $uploaduri"
throw "upload failed"
}
}
Write-LogPassThru -Message "***** New Run *****"
Write-LogPassThru -Message "Forcing winrm quickconfig as it is required for remoting tests."
winrm quickconfig -force
$codeCoverageZip = 'https://ci.appveyor.com/api/projects/PowerShell/powershell-f975h/artifacts/CodeCoverage.zip'
$testContentZip = 'https://ci.appveyor.com/api/projects/PowerShell/powershell-f975h/artifacts/tests.zip'
$openCoverZip = 'https://ci.appveyor.com/api/projects/PowerShell/powershell-f975h/artifacts/OpenCover.zip'
Write-LogPassThru -Message "codeCoverageZip: $codeCoverageZip"
Write-LogPassThru -Message "testcontentZip: $testContentZip"
Write-LogPassThru -Message "openCoverZip: $openCoverZip"
$outputBaseFolder = "$env:Temp\CC"
$null = New-Item -ItemType Directory -Path $outputBaseFolder -Force
$openCoverPath = "$outputBaseFolder\OpenCover"
$testRootPath = "$outputBaseFolder\tests"
$testPath = "$testRootPath\powershell"
$psBinPath = "$outputBaseFolder\PSCodeCoverage"
$openCoverTargetDirectory = "$outputBaseFolder\OpenCoverToolset"
$outputLog = "$outputBaseFolder\CodeCoverageOutput.xml"
$elevatedLogs = "$outputBaseFolder\TestResults_Elevated.xml"
$unelevatedLogs = "$outputBaseFolder\TestResults_Unelevated.xml"
$testToolsPath = "$testRootPath\tools"
$jsonFile = "$outputBaseFolder\CC.json"
try
{
$oldErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
Write-LogPassThru -Message "Starting downloads."
Invoke-WebRequest -uri $codeCoverageZip -outfile "$outputBaseFolder\PSCodeCoverage.zip"
Invoke-WebRequest -uri $testContentZip -outfile "$outputBaseFolder\tests.zip"
Invoke-WebRequest -uri $openCoverZip -outfile "$outputBaseFolder\OpenCover.zip"
Write-LogPassThru -Message "Downloads complete. Starting expansion"
Expand-Archive -path "$outputBaseFolder\PSCodeCoverage.zip" -destinationpath "$psBinPath" -Force
Expand-Archive -path "$outputBaseFolder\tests.zip" -destinationpath $testRootPath -Force
Expand-Archive -path "$outputBaseFolder\OpenCover.zip" -destinationpath $openCoverPath -Force
## Download Coveralls.net uploader
$coverallsToolsUrl = 'https://github.com/csMACnz/coveralls.net/releases/download/0.7.0/coveralls.net.0.7.0.nupkg'
$coverallsPath = "$outputBaseFolder\coveralls"
## Saving the nupkg as zip so we can expand it.
Invoke-WebRequest -uri $coverallsToolsUrl -outfile "$outputBaseFolder\coveralls.zip"
Expand-Archive -Path "$outputBaseFolder\coveralls.zip" -DestinationPath $coverallsPath -Force
Write-LogPassThru -Message "Expansion complete."
Import-Module "$openCoverPath\OpenCover" -Force
Install-OpenCover -TargetDirectory $openCoverTargetDirectory -force
Write-LogPassThru -Message "OpenCover installed."
Write-LogPassThru -Message "TestPath : $testPath"
Write-LogPassThru -Message "openCoverPath : $openCoverTargetDirectory\OpenCover"
Write-LogPassThru -Message "psbinpath : $psBinPath"
Write-LogPassThru -Message "elevatedLog : $elevatedLogs"
Write-LogPassThru -Message "unelevatedLog : $unelevatedLogs"
Write-LogPassThru -Message "TestToolsPath : $testToolsPath"
$openCoverParams = @{outputlog = $outputLog;
TestPath = $testPath;
OpenCoverPath = "$openCoverTargetDirectory\OpenCover";
PowerShellExeDirectory = "$psBinPath";
PesterLogElevated = $elevatedLogs;
PesterLogUnelevated = $unelevatedLogs;
TestToolsModulesPath = "$testToolsPath\Modules";
}
if($SuppressQuiet)
{
$openCoverParams.Add('SuppressQuiet', $true)
}
$openCoverParams | Out-String | Write-LogPassThru
Write-LogPassThru -Message "Starting test run."
if(Test-Path $outputLog)
{
Remove-Item $outputLog -Force -ErrorAction SilentlyContinue
}
Invoke-OpenCover @openCoverParams
if(Test-Path $outputLog)
{
Write-LogPassThru -Message (get-childitem $outputLog).FullName
}
Write-LogPassThru -Message "Test run done."
$gitCommitId = & "$psBinPath\powershell.exe" -noprofile -command { $PSVersiontable.GitCommitId }
$commitId = $gitCommitId.substring($gitCommitId.LastIndexOf('-g') + 2)
Write-LogPassThru -Message $commitId
$coverallsPath = "$outputBaseFolder\coveralls"
$commitInfo = Invoke-RestMethod -Method Get "https://api.github.com/repos/powershell/powershell/git/commits/$commitId"
$message = ($commitInfo.message).replace("`n", " ")
$author = $commitInfo.author.name
$email = $commitInfo.author.email
$coverallsExe = Join-Path $coverallsPath "tools\csmacnz.Coveralls.exe"
$coverallsParams = @("--opencover",
"-i $outputLog",
"--repoToken $coverallsToken",
"--commitId $commitId",
"--commitBranch master",
"--commitAuthor `"$author`"",
"--commitEmail $email",
"--commitMessage `"$message`""
)
$coverallsParams | ForEach-Object { Write-LogPassThru -Message $_ }
Write-LogPassThru -Message "Uploading to CoverAlls"
& $coverallsExe """$coverallsParams"""
Write-LogPassThru -Message "Uploading to CodeCov"
ConvertTo-CodeCovJson -Path $outputLog -DestinationPath $jsonFile
Push-CodeCovData -file $jsonFile -CommitID $commitId -token $codecovToken -Branch 'master'
Write-LogPassThru -Message "Upload complete."
}
catch
{
Write-LogPassThru -Message $_
}
finally
{
## See if Azure log directory is mounted
if(Test-Path $azureLogDrive)
{
##Create yyyy-dd folder
$monthFolder = "{0:yyyy-MM}" -f [datetime]::Now
$monthFolderFullPath = New-Item -Path (Join-Path $azureLogDrive $monthFolder) -ItemType Directory -Force
$windowsFolderPath = New-Item (Join-Path $monthFolderFullPath "Windows") -ItemType Directory -Force
$destinationPath = Join-Path $env:Temp ("CodeCoverageLogs-{0:yyyy_MM_dd}-{0:hh_mm_ss}.zip" -f [datetime]::Now)
Compress-Archive -Path $elevatedLogs,$unelevatedLogs,$outputLog -DestinationPath $destinationPath
Copy-Item $destinationPath $windowsFolderPath -Force -ErrorAction SilentlyContinue
Remove-Item -Path $destinationPath -Force -ErrorAction SilentlyContinue
}
## Disable the cleanup till we stabilize.
#Remove-Item -recurse -force -path $outputBaseFolder
## This is required so we do not keep on merging coverage reports.
Remove-Item $outputLog -Force -ErrorAction SilentlyContinue
$ErrorActionPreference = $oldErrorActionPreference
}