|
| 1 | +<# |
| 2 | +
|
| 3 | +.SYNOPSIS |
| 4 | + Invokes dotnet build on the samples sln and project files. |
| 5 | +
|
| 6 | +.DESCRIPTION |
| 7 | + Invokes dotnet build on the samples sln and project files. |
| 8 | +
|
| 9 | +.PARAMETER RepoRootDir |
| 10 | + The directory of the repository files on the local machine. |
| 11 | +
|
| 12 | +.PARAMETER PullRequest |
| 13 | + The pull requst to process. If 0 or not passed, processes the whole repo |
| 14 | +
|
| 15 | +.PARAMETER RepoOwner |
| 16 | + The name of the repository owner. |
| 17 | + |
| 18 | +.PARAMETER RepoName |
| 19 | + The name of the repository. |
| 20 | +
|
| 21 | +.PARAMETER RangeStart |
| 22 | + A range of results to process. |
| 23 | +
|
| 24 | +.PARAMETER RangeEnd |
| 25 | + A range of results to process. |
| 26 | +
|
| 27 | +.INPUTS |
| 28 | + None |
| 29 | +
|
| 30 | +.OUTPUTS |
| 31 | + None |
| 32 | +
|
| 33 | +.NOTES |
| 34 | + Version: 1.5 |
| 35 | + |
| 36 | + Creation Date: 04/02/2021 |
| 37 | + Purpose/Change: Add extra logging info. |
| 38 | +#> |
| 39 | + |
| 40 | +[CmdletBinding()] |
| 41 | +Param( |
| 42 | + [Parameter(Mandatory = $true, ValueFromPipeline = $false)] |
| 43 | + [System.String] $RepoRootDir = $env:RepoRootDir, |
| 44 | + |
| 45 | + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] |
| 46 | + [System.Int64] $PullRequest = 0, |
| 47 | + |
| 48 | + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] |
| 49 | + [System.String] $RepoOwner = "", |
| 50 | + |
| 51 | + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] |
| 52 | + [System.String] $RepoName = "", |
| 53 | + |
| 54 | + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] |
| 55 | + [System.Int32] $RangeStart = $env:rangestart, |
| 56 | + |
| 57 | + [Parameter(Mandatory = $false, ValueFromPipeline = $false)] |
| 58 | + [System.Int32] $RangeEnd = $env:rangeend |
| 59 | +) |
| 60 | + |
| 61 | +$Global:statusOutput = @() |
| 62 | + |
| 63 | +Write-Host "Gathering solutions and projects..." |
| 64 | + |
| 65 | +if ($PullRequest -ne 0) { |
| 66 | + Write-Host "Running `"LocateProjects `"$RepoRootDir`" --pullrequest $PullRequest --owner $RepoOwner --repo $RepoName`"" |
| 67 | + $output = Invoke-Expression "LocateProjects `"$RepoRootDir`" --pullrequest $PullRequest --owner $RepoOwner --repo $RepoName" |
| 68 | +} |
| 69 | +else { |
| 70 | + Write-Host "Running `"LocateProjects `"$RepoRootDir`"" |
| 71 | + $output = Invoke-Expression "LocateProjects `"$RepoRootDir`"" |
| 72 | +} |
| 73 | + |
| 74 | +if ($LASTEXITCODE -ne 0) |
| 75 | +{ |
| 76 | + $output |
| 77 | + throw "Error on running LocateProjects" |
| 78 | +} |
| 79 | + |
| 80 | +function New-Result($inputFile, $projectFile, $exitcode, $outputText) |
| 81 | +{ |
| 82 | + $info = @{} |
| 83 | + |
| 84 | + $info.InputFile = $inputFile |
| 85 | + $info.ProjectFile = $projectFile |
| 86 | + $info.ExitCode = $exitcode |
| 87 | + $info.Output = $outputText |
| 88 | + |
| 89 | + $object = New-Object -TypeName PSObject -Prop $info |
| 90 | + $Global:statusOutput += $object |
| 91 | +} |
| 92 | + |
| 93 | +$workingSet = $output |
| 94 | + |
| 95 | +if (($RangeStart -ne 0) -and ($RangeEnd -ne 0)){ |
| 96 | + $workingSet = $output[$RangeStart..$RangeEnd] |
| 97 | +} |
| 98 | + |
| 99 | +# Log working set items prior to filtering |
| 100 | +$workingSet | Write-Host |
| 101 | + |
| 102 | +# Remove duplicated projects |
| 103 | +$projects = @() |
| 104 | +$workingSetTemp = @() |
| 105 | + |
| 106 | +foreach ($item in $workingSet) { |
| 107 | + $data = $item.Split('|') |
| 108 | + if ($projects.Contains($data[2].Trim())) { |
| 109 | + continue |
| 110 | + } |
| 111 | + if ($data[2].Trim() -ne "") { |
| 112 | + $projects += $data[2].Trim() |
| 113 | + } |
| 114 | + $workingSetTemp += $item |
| 115 | +} |
| 116 | + |
| 117 | +$workingSet = $workingSetTemp |
| 118 | + |
| 119 | +# Process working set |
| 120 | +$counter = 1 |
| 121 | +$length = $workingSet.Count |
| 122 | +$thisExitCode = 0 |
| 123 | + |
| 124 | +$ErrorActionPreference = "Continue" |
| 125 | + |
| 126 | +foreach ($item in $workingSet) { |
| 127 | + try { |
| 128 | + Write-Host "$counter/$length :: $Item" |
| 129 | + |
| 130 | + $data = $item.Split('|') |
| 131 | + |
| 132 | + # Project found, build it |
| 133 | + if ([int]$data[0] -eq 0) { |
| 134 | + $projectFile = Resolve-Path "$RepoRootDir\$($data[2])" |
| 135 | + $configFile = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($projectFile), "snippets.5000.json") |
| 136 | + |
| 137 | + # Create the default build command |
| 138 | + "dotnet build `"$projectFile`"" | Out-File ".\run.bat" |
| 139 | + |
| 140 | + # Check for config file |
| 141 | + if ([System.IO.File]::Exists($configFile) -eq $true) { |
| 142 | + Write-Host "- Config file found" |
| 143 | + |
| 144 | + $settings = $configFile | Get-ChildItem | Get-Content | ConvertFrom-Json |
| 145 | + |
| 146 | + if ($settings.host -eq "visualstudio") { |
| 147 | + Write-Host "- Using visual studio as build host" |
| 148 | + |
| 149 | + # Create the visual studio build command |
| 150 | + "CALL `"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat`"`n" + |
| 151 | + "msbuild.exe `"$projectFile`" -restore:True" ` |
| 152 | + | Out-File ".\run.bat" |
| 153 | + } |
| 154 | + elseif ($settings.host -eq "custom") { |
| 155 | + Write-Host "- Using custom build host: $($settings.command)" |
| 156 | + |
| 157 | + $ExecutionContext.InvokeCommand.ExpandString($settings.command) | Out-File ".\run.bat" |
| 158 | + } |
| 159 | + elseif ($settings.host -eq "dotnet") { |
| 160 | + Write-Host "- Using dotnet build host" |
| 161 | + |
| 162 | + "dotnet build `"$projectFile`"" | Out-File ".\run.bat" |
| 163 | + } |
| 164 | + else { |
| 165 | + throw "snippets.5000.json file isn't valid." |
| 166 | + } |
| 167 | + } |
| 168 | + |
| 169 | + Write-Host "run.bat contents: " |
| 170 | + Get-Content .\run.bat | Write-Host |
| 171 | + Write-Host |
| 172 | + |
| 173 | + Invoke-Expression ".\run.bat" | Tee-Object -Variable "result" |
| 174 | + $thisExitCode = 0 |
| 175 | + |
| 176 | + if ($LASTEXITCODE -ne 0) { |
| 177 | + $thisExitCode = 4 |
| 178 | + } |
| 179 | + |
| 180 | + New-Result $data[1] $projectFile $thisExitCode $result |
| 181 | + } |
| 182 | + |
| 183 | + # No project found |
| 184 | + elseif ([int]$data[0] -eq 1) { |
| 185 | + New-Result $data[1] "" 1 "😵 Project missing. A project (and optionally a solution file) must be in this directory or one of the parent directories to validate and build this code." |
| 186 | + |
| 187 | + $thisExitCode = 1 |
| 188 | + } |
| 189 | + |
| 190 | + # Too many projects found |
| 191 | + elseif ([int]$data[0] -eq 2) { |
| 192 | + New-Result $data[1] $data[2] 2 "😕 Too many projects found. A single project or solution must existing in this directory or one of the parent directories." |
| 193 | + |
| 194 | + $thisExitCode = 2 |
| 195 | + } |
| 196 | + |
| 197 | + # Solution found, but no project |
| 198 | + elseif ([int]$data[0] -eq 3) { |
| 199 | + New-Result $data[1] $data[2] 2 "😲 Solution found, but missing project. A project is required to compile this code." |
| 200 | + $thisExitCode = 3 |
| 201 | + } |
| 202 | + } |
| 203 | + catch { |
| 204 | + New-Result $data[1] $projectFile 1000 "ERROR: $($_.Exception)" |
| 205 | + $thisExitCode = 4 |
| 206 | + Write-Host $_.Exception.Message -Foreground "Red" |
| 207 | + Write-Host $_.ScriptStackTrace -Foreground "DarkGray" |
| 208 | + } |
| 209 | + |
| 210 | + $counter++ |
| 211 | +} |
| 212 | + |
| 213 | +$resultItems = $Global:statusOutput | Select-Object InputFile, ProjectFile, ExitCode, Output |
| 214 | + |
| 215 | +# Add our output type |
| 216 | +$typeResult = @" |
| 217 | +public class ResultItem |
| 218 | +{ |
| 219 | + public string ProjectFile; |
| 220 | + public string InputFile; |
| 221 | + public int ExitCode; |
| 222 | + public string BuildOutput; |
| 223 | + public MSBuildError[] Errors; |
| 224 | + public int ErrorCount; |
| 225 | +
|
| 226 | + public class MSBuildError |
| 227 | + { |
| 228 | + public string Line; |
| 229 | + public string Error; |
| 230 | + } |
| 231 | +} |
| 232 | +"@ |
| 233 | +Add-Type $typeResult |
| 234 | + |
| 235 | +$transformedItems = $resultItems | ForEach-Object { New-Object ResultItem -Property @{ |
| 236 | + ProjectFile = $_.ProjectFile.Path; |
| 237 | + InputFile = $_.InputFile; |
| 238 | + ExitCode = $_.ExitCode; |
| 239 | + BuildOutput = $_.Output; |
| 240 | + Errors = @(); |
| 241 | + ErrorCount = 0} |
| 242 | + } |
| 243 | + |
| 244 | +# Transform the build output to break it down into MSBuild result entries |
| 245 | +foreach ($item in $transformedItems) { |
| 246 | + $list = @() |
| 247 | + |
| 248 | + # Clean |
| 249 | + if ($item.ExitCode -eq 0) { |
| 250 | + #$list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = $item.BuildOutput; Error = $item.BuildOutput } |
| 251 | + } |
| 252 | + # No project found |
| 253 | + # Too many projects found |
| 254 | + # Solution found, but no project |
| 255 | + elseif ($item.ExitCode -ne 4) { |
| 256 | + $list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = $item.BuildOutput; Error = $item.BuildOutput } |
| 257 | + $item.ErrorCount = 1 |
| 258 | + } |
| 259 | + else { |
| 260 | + $errorInfo = $item.BuildOutput -Split [System.Environment]::NewLine | |
| 261 | + Select-String ": (?:Solution file error|error) ([^:]*)" | ` |
| 262 | + Select-Object Line -ExpandProperty Matches | ` |
| 263 | + Select-Object Line, Groups | ` |
| 264 | + Sort-Object Line | Get-Unique -AsString |
| 265 | + $item.ErrorCount = $errorInfo.Count |
| 266 | + foreach ($err in $errorInfo) { |
| 267 | + $list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = $err.Line; Error = $err.Groups[1].Value } |
| 268 | + } |
| 269 | + |
| 270 | + # Error count of 0 here means that no error was detected from build results, but there was still a failure of some kind |
| 271 | + if ($item.ErrorCount -eq 0) { |
| 272 | + $list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = "Unknown error occurred. Check log and build output."; Error = "4" } |
| 273 | + $item.ErrorCount = 1 |
| 274 | + } |
| 275 | + } |
| 276 | + |
| 277 | + $item.Errors = $list |
| 278 | + |
| 279 | +} |
| 280 | + |
| 281 | +$transformedItems | ConvertTo-Json -Depth 3 | Out-File 'output.json' |
| 282 | + |
| 283 | +exit 0 |
| 284 | + |
| 285 | + |
| 286 | +# Sample snippets.5000.json file |
| 287 | +<# |
| 288 | +{ |
| 289 | + "host": "visualstudio" |
| 290 | +} |
| 291 | +
|
| 292 | +#> |
0 commit comments