Add ProcessUtils helper and output models for Apple CLI APIs#155
Merged
Add ProcessUtils helper and output models for Apple CLI APIs#155
Conversation
Add ProcessUtils static helper (inspired by dotnet/android-tools) for async process execution with cancellation and stdout/stderr capture. Add output model POCOs in Xamarin.MacDev.Models namespace: - XcodeInfo, SimulatorDeviceInfo, SimulatorRuntimeInfo - CommandLineToolsInfo, EnvironmentCheckResult Update copilot-instructions.md with code style conventions. Closes #153 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace manual Process boilerplate in TryGetSystemXcode with ProcessUtils.Exec, which handles the same stdout/stderr capture and cleanup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace hardcoded /bin/echo, /bin/sh, /bin/sleep paths with platform-aware helpers using RuntimeInformation.IsOSPlatform. On Windows, uses cmd.exe /c for echo/exit and timeout for sleep. Also adds using blocks on StringWriter per coding conventions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename directory, project, and namespace from UnitTests to tests. Update all references in solution, CI pipelines, documentation, embedded resource names, and TestHelper path resolution. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds foundational utilities and model classes for Apple CLI APIs, serving as a dependency for subsequent PRs in the Apple CLI library implementation. It introduces ProcessUtils for external process execution, model POCOs for Apple developer environment data, and refactors the test project structure.
Changes:
- Added ProcessUtils helper class with async/sync process execution methods inspired by dotnet/android-tools
- Added five model classes (XcodeInfo, SimulatorDeviceInfo, SimulatorRuntimeInfo, CommandLineToolsInfo, EnvironmentCheckResult) to represent Apple environment data
- Renamed test project from "UnitTests" to "tests" with corresponding namespace and path updates throughout
- Updated XcodeLocator to use ProcessUtils.Exec instead of manual Process creation
- Added 14 new tests covering ProcessUtils and model classes
Reviewed changes
Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Xamarin.MacDev/ProcessUtils.cs | New static helper class for running external processes with async stdout/stderr capture and cancellation support |
| Xamarin.MacDev/Models/XcodeInfo.cs | New model representing Xcode installation details (path, version, build) |
| Xamarin.MacDev/Models/SimulatorDeviceInfo.cs | New model for simulator device information from xcrun simctl |
| Xamarin.MacDev/Models/SimulatorRuntimeInfo.cs | New model for simulator runtime information (platform, version, availability) |
| Xamarin.MacDev/Models/CommandLineToolsInfo.cs | New model for Xcode Command Line Tools installation status |
| Xamarin.MacDev/Models/EnvironmentCheckResult.cs | New model aggregating environment check results with DeriveStatus() method |
| Xamarin.MacDev/XcodeLocator.cs | Refactored to use ProcessUtils.Exec instead of manual Process creation |
| tests/ProcessUtilsTests.cs | New comprehensive tests for ProcessUtils methods (8 tests) |
| tests/XcodeInfoTests.cs | New tests for XcodeInfo model (2 tests) |
| tests/EnvironmentCheckResultTests.cs | New tests for environment models and status derivation (6 tests) |
| tests/TestHelper.cs | Updated to use "tests" namespace and directory name |
| tests/TestMobileProvisionIndex.cs | Updated namespace from UnitTests to Tests |
| tests/PListObjectTests.cs | Updated namespace and manifest resource stream paths |
| tests/tests.csproj | Renamed from UnitTests.csproj with proper embedded resource configuration |
| Xamarin.MacDev.sln | Updated project reference from UnitTests to tests |
| .github/workflows/ci.yml | Updated test project path |
| azure-pipelines.yaml | Updated test project path |
| .github/copilot-instructions.md | Added code style guidelines, error handling patterns, and testing requirements |
| .github/CSharpExpert.agent.md | Updated test project name reference |
| tests/TestData/PropertyLists/*.plist | Added test data files for plist parsing tests |
- Fix potential deadlock in Exec: read stdout/stderr asynchronously before WaitForExit to prevent buffer blocking - Fix race condition in exit detection: check HasExited after Start() in case process exits before Exited event fires - Replace bare catch with specific Win32Exception and InvalidOperationException catches in TryRunAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Provide TextWriter.Null sink when ProcessStartInfo has redirection enabled but caller passes null writer, preventing NullReferenceException. Catch Win32Exception in process termination helper for platforms where the call may fail with access denied. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
rolfbjarne
requested changes
Feb 27, 2026
- Change ProcessUtils arguments from single string to params string[] to avoid quoting issues. Uses ArgumentList on net5.0+ and a QuoteArguments fallback on netstandard2.0. - Add convenience overloads without CancellationToken for RunAsync and TryRunAsync. - Replace "CLT" abbreviation with "Command Line Tools" in CommandLineToolsInfo comments and ToString(). - Update tests to pass argument arrays instead of pre-formatted strings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pass "echo text" as single /c argument to cmd.exe so ArgumentList does not individually quote the text argument with spaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
rolfbjarne
approved these changes
Feb 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Foundation PR for the Apple CLI library APIs (spec). Must merge first — all subsequent PRs depend on these shared types and helpers.
What's included
Xamarin.MacDev/ProcessUtils.cs— Static helper for running external processes, inspired bydotnet/android-toolsProcessUtils. Provides:StartProcess— async with cancellation and stdout/stderr captureRunAsync— convenience, returns stdout or throws on failureTryRunAsync— returns stdout or null on failureExec— sync wrapper returning exit code + stdout + stderrXamarin.MacDev/Models/— Output model POCOs:XcodeInfo— Xcode installation detailsSimulatorDeviceInfo— simulator device infoSimulatorRuntimeInfo— simulator runtime infoCommandLineToolsInfo— CLT statusEnvironmentCheckResult— composite environment status withDeriveStatus()Tests — 14 new tests (26 total pass)
.github/copilot-instructions.md— Updated with code style conventionsCloses #153