PageRenderTime 26ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/test/tools/CodeCoverageAutomation/Start-CodeCoverageRun.ps1

https://gitlab.com/unofficial-mirrors/PowerShell
Powershell | 379 lines | 367 code | 5 blank | 7 comment | 2 complexity | c3064234815be173abbf715217af7321 MD5 | raw file
  1. # Copyright (c) Microsoft Corporation. All rights reserved.
  2. # Licensed under the MIT License.
  3. param(
  4. [Parameter(Mandatory = $true, Position = 0)] $coverallsToken,
  5. [Parameter(Mandatory = $true, Position = 1)] $codecovToken,
  6. [Parameter(Position = 2)] $azureLogDrive = "L:\",
  7. [switch] $SuppressQuiet
  8. )
  9. # Read the XML and create a dictionary for FileUID -> file full path.
  10. function GetFileTable()
  11. {
  12. $files = $script:covData | Select-Xml './/File'
  13. foreach($file in $files)
  14. {
  15. $script:fileTable[$file.Node.uid] = $file.Node.fullPath
  16. }
  17. }
  18. # Get sequence points for a particular file
  19. function GetSequencePointsForFile([string] $fileId)
  20. {
  21. $lineCoverage = [System.Collections.Generic.Dictionary[string,int]]::new()
  22. $sequencePoints = $script:covData | Select-Xml ".//SequencePoint[@fileid = '$fileId']"
  23. if($sequencePoints.Count -gt 0)
  24. {
  25. foreach($sp in $sequencePoints)
  26. {
  27. $visitedCount = [int]::Parse($sp.Node.vc)
  28. $lineNumber = [int]::Parse($sp.Node.sl)
  29. $lineCoverage[$lineNumber] += [int]::Parse($visitedCount)
  30. }
  31. return $lineCoverage
  32. }
  33. }
  34. #### Convert the OpenCover XML output for CodeCov.io JSON format as it is smaller.
  35. function ConvertTo-CodeCovJson
  36. {
  37. param(
  38. [string] $Path,
  39. [string] $DestinationPath
  40. )
  41. $Script:fileTable = [ordered]@{}
  42. $Script:covData = [xml] (Get-Content -ReadCount 0 -Raw -Path $Path)
  43. $totalCoverage = [PSCustomObject]::new()
  44. $totalCoverage | Add-Member -MemberType NoteProperty -Name "coverage" -Value ([PSCustomObject]::new())
  45. ## Populate the dictionary with file uid and file names.
  46. GetFileTable
  47. $keys = $Script:fileTable.Keys
  48. $progress=0
  49. foreach($f in $keys)
  50. {
  51. Write-Progress -Id 1 -Activity "Converting to JSON" -Status 'Converting' -PercentComplete ($progress * 100 / $keys.Count)
  52. $fileCoverage = GetSequencePointsForFile -fileId $f
  53. $fileName = $Script:fileTable[$f]
  54. $previousFileCoverage = $totalCoverage.coverage.${fileName}
  55. ##Update the values for the lines in the file.
  56. if($null -ne $previousFileCoverage)
  57. {
  58. foreach($lineNumber in $fileCoverage.Keys)
  59. {
  60. $previousFileCoverage[$lineNumber] += [int]::Parse($fileCoverage[$lineNumber])
  61. }
  62. }
  63. else ## the file is new, so add the values as a new NoteProperty.
  64. {
  65. $totalCoverage.coverage | Add-Member -MemberType NoteProperty -Value $fileCoverage -Name $fileName
  66. }
  67. $progress++
  68. }
  69. Write-Progress -Id 1 -Completed -Activity "Converting to JSON"
  70. $totalCoverage | ConvertTo-Json -Depth 5 -Compress | Out-File $DestinationPath -Encoding ascii
  71. }
  72. function Write-LogPassThru
  73. {
  74. Param(
  75. [Parameter(Mandatory=$true, ValueFromPipeline=$true, Position = 0)]
  76. [string] $Message,
  77. $Path = "$env:Temp\CodeCoverageRunLogs.txt"
  78. )
  79. $message = "{0:d} - {0:t} : {1}" -f ([datetime]::now),$message
  80. Add-Content -Path $Path -Value $Message -PassThru -Force
  81. }
  82. function Push-CodeCovData
  83. {
  84. param (
  85. [Parameter(Mandatory=$true)]$file,
  86. [Parameter(Mandatory=$true)]$CommitID,
  87. [Parameter(Mandatory=$false)]$token,
  88. [Parameter(Mandatory=$false)]$Branch = "master"
  89. )
  90. $VERSION="64c1150"
  91. $url="https://codecov.io"
  92. $query = "package=bash-${VERSION}&token=${token}&branch=${Branch}&commit=${CommitID}&build=&build_url=&tag=&slug=&yaml=&service=&flags=&pr=&job="
  93. $uri = "$url/upload/v2?${query}"
  94. $response = Invoke-WebRequest -Method Post -InFile $file -Uri $uri
  95. if ( $response.StatusCode -ne 200 )
  96. {
  97. Write-LogPassThru -Message "Upload failed for upload uri: $uploaduri"
  98. throw "upload failed"
  99. }
  100. }
  101. Write-LogPassThru -Message "***** New Run *****"
  102. Write-LogPassThru -Message "Forcing winrm quickconfig as it is required for remoting tests."
  103. winrm quickconfig -force
  104. $codeCoverageZip = 'https://ci.appveyor.com/api/projects/PowerShell/powershell-f975h/artifacts/CodeCoverage.zip'
  105. $testContentZip = 'https://ci.appveyor.com/api/projects/PowerShell/powershell-f975h/artifacts/tests.zip'
  106. $openCoverZip = 'https://ci.appveyor.com/api/projects/PowerShell/powershell-f975h/artifacts/OpenCover.zip'
  107. Write-LogPassThru -Message "codeCoverageZip: $codeCoverageZip"
  108. Write-LogPassThru -Message "testcontentZip: $testContentZip"
  109. Write-LogPassThru -Message "openCoverZip: $openCoverZip"
  110. $outputBaseFolder = "$env:Temp\CC"
  111. $null = New-Item -ItemType Directory -Path $outputBaseFolder -Force
  112. $openCoverPath = "$outputBaseFolder\OpenCover"
  113. $testRootPath = "$outputBaseFolder\tests"
  114. $testPath = "$testRootPath\powershell"
  115. $psBinPath = "$outputBaseFolder\PSCodeCoverage"
  116. $openCoverTargetDirectory = "$outputBaseFolder\OpenCoverToolset"
  117. $outputLog = "$outputBaseFolder\CodeCoverageOutput.xml"
  118. $elevatedLogs = "$outputBaseFolder\TestResults_Elevated.xml"
  119. $unelevatedLogs = "$outputBaseFolder\TestResults_Unelevated.xml"
  120. $testToolsPath = "$testRootPath\tools"
  121. $jsonFile = "$outputBaseFolder\CC.json"
  122. try
  123. {
  124. ## Github needs TLS1.2 whereas the defaults for Invoke-WebRequest do not have TLS1.2
  125. $prevSecProtocol = [System.Net.ServicePointManager]::SecurityProtocol
  126. [System.Net.ServicePointManager]::SecurityProtocol =
  127. [System.Net.ServicePointManager]::SecurityProtocol -bor
  128. [System.Security.Authentication.SslProtocols]::Tls12 -bor
  129. [System.Security.Authentication.SslProtocols]::Tls11
  130. # first thing to do is to be sure that no processes are running which will cause us issues
  131. Get-Process pwsh -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction Stop
  132. ## This is required so we do not keep on merging coverage reports.
  133. if(Test-Path $outputLog)
  134. {
  135. Remove-Item $outputLog -Force -ErrorAction SilentlyContinue
  136. }
  137. $oldErrorActionPreference = $ErrorActionPreference
  138. $ErrorActionPreference = 'Stop'
  139. $oldProgressPreference = $ProgressPreference
  140. $ProgressPreference = 'SilentlyContinue'
  141. Write-LogPassThru -Message "Starting downloads."
  142. $CoverageZipFilePath = "$outputBaseFolder\PSCodeCoverage.zip"
  143. if(Test-Path $CoverageZipFilePath)
  144. {
  145. Remove-Item $CoverageZipFilePath -Force
  146. }
  147. Invoke-WebRequest -uri $codeCoverageZip -outfile "$outputBaseFolder\PSCodeCoverage.zip"
  148. $TestsZipFilePath = "$outputBaseFolder\tests.zip"
  149. if(Test-Path $TestsZipFilePath)
  150. {
  151. Remove-Item $TestsZipFilePath -Force
  152. }
  153. Invoke-WebRequest -uri $testContentZip -outfile $TestsZipFilePath
  154. $OpenCoverZipFilePath = "$outputBaseFolder\OpenCover.zip"
  155. if(Test-Path $OpenCoverZipFilePath)
  156. {
  157. Remove-Item $OpenCoverZipFilePath -Force
  158. }
  159. Invoke-WebRequest -uri $openCoverZip -outfile $OpenCoverZipFilePath
  160. Write-LogPassThru -Message "Downloads complete. Starting expansion"
  161. if(Test-Path $psBinPath)
  162. {
  163. Remove-Item -Force -Recurse $psBinPath
  164. }
  165. Expand-Archive -path $CoverageZipFilePath -destinationpath "$psBinPath" -Force
  166. if(Test-Path $testRootPath)
  167. {
  168. Remove-Item -Force -Recurse $testRootPath
  169. }
  170. Expand-Archive -path $TestsZipFilePath -destinationpath $testRootPath -Force
  171. if(Test-Path $openCoverPath)
  172. {
  173. Remove-Item -Force -Recurse $openCoverPath
  174. }
  175. Expand-Archive -path $OpenCoverZipFilePath -destinationpath $openCoverPath -Force
  176. Write-LogPassThru -Message "Expansion complete."
  177. if(Test-Path $elevatedLogs)
  178. {
  179. Remove-Item -Force -Recurse $elevatedLogs
  180. }
  181. if(Test-Path $unelevatedLogs)
  182. {
  183. Remove-Item -Force -Recurse $unelevatedLogs
  184. }
  185. if(Test-Path $outputLog)
  186. {
  187. Remove-Item $outputLog -Force -ErrorAction SilentlyContinue
  188. }
  189. Import-Module "$openCoverPath\OpenCover" -Force
  190. Install-OpenCover -TargetDirectory $openCoverTargetDirectory -force
  191. Write-LogPassThru -Message "OpenCover installed."
  192. Write-LogPassThru -Message "TestPath : $testPath"
  193. Write-LogPassThru -Message "openCoverPath : $openCoverTargetDirectory\OpenCover"
  194. Write-LogPassThru -Message "psbinpath : $psBinPath"
  195. Write-LogPassThru -Message "elevatedLog : $elevatedLogs"
  196. Write-LogPassThru -Message "unelevatedLog : $unelevatedLogs"
  197. Write-LogPassThru -Message "TestToolsPath : $testToolsPath"
  198. $openCoverParams = @{outputlog = $outputLog;
  199. TestPath = $testPath;
  200. OpenCoverPath = "$openCoverTargetDirectory\OpenCover";
  201. PowerShellExeDirectory = "$psBinPath";
  202. PesterLogElevated = $elevatedLogs;
  203. PesterLogUnelevated = $unelevatedLogs;
  204. TestToolsModulesPath = "$testToolsPath\Modules";
  205. }
  206. if($SuppressQuiet)
  207. {
  208. $openCoverParams.Add('SuppressQuiet', $true)
  209. }
  210. # grab the commitID, we need this to grab the right sources
  211. $assemblyLocation = & "$psBinPath\pwsh.exe" -noprofile -command { Get-Item ([psobject].Assembly.Location) }
  212. $productVersion = $assemblyLocation.VersionInfo.productVersion
  213. $commitId = $productVersion.split(" ")[-1]
  214. Write-LogPassThru -Message "Using GitCommitId: $commitId"
  215. # download the src directory
  216. try
  217. {
  218. $gitexe = "C:\Program Files\git\bin\git.exe"
  219. # operations relative to where the test location is.
  220. # some tests rely on source files being available in $outputBaseFolder/test
  221. Push-Location $outputBaseFolder
  222. # clean up partial repo clone before starting
  223. $cleanupDirectories = "${outputBaseFolder}/.git",
  224. "${outputBaseFolder}/src",
  225. "${outputBaseFolder}/assets"
  226. foreach($directory in $cleanupDirectories)
  227. {
  228. if ( Test-Path "$directory" )
  229. {
  230. Remove-Item -Force -Recurse "$directory"
  231. }
  232. }
  233. Write-LogPassThru -Message "initializing repo in $outputBaseFolder"
  234. & $gitexe init
  235. Write-LogPassThru -Message "git operation 'init' returned $LASTEXITCODE"
  236. Write-LogPassThru -Message "adding remote"
  237. & $gitexe remote add origin https://github.com/PowerShell/PowerShell
  238. Write-LogPassThru -Message "git operation 'remote add' returned $LASTEXITCODE"
  239. Write-LogPassThru -Message "setting sparse-checkout"
  240. & $gitexe config core.sparsecheckout true
  241. Write-LogPassThru -Message "git operation 'set sparse-checkout' returned $LASTEXITCODE"
  242. Write-LogPassThru -Message "pulling sparse repo"
  243. "/src" | Out-File -Encoding ascii .git\info\sparse-checkout -Force
  244. "/assets" | Out-File -Encoding ascii .git\info\sparse-checkout -Append
  245. & $gitexe pull origin master
  246. Write-LogPassThru -Message "git operation 'pull' returned $LASTEXITCODE"
  247. Write-LogPassThru -Message "checkout commit $commitId"
  248. & $gitexe checkout $commitId
  249. Write-LogPassThru -Message "git operation 'checkout' returned $LASTEXITCODE"
  250. }
  251. finally
  252. {
  253. Pop-Location
  254. }
  255. $openCoverParams | Out-String | Write-LogPassThru
  256. Write-LogPassThru -Message "Starting test run."
  257. try {
  258. # now invoke opencover
  259. Invoke-OpenCover @openCoverParams | Out-String | Write-LogPassThru
  260. }
  261. catch {
  262. ("ERROR: " + $_.ScriptStackTrace) | Write-LogPassThru
  263. $_ 2>&1 | out-string -Stream | %{ "ERROR: $_" } | Write-LogPassThru
  264. }
  265. if(Test-Path $outputLog)
  266. {
  267. Write-LogPassThru -Message (get-childitem $outputLog).FullName
  268. }
  269. Write-LogPassThru -Message "Test run done."
  270. Write-LogPassThru -Message $commitId
  271. $commitInfo = Invoke-RestMethod -Method Get "https://api.github.com/repos/powershell/powershell/git/commits/$commitId"
  272. $message = ($commitInfo.message).replace("`n", " ")
  273. Write-LogPassThru -Message "Uploading to CodeCov"
  274. if ( Test-Path $outputLog ) {
  275. ConvertTo-CodeCovJson -Path $outputLog -DestinationPath $jsonFile
  276. Push-CodeCovData -file $jsonFile -CommitID $commitId -token $codecovToken -Branch 'master'
  277. Write-LogPassThru -Message "Upload complete."
  278. }
  279. else {
  280. Write-LogPassThru -Message "ERROR: Could not find $outputLog - no upload"
  281. }
  282. }
  283. catch
  284. {
  285. Write-LogPassThru -Message $_
  286. }
  287. finally
  288. {
  289. ## reset TLS1.2 settings.
  290. [System.Net.ServicePointManager]::SecurityProtocol = $prevSecProtocol
  291. # the powershell execution should be done, be sure that there are no PowerShell test executables running because
  292. # they will cause subsequent coverage runs to behave poorly. Make sure that the path is properly formatted, and
  293. # we need to use like rather than match because on Windows, there will be "\" as path separators which would need
  294. # escaping for -match
  295. $ResolvedPSBinPath = (Resolve-Path ${psbinpath}).Path
  296. Get-Process PowerShell | Where-Object { $_.Path -like "*${ResolvedPSBinPath}*" } | Stop-Process -Force -ErrorAction Continue
  297. ## See if Azure log directory is mounted
  298. if(Test-Path $azureLogDrive)
  299. {
  300. ##Create yyyy-dd folder
  301. $monthFolder = "{0:yyyy-MM}" -f [datetime]::Now
  302. $monthFolderFullPath = New-Item -Path (Join-Path $azureLogDrive $monthFolder) -ItemType Directory -Force
  303. $windowsFolderPath = New-Item (Join-Path $monthFolderFullPath "Windows") -ItemType Directory -Force
  304. $destinationPath = Join-Path $env:Temp ("CodeCoverageLogs-{0:yyyy_MM_dd}-{0:hh_mm_ss}.zip" -f [datetime]::Now)
  305. Compress-Archive -Path $elevatedLogs,$unelevatedLogs,$outputLog -DestinationPath $destinationPath
  306. Copy-Item $destinationPath $windowsFolderPath -Force -ErrorAction SilentlyContinue
  307. Remove-Item -Path $destinationPath -Force -ErrorAction SilentlyContinue
  308. }
  309. Write-LogPassThru -Message "**** COMPLETE ****"
  310. ## Disable the cleanup till we stabilize.
  311. #Remove-Item -recurse -force -path $outputBaseFolder
  312. $ErrorActionPreference = $oldErrorActionPreference
  313. $ProgressPreference = $oldProgressPreference
  314. }