Skip to content

Use simctl --json-output flag to avoid stdout pollution#170

Merged
rmarinho merged 14 commits into
mainfrom
copilot/fix-consolelogger-stdout-pollution
Apr 29, 2026
Merged

Use simctl --json-output flag to avoid stdout pollution#170
rmarinho merged 14 commits into
mainfrom
copilot/fix-consolelogger-stdout-pollution

Conversation

Copilot AI commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Per review feedback, relying on stdout being clean is fragile, and routing ConsoleLogger output to stderr would break MSBuild tasks.

Changes

  • Xamarin.MacDev/SimCtl.cs — Add RunJson(params string[] args) which passes --json --json-output=<tempfile> to xcrun simctl, reads JSON from the temp file, then cleans up. JSON output is never read from stdout.
  • SimulatorService, RuntimeService — Updated to call simctl.RunJson("list", ...) instead of simctl.Run("list", ..., "--json").
  • tests/tests.csproj — Add explicit Microsoft.NET.Test.Sdk package reference and suppress NETSDK1023/NU1504 warnings.
  • Merge conflicts with main resolved.

Copilot AI and others added 3 commits April 22, 2026 17:53
LogInfo, LogWarning, and LogDebug in ConsoleLogger now use
Console.Error.WriteLine (stderr) instead of Console.WriteLine (stdout).
This prevents log messages from polluting structured output (e.g. JSON)
for consumers that capture stdout.

Fixes #2

Agent-Logs-Url: https://github.com/dotnet/macios-devtools/sessions/005240a3-2797-4f5f-865c-c920f0723994

Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/macios-devtools/sessions/005240a3-2797-4f5f-865c-c920f0723994

Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix ConsoleLogger to prevent stdout pollution for JSON output Route ConsoleLogger Info/Warning/Debug to stderr Apr 22, 2026
Copilot AI requested a review from rmarinho April 22, 2026 17:57

@rolfbjarne rolfbjarne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relying on stdout not containing noise is unreliable, because any number of places can print to stdout.

A better solution is to get specific output written to a file instead.

For instance for xcrun simctl list devices --json, pass --json-output /path/to/temporary/file.json as well, and read that file afterwards, instead of relying on stdout.

Also the solution of writing to stderr instead of stdout has a separate problem: some MSBuild tasks will automatically fail if anything is printed to stderr.

@rmarinho

Copy link
Copy Markdown
Member

@copilot can you look at @rolfbjarne comment and use the file route

Copilot AI and others added 3 commits April 23, 2026 10:50
…sed output

Per reviewer feedback: writing to stderr breaks MSBuild tasks. Instead,
add SimCtl.RunToFile() so consumers can capture structured output (JSON)
to a file, isolating it from any stdout noise.

Agent-Logs-Url: https://github.com/dotnet/macios-devtools/sessions/2bbfd1eb-7c88-49ed-8bb9-6e335c369cee

Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>

Copilot AI commented Apr 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot can you look at @rolfbjarne comment and use the file route

Reverted the ConsoleLogger stderr changes and added SimCtl.RunToFile(string outputPath, params string[] args) in a4a1b50. This lets downstream consumers capture structured output (e.g. JSON) to a file, isolating it from any stdout noise. The existing Run() method is unchanged for backward compatibility.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 2kmvsblobprodcus39.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/EAFBC6E33F4372D62A064209AA87BA2F/missingpackages_workingdir --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/46EB19D8E6D150879BD3367A72FC2FBC/missingpackages_workingdir --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 4myvsblobprodcus32.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/E19C1E824C36607F03B2825D19A987A4/missingpackages_workingdir --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 51yvsblobprodcus36.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet build Xamarin.MacDev/Xamarin.MacDev.csproj (dns block)
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/macios-devtools/macios-devtools/Xamarin.MacDev.sln --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true (dns block)
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/macios-devtools/macios-devtools/tests/tests.csproj --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true (dns block)
  • 7k6vsblobprodcus337.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet build Xamarin.MacDev/Xamarin.MacDev.csproj (dns block)
  • kmuvsblobprodcus389.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/1381A7934071EB35EC16B755076CAB69/missingpackages_workingdir --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • kxqvsblobprodcus376.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/047D30272EE2B8A118836103AA894C89/missingpackages_workingdir --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • sc4vsblobprodcus331.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/0A4E58E778FC4449F6B50463EA93DD88/missingpackages_workingdir --packages /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-05016c733fb84ab0/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • securitytools.pkgs.visualstudio.com
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Route ConsoleLogger Info/Warning/Debug to stderr Add SimCtl.RunToFile for file-based structured output capture Apr 23, 2026
@rmarinho rmarinho requested a review from rolfbjarne April 23, 2026 13:26
Comment thread Xamarin.MacDev/SimCtl.cs Outdated
Per reviewer feedback, use xcrun simctl's native --json-output=<file>
flag to write structured JSON output directly to a temp file, instead
of capturing stdout and writing it ourselves.

