diff --git a/changelog.d/unreleased/3631.fixed.md b/changelog.d/unreleased/3631.fixed.md new file mode 100644 index 0000000000..5c49b657ea --- /dev/null +++ b/changelog.d/unreleased/3631.fixed.md @@ -0,0 +1,16 @@ +--- +category: fixed +issues: + - 3631 +affected: + - tools/CodeIndex.PackageNormalize/PackageNormalizeCli.cs + - tests/CodeIndex.Tests/ReleaseWorkflowTests.cs +--- + +## English + +- **Package normalize dry-run tests no longer capture unrelated stderr (#3631)** — release workflow tests now invoke the package normalizer with dedicated output writers so MCP telemetry from other test activity cannot make dry-run stderr assertions flaky. + +## 日本語 + +- **Package normalize の dry-run テストが無関係な stderr を捕捉しないようになりました (#3631)** — release workflow テストは package normalizer を専用の出力 writer で実行するため、他のテスト活動からの MCP telemetry が dry-run の stderr アサーションを不安定にしなくなりました。 diff --git a/tests/CodeIndex.Tests/ReleaseWorkflowTests.cs b/tests/CodeIndex.Tests/ReleaseWorkflowTests.cs index fea0d42412..9e682267c4 100644 --- a/tests/CodeIndex.Tests/ReleaseWorkflowTests.cs +++ b/tests/CodeIndex.Tests/ReleaseWorkflowTests.cs @@ -237,8 +237,7 @@ public void PackageNormalizeCli_DryRunDoesNotRewritePackage() CreateMinimalNuGetPackage(packagePath, "random.psmdcp"); var beforeHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(packagePath))); - var (exitCode, stdout, stderr) = ConsoleCapture.Capture(() => - PackageNormalizeCli.Run(["--dry-run", "--summary", packagePath])); + var (exitCode, stdout, stderr) = RunPackageNormalizeCli(["--dry-run", "--summary", packagePath]); var afterHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(packagePath))); Assert.Equal(0, exitCode); @@ -268,8 +267,7 @@ public void PackageNormalizeCli_JsonContinueOnErrorReportsAggregateSummary() var missingPackagePath = Path.Combine(projectRoot, "missing.nupkg"); CreateMinimalNuGetPackage(packagePath, "random.psmdcp"); - var (exitCode, stdout, stderr) = ConsoleCapture.Capture(() => - PackageNormalizeCli.Run(["--dry-run", "--json", "--continue-on-error", missingPackagePath, packagePath])); + var (exitCode, stdout, stderr) = RunPackageNormalizeCli(["--dry-run", "--json", "--continue-on-error", missingPackagePath, packagePath]); Assert.Equal(1, exitCode); Assert.Empty(stderr); @@ -303,7 +301,7 @@ public void PackageNormalizeCli_RejectsTooManyPackageArguments() .Select(index => $"package-{index}.nupkg") .ToArray(); - var (exitCode, stdout, stderr) = ConsoleCapture.Capture(() => PackageNormalizeCli.Run(args)); + var (exitCode, stdout, stderr) = RunPackageNormalizeCli(args); Assert.Equal(1, exitCode); Assert.Empty(stdout); @@ -318,8 +316,7 @@ public void PackageNormalizeCli_JsonReportsBoundedFriendlyFailure() { var missingPackagePath = Path.Combine(projectRoot, "missing.nupkg"); - var (exitCode, stdout, stderr) = ConsoleCapture.Capture(() => - PackageNormalizeCli.Run(["--json", missingPackagePath])); + var (exitCode, stdout, stderr) = RunPackageNormalizeCli(["--json", missingPackagePath]); Assert.Equal(1, exitCode); Assert.Empty(stderr); @@ -350,8 +347,7 @@ public void PackageNormalizeCli_JsonBoundsZipEntryDiagnostics() ("package/services/metadata/core-properties/random.psmdcp", ""), (longEntryName, "payload")); - var (exitCode, stdout, stderr) = ConsoleCapture.Capture(() => - PackageNormalizeCli.Run(["--json", packagePath])); + var (exitCode, stdout, stderr) = RunPackageNormalizeCli(["--json", packagePath]); Assert.Equal(1, exitCode); Assert.Empty(stderr); @@ -738,6 +734,14 @@ private static string GetRepositoryRoot() throw new InvalidOperationException("Could not locate repository root / リポジトリルートを特定できませんでした"); } + private static (int ExitCode, string Stdout, string Stderr) RunPackageNormalizeCli(string[] args) + { + using var stdout = new StringWriter(); + using var stderr = new StringWriter(); + var exitCode = PackageNormalizeCli.Run(args, stdout, stderr); + return (exitCode, stdout.ToString(), stderr.ToString()); + } + private static void CreateMinimalNuGetPackage(string packagePath, string corePropertiesFileName) { var corePropertiesPath = $"package/services/metadata/core-properties/{corePropertiesFileName}"; diff --git a/tools/CodeIndex.PackageNormalize/PackageNormalizeCli.cs b/tools/CodeIndex.PackageNormalize/PackageNormalizeCli.cs index 55b77abe0e..c56f3e20dc 100644 --- a/tools/CodeIndex.PackageNormalize/PackageNormalizeCli.cs +++ b/tools/CodeIndex.PackageNormalize/PackageNormalizeCli.cs @@ -6,18 +6,20 @@ namespace CodeIndex.PackageNormalize; public static class PackageNormalizeCli { - public static int Run(string[] args) + public static int Run(string[] args) => Run(args, Console.Out, Console.Error); + + internal static int Run(string[] args, TextWriter stdout, TextWriter stderr) { if (args.Any(arg => arg is "-h" or "--help")) { - WriteUsage(); + WriteUsage(stderr); return 0; } if (!PackageNormalizeOptions.TryParse(args, out var options, out var parseError)) { - Console.Error.WriteLine($"Error: {parseError}"); - WriteUsage(); + stderr.WriteLine($"Error: {parseError}"); + WriteUsage(stderr); return 1; } @@ -38,14 +40,14 @@ public static int Run(string[] args) summary.Skipped++; results.Add(new PackageNormalizePackageResult(packagePath, "would_normalize", null, warnings)); if (!options.Json) - Console.WriteLine($"Would normalize {packagePath}"); + stdout.WriteLine($"Would normalize {packagePath}"); } else { summary.Unchanged++; results.Add(new PackageNormalizePackageResult(packagePath, "unchanged", null, warnings)); if (!options.Json) - Console.WriteLine($"Unchanged {packagePath}"); + stdout.WriteLine($"Unchanged {packagePath}"); } } else @@ -55,8 +57,8 @@ public static int Run(string[] args) results.Add(new PackageNormalizePackageResult(packagePath, "normalized", null, warnings)); if (!options.Json) { - Console.WriteLine($"Normalized {packagePath}"); - WriteWarnings(warnings); + stdout.WriteLine($"Normalized {packagePath}"); + WriteWarnings(stderr, warnings); } } } @@ -67,8 +69,8 @@ public static int Run(string[] args) results.Add(new PackageNormalizePackageResult(packagePath, "failed", error, warnings)); if (!options.Json) { - Console.Error.WriteLine($"Failed {PackageNormalizeDiagnostics.FormatPath(packagePath)}: {error}"); - WriteWarnings(warnings); + stderr.WriteLine($"Failed {PackageNormalizeDiagnostics.FormatPath(packagePath)}: {error}"); + WriteWarnings(stderr, warnings); } if (!options.ContinueOnError) @@ -78,7 +80,7 @@ public static int Run(string[] args) if (options.Json) { - Console.WriteLine(JsonSerializer.Serialize( + stdout.WriteLine(JsonSerializer.Serialize( new PackageNormalizeJsonResult( options.DryRun, options.ContinueOnError, @@ -92,22 +94,22 @@ public static int Run(string[] args) } else if (options.Summary) { - Console.WriteLine( + stdout.WriteLine( $"Summary: inspected={summary.Inspected} normalized={summary.Normalized} unchanged={summary.Unchanged} failed={summary.Failed} skipped={summary.Skipped}"); } return summary.Failed == 0 ? 0 : 1; } - private static void WriteUsage() + private static void WriteUsage(TextWriter error) { - Console.Error.WriteLine("Usage: dotnet run --project tools/CodeIndex.PackageNormalize -- [--dry-run|--check] [--summary] [--json] [--continue-on-error] [...]"); + error.WriteLine("Usage: dotnet run --project tools/CodeIndex.PackageNormalize -- [--dry-run|--check] [--summary] [--json] [--continue-on-error] [...]"); } - private static void WriteWarnings(IReadOnlyList warnings) + private static void WriteWarnings(TextWriter error, IReadOnlyList warnings) { foreach (var warning in warnings) - Console.Error.WriteLine($"Warning: {warning}"); + error.WriteLine($"Warning: {warning}"); } }