diff --git a/snippets5000/Get-MSBuildResults.ps1 b/snippets5000/Get-MSBuildResults.ps1
deleted file mode 100644
index 9d7480ba..00000000
--- a/snippets5000/Get-MSBuildResults.ps1
+++ /dev/null
@@ -1,352 +0,0 @@
-<#
-
-.SYNOPSIS
- Invokes dotnet build on the samples sln and project files.
-
-.DESCRIPTION
- Invokes dotnet build on the samples sln and project files.
-
-.PARAMETER RepoRootDir
- The directory of the repository files on the local machine.
-
-.PARAMETER PullRequest
- The pull request to process. If 0 or not passed, processes the whole repo
-
-.PARAMETER RepoOwner
- The name of the repository owner.
-
-.PARAMETER RepoName
- The name of the repository.
-
-.PARAMETER RangeStart
- A range of results to process.
-
-.PARAMETER RangeEnd
- A range of results to process.
-
-.INPUTS
- None
-
-.OUTPUTS
- None
-
-.NOTES
-
- Version: 1.8
- Author: adegeo@microsoft.com
- Creation Date: 12/11/2020
- Update Date: 10/05/2022
- Purpose/Change: Add support for discovering and processing settings file for project errors (not found, too many, etc)
-
- Version: 1.7
- Author: adegeo@microsoft.com
- Creation Date: 12/11/2020
- Update Date: 09/26/2022
- Purpose/Change: Trim build error lines to help remove duplicates.
-
- Version: 1.6
- Author: adegeo@microsoft.com
- Creation Date: 12/11/2020
- Update Date: 03/10/2022
- Purpose/Change: Export proj/sln settings config to output.json file.
-#>
-
-[CmdletBinding()]
-Param(
- [Parameter(Mandatory = $true, ValueFromPipeline = $false)]
- [System.String] $RepoRootDir = $env:RepoRootDir,
-
- [Parameter(Mandatory = $false, ValueFromPipeline = $false)]
- [System.Int64] $PullRequest = 0,
-
- [Parameter(Mandatory = $false, ValueFromPipeline = $false)]
- [System.String] $RepoOwner = "",
-
- [Parameter(Mandatory = $false, ValueFromPipeline = $false)]
- [System.String] $RepoName = "",
-
- [Parameter(Mandatory = $false, ValueFromPipeline = $false)]
- [System.Int32] $RangeStart = $env:rangestart,
-
- [Parameter(Mandatory = $false, ValueFromPipeline = $false)]
- [System.Int32] $RangeEnd = $env:rangeend
-)
-
-$Global:statusOutput = @()
-
-Write-Host "Gathering solutions and projects... (v1.8)"
-
-if ($PullRequest -ne 0) {
- Write-Host "Running `"LocateProjects `"$RepoRootDir`" --pullrequest $PullRequest --owner $RepoOwner --repo $RepoName`""
- $output = Invoke-Expression "LocateProjects `"$RepoRootDir`" --pullrequest $PullRequest --owner $RepoOwner --repo $RepoName"
-}
-else {
- Write-Host "Running `"LocateProjects `"$RepoRootDir`""
- $output = Invoke-Expression "LocateProjects `"$RepoRootDir`""
-}
-
-if ($LASTEXITCODE -ne 0)
-{
- $output
- throw "Error on running LocateProjects"
-}
-
-function New-Result($inputFile, $projectFile, $exitcode, $outputText, $settingsJson)
-{
- $info = @{}
-
- $info.InputFile = $inputFile
- $info.ProjectFile = $projectFile
- $info.ExitCode = $exitcode
- $info.Output = $outputText
- $info.Settings = $settingsJson
-
- $object = New-Object -TypeName PSObject -Prop $info
- $Global:statusOutput += $object
-}
-
-$workingSet = $output
-
-if (($RangeStart -ne 0) -and ($RangeEnd -ne 0)){
- $workingSet = $output[$RangeStart..$RangeEnd]
-}
-
-# Log working set items prior to filtering
-$workingSet | Write-Host
-
-# Remove duplicated projects and skip snippets files from being processed
-$projects = @()
-$workingSetTemp = @()
-
-foreach ($item in $workingSet) {
- $data = $item.Split('|')
- if ($projects.Contains($data[2].Trim()) -or $data[1].EndsWith("snippets.5000.json")) {
- continue
- }
- if ($data[2].Trim() -ne "") {
- $projects += $data[2].Trim()
- }
- $workingSetTemp += $item
-}
-
-$workingSet = $workingSetTemp
-
-# Process working set
-$counter = 1
-$length = $workingSet.Count
-$thisExitCode = 0
-
-$ErrorActionPreference = "Continue"
-
-foreach ($item in $workingSet) {
- try {
- Write-Host "$counter/$length :: $Item"
-
- $data = $item.Split('|')
-
- # Project found, build it
- if ([int]$data[0] -eq 0) {
- $projectFile = Resolve-Path "$RepoRootDir\$($data[2])"
- $configFile = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($projectFile), "snippets.5000.json")
- $settings = $null
-
- # Create the default build command
- "dotnet build `"$projectFile`"" | Out-File ".\run.bat"
-
- # Check for config file
- if ([System.IO.File]::Exists($configFile) -eq $true) {
- Write-Host "- Config file found"
-
- $settings = $configFile | Get-ChildItem | Get-Content | ConvertFrom-Json
-
- if ($settings.host -eq "visualstudio") {
- Write-Host "- Using visual studio as build host"
-
- # Create the visual studio build command
- "CALL `"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat`"`n" +
- "nuget.exe restore `"$projectFile`"`n" +
- "msbuild.exe `"$projectFile`" -restore:True" `
- | Out-File ".\run.bat"
- }
- elseif ($settings.host -eq "custom") {
- Write-Host "- Using custom build host: $($settings.command)"
-
- $ExecutionContext.InvokeCommand.ExpandString($settings.command) | Out-File ".\run.bat"
- }
- elseif ($settings.host -eq "dotnet") {
- Write-Host "- Using dotnet build host"
-
- "dotnet build `"$projectFile`"" | Out-File ".\run.bat"
- }
- else {
- throw "snippets.5000.json file isn't valid."
- }
- }
-
- Write-Host "run.bat contents: "
- Get-Content .\run.bat | Write-Host
- Write-Host
-
- $thisExitCode = 0
-
- Invoke-Expression ".\run.bat" | Out-String | Tee-Object -Variable "result"
-
- if ($LASTEXITCODE -ne 0) {
- $thisExitCode = 4
- }
-
- New-Result $data[1] $projectFile $thisExitCode $result $settings
- }
-
- # No project found
- else
- {
- $settings = $null
- $filePath = Resolve-Path "$RepoRootDir\$($data[1])"
-
- # Hunt for snippets config file
- do {
-
- $configFile = [System.IO.Path]::Combine($filePath, "snippets.5000.json")
-
- if ([System.IO.File]::Exists($configFile) -eq $true) {
-
- $settings = $configFile | Get-ChildItem | Get-Content | ConvertFrom-Json
- Write-Host "Loading settings for errors found by LocateProjects: $configFile"
- break
- }
-
- # go back one folder
- $filePath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($filePath, "..\"))
- } until ([System.Linq.Enumerable]::Count($filePath, [Func[Char, Boolean]] { param($x) $x -eq '\' }) -eq 1)
-
- if ($settings -eq $null) {
- Write-Host "No settings file found for LocateProjects reported error"
- }
-
- # Process each error
- if ([int]$data[0] -eq 1) {
- New-Result $data[1] "" 1 "ERROR: 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." $settings
-
- $thisExitCode = 1
- }
-
- # Too many projects found
- elseif ([int]$data[0] -eq 2) {
- New-Result $data[1] $data[2] 2 "ERROR: Too many projects found. A single project or solution must exist in this directory or one of the parent directories." $settings
-
- $thisExitCode = 2
- }
-
- # Solution found, but no project
- elseif ([int]$data[0] -eq 3) {
- New-Result $data[1] $data[2] 2 "ERROR: Solution found, but missing project. A project is required to compile this code." $settings
- $thisExitCode = 3
- }
-
- }
-
- }
- catch {
- New-Result $data[1] $projectFile 1000 "ERROR: $($_.Exception)" $null
- $thisExitCode = 4
- Write-Host $_.Exception.Message -Foreground "Red"
- Write-Host $_.ScriptStackTrace -Foreground "DarkGray"
- }
-
- $counter++
-}
-
-$resultItems = $Global:statusOutput | Select-Object InputFile, ProjectFile, ExitCode, Output, Settings
-
-# Add our output type
-$typeResult = @"
-public class ResultItem
-{
- public string ProjectFile;
- public string InputFile;
- public int ExitCode;
- public string BuildOutput;
- public object Settings;
- public MSBuildError[] Errors;
- public int ErrorCount;
-
- public class MSBuildError
- {
- public string Line;
- public string Error;
- }
-}
-"@
-Add-Type $typeResult
-
-$transformedItems = $resultItems | ForEach-Object { New-Object ResultItem -Property @{
- ProjectFile = $_.ProjectFile.Path;
- InputFile = $_.InputFile;
- ExitCode = $_.ExitCode;
- BuildOutput = $_.Output;
- Settings = $_.Settings;
- Errors = @();
- ErrorCount = 0;
- } }
-
-# Transform the build output to break it down into MSBuild result entries
-foreach ($item in $transformedItems) {
- $list = @()
-
- # Clean
- if ($item.ExitCode -eq 0) {
- #$list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = $item.BuildOutput; Error = $item.BuildOutput }
- }
- # No project found
- # Too many projects found
- # Solution found, but no project
- elseif ($item.ExitCode -ne 4) {
- $list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = $item.BuildOutput; Error = $item.BuildOutput }
- $item.ErrorCount = 1
- }
-
- # Actual build error found
- else {
- $errorInfo = $item.BuildOutput -Split [System.Environment]::NewLine |
- Select-String ": (?:Solution file error|error) ([^:]*)" | `
- Select-Object Line -ExpandProperty Matches | `
- Select-Object -Property @{Name = 'Line'; Expression = {$_.Line.Trim()}}, Groups | `
- Sort-Object Line | Get-Unique -AsString
- $item.ErrorCount = $errorInfo.Count
- foreach ($err in $errorInfo) {
- $list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = $err.Line; Error = $err.Groups[1].Value }
- }
-
- # Error count of 0 here means that no error was detected from build results, but there was still a failure of some kind
- if ($item.ErrorCount -eq 0) {
- $list += New-Object -TypeName "ResultItem+MSBuildError" -Property @{ Line = "Unknown error occurred. Check log and build output."; Error = "4" }
- $item.ErrorCount = 1
- }
- }
-
- # Set build errors
- $item.Errors = $list
-
-}
-
-$transformedItems | ConvertTo-Json -Depth 4 | Out-File 'output.json'
-
-exit 0
-
-
-# Sample snippets.5000.json file
-<#
-{
- "host": "visualstudio",
- "expectederrors": [
- {
- "file": "samples/snippets/csharp/VS_Snippets_VBCSharp/csprogguideindexedproperties/cs/Program.cs",
- "line": 5,
- "column": 25,
- "error": "CS0234"
- }
- ]
-}
-
-#>
diff --git a/snippets5000/Out-GithubActionStatus.ps1 b/snippets5000/Out-GithubActionStatus.ps1
deleted file mode 100644
index b116a856..00000000
--- a/snippets5000/Out-GithubActionStatus.ps1
+++ /dev/null
@@ -1,79 +0,0 @@
-<#
-
-.SYNOPSIS
- Reads the output.json file and outputs status to GitHub Actions
-
-.DESCRIPTION
- Reads the output.json file and outputs status to GitHub Actions
-
-.INPUTS
- None
-
-.OUTPUTS
- None
-
-.NOTES
- Version: 1.2
- Author: adegeo@microsoft.com
- Creation Date: 06/24/2020
- Update Date: 03/10/2022
- Purpose/Change: Support ignoring known errors.
-#>
-
-[CmdletBinding()]
-Param(
-)
-
-$json = Get-Content output.json | ConvertFrom-Json
-
-$errors = $json | Where-Object ErrorCount -ne 0 | Select-Object InputFile, Settings -ExpandProperty Errors | Select-Object InputFile, Settings, Error, Line
-
-# Exit if no error entries were found
-$count = $errors.Count
-
-if ($count -eq 0) {
- Write-Host "All builds passed"
- exit 0
-}
-
-Write-Host "Total errors: $count"
-
-foreach ($er in $errors) {
-
- $skipError = $false
-
- $lineColMatch = $er.Line | Select-String "(^.*)\((\d*),(\d*)\)" | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Groups
- $errorFile = $er.InputFile
- $errorLineNumber = 0
- $errorColNumber = 0
-
- if ($lineColMatch.Count -eq 4) {
- $errorFile = $lineColMatch[1].Value.Replace("D:\a\$($env:repo)\$($env:repo)\", "").Replace("\", "/")
- $errorLineNumber = $lineColMatch[2].Value
- $errorColNumber = $lineColMatch[3].Value
- }
-
- # Check if there are any errors that should be skipped because they're known failures
- foreach ($expectedError in $er.Settings.expectederrors) {
- if (($expectedError.file -eq $errorFile) -and ($expectedError.error -eq $er.error)) {
- Write-Host "Skipping error:`n- File: $errorFile`n- Error: $($er.error)"
- $skipError = $true
- break
- }
- }
-
- if ($skipError -eq $false) {
- Write-Host "::error file=$errorFile,line=$errorLineNumber,col=$errorColNumber::$($er.Line)"
- }
- else {
- $count -= 1
- }
-}
-
-Write-Host "Errors after skips: $count"
-
-if ($count -eq 0) {
- exit 0
-}
-
-exit 1
diff --git a/snippets5000/Snippets5000/Program.cs b/snippets5000/Snippets5000/Program.cs
index 327ed698..87679744 100644
--- a/snippets5000/Snippets5000/Program.cs
+++ b/snippets5000/Snippets5000/Program.cs
@@ -1,9 +1,7 @@
๏ปฟusing System.CommandLine;
-using System.CommandLine.Parsing;
using System.Diagnostics;
using System.Text.Json;
using System.Text.RegularExpressions;
-using DotNet.DocsTools.Utility;
using DotNetDocs.Tools.Utility;
using static Snippets5000.SnippetsConfigFile;
using Log = DotNet.DocsTools.Utility.EchoLogging;
@@ -43,86 +41,193 @@ class Program
/// 0 on success. Otherwise, a non-zero error code.
static async Task Main(string[] args)
{
- var (sourcepath, pullrequest, owner, repo, dryrunTestId, dryrunTestDataFile) = ParseArguments(args);
+ // Shared option for all commands
+ Option sourcePathOption = new("--sourcepath")
+ {
+ Description = "The directory containing the local source tree.",
+ Required = true
+ };
- int exitCode = EXITCODE_GOOD;
- string appStartupFolder = Directory.GetCurrentDirectory();
+ // Root command options (PR mode - default)
+ Option pullrequestOption = new("--pullrequest")
+ {
+ Description = "The number of the pull request being built.",
+ Required = true
+ };
+ Option ownerOption = new("--owner")
+ {
+ Description = "The owner organization of the repository.",
+ Required = true
+ };
+ Option repoOption = new("--repo")
+ {
+ Description = "The name of the repository.",
+ Required = true
+ };
- if ((pullrequest.HasValue) &&
- !string.IsNullOrEmpty(owner) &&
- !string.IsNullOrEmpty(repo))
+ RootCommand rootCommand = new("Snippets5000 CI build application.")
{
- List projects;
+ sourcePathOption,
+ pullrequestOption,
+ ownerOption,
+ repoOption
+ };
- // Normal github PR
- if (string.IsNullOrEmpty(dryrunTestId))
- {
- var key = CommandLineUtility.GetEnvVariable("GitHubKey", "You must store your GitHub key in the 'GitHubKey' environment variable", null);
+ rootCommand.SetAction(async (parseResult, cancellationToken) =>
+ {
+ var sourcepath = parseResult.GetValue(sourcePathOption)!;
+ var pullrequest = parseResult.GetValue(pullrequestOption);
+ var owner = parseResult.GetValue(ownerOption)!;
+ var repo = parseResult.GetValue(repoOption)!;
- List localResults = new();
- await foreach (var item in new PullRequestProcessor(owner, repo, pullrequest.Value, sourcepath).GenerateBuildList(key))
- localResults.Add(item);
+ Console.WriteLine($"Processing source path: {sourcepath}");
+ Console.WriteLine($"Processing PR #{pullrequest} from {owner}/{repo}");
- projects = localResults;
- }
+ return await RunPullRequestAsync(sourcepath, pullrequest, owner, repo);
+ });
- // NOT a normal github PR and instead is a test
- else if (string.IsNullOrEmpty(dryrunTestDataFile))
- throw new InvalidOperationException($"{nameof(dryrunTestDataFile)}: The dryrun Test DataFile must be set");
- else
- projects = new TestingProjectList(dryrunTestId, dryrunTestDataFile, sourcepath).GenerateBuildList().ToList();
+ // Dryrun subcommand - simulates a PR using local test data
+ Option testIdOption = new("--test-id")
+ {
+ Description = "The test id from the test data file to simulate a pull request.",
+ Required = true
+ };
+ Option testDataFileOption = new("--test-data-file")
+ {
+ Description = "The json file defining all the tests that can be referenced by test-id. Usually data.json.",
+ Required = true
+ };
- Log.Write(0, $"{projects.Count} items found.");
- Log.Write(0, "\r\nOutput all items found, grouped by status...");
+ Command dryrunCommand = new("dryrun", "Simulate a pull request using local test data.")
+ {
+ sourcePathOption,
+ testIdOption,
+ testDataFileOption
+ };
- // Start processing all of the discovered projects
- ProcessDiscoveredProjects(projects, out List transformedProjects, out string[] projectsToCompile);
+ dryrunCommand.SetAction(async (parseResult, cancellationToken) =>
+ {
+ var sourcepath = parseResult.GetValue(sourcePathOption)!;
+ var testId = parseResult.GetValue(testIdOption)!;
+ var testDataFile = parseResult.GetValue(testDataFileOption)!;
- // Compile each project
- await CompileProjects(sourcepath, projectsToCompile, transformedProjects);
+ Console.WriteLine($"Processing source path: {sourcepath}");
+ Console.WriteLine($"Running dryrun test: {testId}");
- // Clear any known errors from the failed projects
- ProcessFailedProjects(repo, transformedProjects.Where(p => p.RunExitCode != 0));
+ return await RunDryrunAsync(sourcepath, testId, testDataFile);
+ });
- // Final results. List the projects/files that have failed
- bool first = false;
- var finalFailedProjects = transformedProjects.Where(p => !p.RunConsideredGood).ToArray();
- foreach (var item in finalFailedProjects)
- {
- if (!first)
- {
- Log.Write(0, "\r\n๐ญ Compile targets with unresolved issues:");
- first = true;
- }
- Log.Write(2, item.RunTargetFile);
- exitCode = EXITCODE_BAD;
- }
+ rootCommand.Subcommands.Add(dryrunCommand);
- // Generate output file
- if (finalFailedProjects.Length != 0)
- {
- Directory.SetCurrentDirectory(appStartupFolder);
- JsonSerializerOptions options = new JsonSerializerOptions() { WriteIndented = true, ReadCommentHandling = JsonCommentHandling.Skip };
- using FileStream file = File.Open("output.json", FileMode.Create);
- JsonSerializer.Serialize(file, finalFailedProjects, options);
- }
+ // Build-all subcommand - builds the entire repository
+ Command buildAllCommand = new("build-all", "Build all projects in the repository.")
+ {
+ sourcePathOption
+ };
+
+ buildAllCommand.SetAction(async (parseResult, cancellationToken) =>
+ {
+ var sourcepath = parseResult.GetValue(sourcePathOption)!;
+
+ Console.WriteLine($"Processing source path: {sourcepath}");
+ Console.WriteLine("Building all projects in repository...");
+
+ return await RunBuildAllAsync(sourcepath);
+ });
+
+ rootCommand.Subcommands.Add(buildAllCommand);
- // There were no errors, log it!
- if (exitCode == 0)
- Log.Write(0, "\r\n๐ All builds passing! ๐");
+ return await rootCommand.Parse(args).InvokeAsync();
+ }
+
+ ///
+ /// Process a GitHub pull request.
+ ///
+ private static async Task RunPullRequestAsync(string sourcepath, int pullrequest, string owner, string repo)
+ {
+ var key = CommandLineUtility.GetEnvVariable("GitHubKey", "You must store your GitHub key in the 'GitHubKey' environment variable", null);
+
+ List projects = [];
+ await foreach (var item in new PullRequestProcessor(owner, repo, pullrequest, sourcepath).GenerateBuildList(key))
+ projects.Add(item);
+
+ return await ProcessAndCompileProjectsAsync(sourcepath, repo, projects);
+ }
+
+ ///
+ /// Simulate a pull request using local test data.
+ ///
+ private static async Task RunDryrunAsync(string sourcepath, string testId, string testDataFile)
+ {
+ List projects = new TestingProjectList(testId, testDataFile, sourcepath)
+ .GenerateBuildList()
+ .ToList();
- return exitCode;
+ // Use a placeholder repo name for error path processing
+ return await ProcessAndCompileProjectsAsync(sourcepath, "dryrun", projects);
+ }
+
+ ///
+ /// Build all projects in the repository.
+ ///
+ private static Task RunBuildAllAsync(string sourcepath)
+ {
+ // TODO: Implement full build with compile step
+ var fullBuild = new FullBuildProjectList(sourcepath);
+ foreach (var path in fullBuild.GenerateBuildList())
+ Log.Write(0, path);
+
+ return Task.FromResult(EXITCODE_GOOD);
+ }
+
+ ///
+ /// Shared logic for processing and compiling discovered projects.
+ ///
+ private static async Task ProcessAndCompileProjectsAsync(string sourcepath, string repo, List projects)
+ {
+ int exitCode = EXITCODE_GOOD;
+ string appStartupFolder = Directory.GetCurrentDirectory();
+
+ Log.Write(0, $"{projects.Count} items found.");
+ Log.Write(0, "\r\nOutput all items found, grouped by status...");
+
+ // Start processing all of the discovered projects
+ ProcessDiscoveredProjects(projects, out List transformedProjects, out string[] projectsToCompile);
+
+ // Compile each project
+ await CompileProjects(sourcepath, projectsToCompile, transformedProjects);
+
+ // Clear any known errors from the failed projects
+ ProcessFailedProjects(repo, transformedProjects.Where(p => p.RunExitCode != 0));
+
+ // Final results. List the projects/files that have failed
+ bool first = false;
+ var finalFailedProjects = transformedProjects.Where(p => !p.RunConsideredGood).ToArray();
+ foreach (var item in finalFailedProjects)
+ {
+ if (!first)
+ {
+ Log.Write(0, "\r\n๐ญ Compile targets with unresolved issues:");
+ first = true;
+ }
+ Log.Write(2, item.RunTargetFile);
+ exitCode = EXITCODE_BAD;
}
- // TODO: building the whole repository
- else
+ // Generate output file
+ if (finalFailedProjects.Length != 0)
{
- var fullBuild = new FullBuildProjectList(sourcepath);
- foreach (var path in fullBuild.GenerateBuildList())
- Log.Write(0, path);
+ Directory.SetCurrentDirectory(appStartupFolder);
+ JsonSerializerOptions options = new() { WriteIndented = true, ReadCommentHandling = JsonCommentHandling.Skip };
+ using FileStream file = File.Open("output.json", FileMode.Create);
+ JsonSerializer.Serialize(file, finalFailedProjects, options);
}
- return EXITCODE_GOOD;
+ // There were no errors, log it!
+ if (exitCode == 0)
+ Log.Write(0, "\r\n๐ All builds passing! ๐");
+
+ return exitCode;
}
// Takes the discovery results from scanning the files in the PR and checks their status. The projects
@@ -196,7 +301,7 @@ private static async Task CompileProjects(string sourcePath, string[] projectsTo
foreach (var item in projectsToCompile)
{
expansionVariables.Clear();
-
+
Directory.SetCurrentDirectory(sourcePath);
Log.CreateGroup($"Compile: {counter}/{projectsToCompile.Length} {item}");
@@ -458,61 +563,4 @@ private static void ProcessFailedProjects(string repo, IEnumerable sourcePathOption = new("--sourcepath")
- {
- Description = "The directory containing the local source tree."
- };
- Option pullrequestOption = new("--pullrequest")
- {
- Description = "If available, the number of the pull request being built.",
- DefaultValueFactory = parseResult => null
- };
- Option ownerOption = new("--owner")
- {
- Description = "If available, the owner organization of the repository.",
- DefaultValueFactory = parseResult => null
- };
- Option repoOption = new("--repo")
- {
- Description = "If available, the name of the repository.",
- DefaultValueFactory = parseResult => null
- };
- Option dryrunTestIdOption = new("--dryrun-test-id")
- {
- Description = "The test id from data.json to simulate a pull request.",
- DefaultValueFactory = parseResult => null
- };
- Option dryrunTestDataFileOption = new("--dryrun-test-data-file")
- {
- Description = "The json file defining all the tests that can be referenced by `dryrunTestId`. Usually data.json.",
- DefaultValueFactory = parseResult => null
- };
- RootCommand rootCommand = new("Snippets5000 CI build application.");
-
- rootCommand.Options.Add(sourcePathOption);
- rootCommand.Options.Add(pullrequestOption);
- rootCommand.Options.Add(ownerOption);
- rootCommand.Options.Add(repoOption);
- rootCommand.Options.Add(dryrunTestIdOption);
- rootCommand.Options.Add(dryrunTestDataFileOption);
-
- ParseResult result = rootCommand.Parse(args);
- foreach (ParseError parseError in result.Errors)
- {
- Console.Error.WriteLine(parseError.Message);
- }
- if (result.Errors.Count > 0)
- {
- throw new InvalidOperationException("Invalid command line.");
- }
- var sourcepath = result.GetValue(sourcePathOption) ?? throw new InvalidOperationException("organization is null");
- var pullrequest = result.GetValue(pullrequestOption);
- var owner = result.GetValue(ownerOption);
- var repo = result.GetValue(repoOption);
- var dryrunTestId = result.GetValue(dryrunTestIdOption);
- var dryrunTestDataFile = result.GetValue(dryrunTestDataFileOption);
- return (sourcepath, pullrequest, owner, repo, dryrunTestId, dryrunTestDataFile);
- }
}
diff --git a/snippets5000/Snippets5000/Properties/launchSettings.json b/snippets5000/Snippets5000/Properties/launchSettings.json
index 2bd80190..683f10f3 100644
--- a/snippets5000/Snippets5000/Properties/launchSettings.json
+++ b/snippets5000/Snippets5000/Properties/launchSettings.json
@@ -2,22 +2,22 @@
"profiles": {
"Test via GitHub": {
"commandName": "Project",
- "commandLineArgs": "--sourcepath C:\\Users\\adegeo\\code\\dotnet-api-docs --owner dotnet --repo dotnet-api-docs --pullrequest 11502",
+ "commandLineArgs": "--sourcepath C:\\Users\\adegeo\\code\\dotnet\\dotnet-docs --owner dotnet --repo docs --pullrequest 51928",
"environmentVariables": {
- "ExtensionsProjs": ".csproj;.fsproj;.vbproj;.vcxproj;.sln;.slnx",
+ "ExtensionsProjs": ".csproj;.fsproj;.vbproj;.vcxproj;.sln;.slnx",
"ExtensionsCodeTriggers": ".cs;.vb;.fs;.cpp;.h;.xaml;.razor;.cshtml;.vbhtml",
"FileTriggers": "global.json;snippets.5000.json",
- "VS_DEVCMD": "C:\\Program Files\\Microsoft Visual Studio\\2026\\Community\\Common7\\Tools\\VsDevCmd.bat"
+ "VS_DEVCMD": "C:\\Program Files\\Microsoft Visual Studio\\2026\\Community\\Common7\\Tools\\VsDevCmd.bat"
}
},
"Test via Local Tests": {
"commandName": "Project",
- "commandLineArgs": "--dryrun-test-id \"Edit - Solution found, no project\" --sourcepath C:\\Users\\adegeo\\code\\dotnet\\docs-tools\\snippets5000\\PullRequestSimulations --owner nah --repo nah --pullrequest 1 --dryrun-test-data-file C:\\Users\\adegeo\\code\\dotnet\\docs-tools\\snippets5000\\PullRequestSimulations\\data.json",
+ "commandLineArgs": "dryrun --test-id \"Edit - Solution found, no project\" --sourcepath C:\\Users\\adegeo\\code\\dotnet\\docs-tools\\snippets5000\\PullRequestSimulations --test-data-file C:\\Users\\adegeo\\code\\dotnet\\docs-tools\\snippets5000\\PullRequestSimulations\\data.json",
"environmentVariables": {
- "ExtensionsProjs": ".csproj;.fsproj;.vbproj;.vcxproj;.sln;slnx",
+ "ExtensionsProjs": ".csproj;.fsproj;.vbproj;.vcxproj;.sln;slnx",
"ExtensionsCodeTriggers": ".cs;.vb;.fs;.cpp;.h;.xaml;.razor;.cshtml;.vbhtml",
"FileTriggers": "global.json;snippets.5000.json",
- "VS_DEVCMD": "C:\\Program Files\\Microsoft Visual Studio\\2026\\Community\\Common7\\Tools\\VsDevCmd.bat"
+ "VS_DEVCMD": "C:\\Program Files\\Microsoft Visual Studio\\2026\\Community\\Common7\\Tools\\VsDevCmd.bat"
}
}
}
diff --git a/snippets5000/Snippets5000/PullRequestProcessor.cs b/snippets5000/Snippets5000/PullRequestProcessor.cs
index 51c2b4a4..9895eb53 100644
--- a/snippets5000/Snippets5000/PullRequestProcessor.cs
+++ b/snippets5000/Snippets5000/PullRequestProcessor.cs
@@ -72,7 +72,7 @@ private async IAsyncEnumerable FindAllSolutionsAndProjects(stri
static internal DiscoveryResult? GenerateItemResult(string rootDir, string item)
{
// Get components of the file path
- string fullPath = Path.Combine(rootDir, item);
+ string fullPath = Path.GetFullPath(Path.Combine(rootDir, item));
string itemFileName = Path.GetFileName(fullPath);
string itemPath = Path.GetDirectoryName(fullPath)!;