- Revert RunToFile/RunCore approach back to original Run() method
- Add RunJson() that passes --json --json-output=<tempPath> to simctl
  and reads the result from the temp file
- Update SimulatorService, RuntimeService, and tests to use RunJson()

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rmarinho

Copy link
Copy Markdown
Member

Updated per @rolfbjarne's feedback: now using xcrun simctl's native --json-output=<file> flag instead of capturing stdout.

The new RunJson() method passes --json --json-output=<tempPath> to simctl, reads the result from the temp file, then cleans up. Callers (SimulatorService, RuntimeService) updated to use RunJson("list", ...) instead of Run("list", ..., "--json"). Stdout is never used for structured data.

rmarinho and others added 4 commits April 24, 2026 09:35
…ter to 4.6.0

NUnit3TestAdapter 5.0.0 pulled in Microsoft.Testing.Platform which brought
a broken transitive dependency chain (ApplicationInsights, Telemetry DLLs
not copied to output). Downgrade to 4.6.0 to avoid the Testing Platform
migration issues.

Add Microsoft.NET.Test.Sdk (implicitly referenced by .NET SDK) and
CopyLocalLockFileAssemblies to ensure all test dependencies are resolved
at runtime. Remove NUnit.ConsoleRunner (unused with dotnet test).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use Path.GetTempFileName() instead of GetRandomFileName() to
  atomically reserve the temp file path (avoids race condition).
- Check Run() return value before reading the file, so simctl
  failures surface the correct error instead of a misleading
  'no JSON output file' message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The walk-up logic stopped at artifacts/bin/tests/ (first dir named
'tests') instead of the source tests/ directory. Fix by requiring
tests.csproj to exist as a sentinel, disambiguating the source
directory from the Arcade SDK output layout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The explicit PackageReference is needed for testhost.runtimeconfig.json,
but .NET SDK 10.0+ implicitly references it causing duplicate errors.
Suppress NETSDK1023 and NU1504 in the test project.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rmarinho rmarinho force-pushed the copilot/fix-consolelogger-stdout-pollution branch from 9e0781d to a4864e8 Compare April 24, 2026 09:24
@rmarinho rmarinho marked this pull request as ready for review April 24, 2026 09:39
@rmarinho rmarinho requested a review from rolfbjarne April 24, 2026 09:39

@rolfbjarne rolfbjarne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the PR title & description seem out of date.

Comment thread eng/Versions.props Outdated
@rmarinho rmarinho changed the title Add SimCtl.RunToFile for file-based structured output capture Use simctl --json-output flag to avoid stdout pollution Apr 27, 2026
… Microsoft.NET.Test.Sdk

Tested: build succeeds and 118/119 tests pass (1 skipped) with NUnit3TestAdapter
5.0.0 + Microsoft.NET.Test.Sdk 17.12.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rmarinho rmarinho requested a review from rolfbjarne April 27, 2026 15:57
@rmarinho

Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

Resolve conflict in tests/TestHelper.cs by taking main's IsTestsProjectDir helper approach.

Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>

Copilot AI commented Apr 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Resolved the merge conflict in tests/TestHelper.cs by taking main's IsTestsProjectDir helper method approach. Merge commit: fba1508.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ConsoleLogger writes Info/Warning to stdout, polluting JSON output of consumers

3 participants