Skip to content

Commit d87e550

Browse files
adegeoThraka
andauthored
Add snippets 5000 check (#6982)
Co-authored-by: Andy De George <[email protected]>
1 parent cf7ea53 commit d87e550

File tree

4 files changed

+449
-0
lines changed

4 files changed

+449
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# This is a basic workflow to help you get started with Actions
2+
name: Snippets 5000
3+
4+
# Controls when the action will run. Triggers the workflow on push or pull request
5+
# events on the main branch only.
6+
on:
7+
pull_request:
8+
paths:
9+
- "**.cs"
10+
- "**.vb"
11+
- "**.fs"
12+
- "**.cpp"
13+
- "**.h"
14+
- "**.xaml"
15+
- "**.razor"
16+
- "**.cshtml"
17+
- "**.vbhtml"
18+
- "**.csproj"
19+
- "**.vbproj"
20+
- "**.fsproj"
21+
- "**.vcxproj"
22+
- "**.sln"
23+
- "**global.json"
24+
- "**snippets.5000.json"
25+
branches: [ main ]
26+
27+
env:
28+
DOTNET_INSTALLER_CHANNEL: '6.0'
29+
DOTNET_DO_INSTALL: 'true'
30+
EnableNuGetPackageRestore: 'True'
31+
32+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
33+
jobs:
34+
# This workflow contains a single job called "build"
35+
build:
36+
# The type of runner that the job will run on
37+
runs-on: windows-latest
38+
39+
# Steps represent a sequence of tasks that will be executed as part of the job
40+
steps:
41+
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
42+
- uses: actions/checkout@a81bbbf8298c0fa03ea29cdc473d45769f953675 #@v2
43+
44+
# Get the latest preview SDK (or sdk not installed by the runner)
45+
- name: Setup .NET SDK
46+
if: ${{ env.DOTNET_DO_INSTALL == 'true' }}
47+
run: |
48+
echo "Downloading dotnet-install.ps1"
49+
Invoke-WebRequest https://raw.githubusercontent.com/dotnet/install-scripts/master/src/dotnet-install.ps1 -OutFile dotnet-install.ps1
50+
echo "Installing dotnet version ${{ env.DOTNET_INSTALLER_CHANNEL }}"
51+
.\dotnet-install.ps1 -InstallDir "c:\program files\dotnet" -Channel "${{ env.DOTNET_INSTALLER_CHANNEL }}"
52+
53+
# Print dotnet info
54+
- name: Display .NET info
55+
run: |
56+
dotnet --info
57+
58+
# Install locate projs global tool
59+
- name: Install LocateProjects tool
60+
run: |
61+
dotnet tool install --global --add-source ./.github/workflows/dependencies/ DotnetDocsTools.LocateProjects
62+
63+
# Run locate projs tool
64+
- name: Locate projects for PR
65+
env:
66+
GitHubKey: ${{ secrets.GITHUB_TOKEN }}
67+
LocateExts: ".cs;.vb;.fs;.cpp;.h;.xaml;.razor;.cshtml;.vbhtml;.csproj;.fsproj;.vbproj;.vcxproj;.sln"
68+
run: |
69+
./.github/workflows/dependencies/Get-MSBuildResults.ps1 "${{ github.workspace }}" -PullRequest ${{ github.event.number }} -RepoOwner ${{ github.repository_owner }} -RepoName ${{ github.event.repository.name }}
70+
71+
# Update build output json file
72+
- name: Upload build results
73+
uses: actions/upload-artifact@3446296876d12d4e3a0f3145a3c87e67bf0a16b5 #@v1
74+
with:
75+
name: build
76+
path: ./output.json
77+
78+
# Return status based on json file
79+
- name: Report status
80+
run: |
81+
./.github/workflows/dependencies/Out-GithubActionStatus.ps1
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
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

Comments
 (0)