How to Export xcresult from Remote Mac CI? 2026 Guide
If your remote Mac test job finishes without a downloadable xcresult, the issue is usually in the result path, upload condition, or artifact file selection. This guide walks CI maintainers, build engineers, test engineers, and platform owners through creating, uploading, inspecting, and verifying test result bundles.
Table of Contents
- CI maintainers: confirm the test run produces a result bundle
- Build engineers: assign every test task its own result path
- Why is the result path missing?
- Workflow maintainers: upload results after a failed test
- Test engineers: download and inspect the bundle
- Platform owners: define artifact naming, access, and retention
- Release owners: accept the pipeline with success and failure runs
Your remote Mac test job failed, but the workflow run has no result bundle to download.
This week, set an explicit, unique -resultBundlePath, upload that .xcresult as a workflow artifact even when tests fail, then download and open it on macOS.
This guide is for CI maintainers who need to retrieve test output after a remote run.
It also helps test engineers inspect failures, logs, and coverage, and platform or release owners set traceable access and retention rules.
An xcresult is not the same thing as a build log or an archive. First confirm that the workflow actually ran tests, then follow the bundle from its creation path through artifact upload to local inspection. Apple describes Xcode test results and result bundles in its guide to running tests and interpreting results.
CI maintainers: confirm the test run produces a result bundle
An Xcode test result bundle is generated by a test operation, not merely because a workflow invokes a build. If your job runs a build or archive step but never executes tests, there may be no test result bundle to export. Check the actual xcodebuild invocation and the job log before troubleshooting artifact upload.
Apple documents test execution and the information available when interpreting results in its Xcode testing guide. The command-line options available to your installed Xcode are documented in Apple’s Xcode command-line tool reference. Verify command options against the Xcode version used by the runner; don’t assume a command copied from another pipeline applies unchanged.
| Output | What it represents | Can it replace an .xcresult? |
|---|---|---|
| Build or test log | Text emitted during the command; useful for seeing command output and errors | No. It may not provide the structured test-result data you need to inspect later. |
.xcresult bundle |
Xcode test result data, which can be inspected with Xcode or supported command-line tools | No. Treat it as a distinct result package, not a plain text log. |
| Archive output | A build product prepared for distribution or other downstream handling | No. Creating an archive alone does not establish that tests ran or that a test result bundle exists. |
Use the distinction to narrow the failure. If the test command did not run, fix the workflow’s test stage. If it ran but no bundle appeared, inspect its result path. If the bundle exists on the runner but not in the downloadable artifact, focus on the upload step and its path selection.
Build engineers: assign every test task its own result path
An explicit result path makes the output location predictable. It also gives later workflow steps a concrete directory to upload. Use a path outside the checked-out source tree where practical, and don’t reuse a path that could contain a previous run’s output.
A command structure can look like this:
RESULT_BUNDLE="${RUNNER_TEMP}/results/${WORKFLOW_LABEL}-${TASK_LABEL}.xcresult"
xcodebuild \
-workspace "<WORKSPACE_PATH>" \
-scheme "<SCHEME_NAME>" \
-destination "<TEST_DESTINATION>" \
-resultBundlePath "$RESULT_BUNDLE" \
test
Replace every placeholder with a value from your project and runner. Keep the result path in an environment variable or another shared workflow setting so the test step and artifact-upload step refer to the same location. Apple’s command-line tool reference is the place to verify the supported options for the installed toolchain.
For parallel jobs, include a task-specific component in each path. Two test jobs writing to the same result location can collide, fail to create their bundle, or leave you unsure which task produced the output. Use a separate directory for each scheme, destination, or matrix job as appropriate to your workflow. Don’t treat a path as unique merely because the job name looks different in the workflow interface.
The bundle is a directory-style package rather than a single text file. That matters when choosing an upload path: a glob that selects a log file may omit the result package, even though the package is present on the runner. After the command finishes, check that the exact path exists before assuming the upload step is at fault.
Why is the result path missing?
Check the workflow in this order:
- Confirm the step invokes
xcodebuild ... test, not only a build or archive operation. - Confirm the test command includes
-resultBundlePathand that its value is the same path expected by the upload step. - Check for a path collision with another task or an existing output.
- Check the test command’s log for an earlier failure that prevented result creation.
- Inspect the runner’s output directory before it is cleaned up or the job ends.
This sequence separates “no test bundle was created” from “a created bundle was not uploaded.” They require different fixes.
Workflow maintainers: upload results after a failed test
In a typical CI workflow, a failed test step stops later steps from running unless the later step has a condition that allows it to proceed. That means a correctly generated result bundle can still be lost when the workflow skips the upload action after a test failure.
GitHub documents how workflow artifacts can preserve and share build or test output in its guide to persisting workflow data with artifacts. Use an upload condition that allows artifact collection after a failed test, while respecting cancellation behavior defined for your workflow. GitHub’s expression reference describes the available status-check functions and expression syntax.
- name: Run tests
run: |
xcodebuild \
-workspace "<WORKSPACE_PATH>" \
-scheme "<SCHEME_NAME>" \
-destination "<TEST_DESTINATION>" \
-resultBundlePath "${{ runner.temp }}/results/<TASK_LABEL>.xcresult" \
test
- name: Upload test result bundle
if: ${{ !cancelled() }}
uses: actions/upload-artifact@<PINNED_VERSION>
with:
name: "xcresult-${{ github.run_id }}-${{ github.run_attempt }}-<TASK_LABEL>"
path: "${{ runner.temp }}/results/<TASK_LABEL>.xcresult"
This example uses placeholders deliberately. Pin the upload action according to your organization’s dependency policy, and ensure the upload path matches the result path in the test command. The run identifiers in the artifact name help distinguish workflow executions; add a task or matrix label when multiple test jobs produce results.
GitHub’s artifact documentation covers how files and directories are saved as workflow artifacts. Its workflow artifact concepts distinguish artifacts from caches: use an artifact when you need to retrieve a particular run’s output, not a cache as a substitute for test-result delivery. Caches serve dependency reuse; they are not a dependable record of a specific test execution.
| Upload setup | What you should expect | First check when it fails |
|---|---|---|
Exact .xcresult directory path |
The upload step targets the intended result bundle | Compare the path with the test command’s -resultBundlePath. |
| Broad directory or pattern | More than one output may be selected, depending on the configured path | Confirm that the selected files include the .xcresult package. |
| Log-only path | Text output may upload while the result bundle does not | Expand the upload selection to include the bundle directory. |
| Upload step with no failure-tolerant condition | A prior test failure may prevent the upload step from running | Check the job’s step status and upload condition. |
A practical failure pattern is a path mismatch: the test step writes to a runner temporary directory, while the upload step looks under the repository workspace. Both steps can appear reasonable in isolation, yet the artifact is empty or missing. Compare their fully resolved paths rather than just the variable names.
Don’t use a green workflow status as proof that result delivery works. A success-only test can validate the normal path while leaving the failure path untested.
Test engineers: download and inspect the bundle
When the workflow run completes, use its artifact interface to download the uploaded result. GitHub explains the available steps in its workflow artifact download guide. After downloading, extract the artifact if it arrives as an archive, then inspect the .xcresult package on a Mac with Xcode or the command-line tools available for that environment.
xcresulttool provides a command-line route for examining result-bundle data. Its available subcommands can depend on the installed Xcode, so check the local tool’s help before adopting a command in scripts. For a supported installation, a summary query may look like this:
xcrun xcresulttool get test-results summary --path "<PATH_TO_RESULT>.xcresult"
Treat the command as a starting point, not a universal compatibility guarantee. If it is unavailable, run xcrun xcresulttool --help and use the syntax documented for your installed Xcode. Apple’s Xcode command-line tool reference provides the official entry point for checking the tool and its options.
| Inspection target | What to verify | Why it matters |
|---|---|---|
| Test summary | The result bundle opens and identifies the expected test run | Confirms that the downloaded output is readable and belongs to the intended task. |
| Failed tests | Failure details match the CI job and the commit under investigation | Helps you diagnose test behavior rather than relying on a truncated console log. |
| Logs or attachments | Required diagnostic material is present for the failure you are investigating | Missing attachments may indicate that you uploaded the wrong output or that the test did not generate them. |
| Coverage | Coverage data is present when your project’s test configuration is expected to produce it | A readable bundle does not, by itself, prove that every optional report was collected. |
Use the project’s own test configuration to decide whether coverage or particular attachments should exist. Don’t interpret their absence as an upload failure unless the workflow is supposed to generate them. The bundle’s readability, test identity, failure details, and expected reports are separate checks.
Platform owners: define artifact naming, access, and retention
A result bundle can include details about tests, failures, and project behavior. Treat it as diagnostic material with an access boundary, not as a file that is automatically safe to make public. Decide who can view workflow runs and artifacts, and ensure that permissions match the sensitivity of the repository and its test output.
Name each artifact so that an engineer can associate it with the workflow run, commit, and test task without opening every download. Workflow-provided identifiers such as run ID and attempt, together with a scheme or matrix label, can support that traceability. Avoid names that reveal secrets or unnecessary customer information.
Set retention according to your organization’s debugging and release needs and the platform’s available settings. Do not assume a universal default retention period: confirm what applies to your repository and organization in the current GitHub settings and documentation. GitHub’s artifact guidance describes artifact storage and handling, but your actual policy must be checked in the environment that owns the workflow.
Keep artifact retention separate from cache policy. A cache may speed later jobs, but it is not the right record to retrieve a named test result for a particular run. If a release or incident process requires traceable evidence, specify who owns the artifact, who may download it, and how long it must remain available.
Release owners: accept the pipeline with success and failure runs
A reliable export path is not proven by a passing test alone. Validate a successful test run and a deliberately failing test run in a controlled branch or test environment. For each, check the same chain: test command executed, result bundle appeared at the expected path, upload step ran, artifact can be downloaded, and the package opens on macOS.
Use the following decision branches to locate the fault:
- If the test log confirms a test operation and the result directory exists, but no artifact appears, inspect the upload step’s condition and path selection.
- If the upload step ran but reports no matching output, compare its resolved path with
-resultBundlePath; don’t assume the package is a single file. - If the artifact downloads but does not open, check that you downloaded and extracted the intended bundle, then verify it with the Xcode tools available on the inspection Mac.
- If the artifact was available earlier but is no longer downloadable, check the repository or organization’s retention settings and access permissions before rerunning tests.
- If the test command never ran, fix the workflow’s test-stage conditions before changing artifact handling.
Record the outcome for both paths in your pipeline acceptance notes. A passing run confirms that the normal output can be delivered. A failing run confirms that the diagnostic evidence survives the condition that most often makes it valuable. Keep the workflow logs for the test and upload steps alongside your troubleshooting notes, but don’t mistake those logs for the bundle itself.
For a remote Mac that is already part of your build process, the result path and artifact handling should be tested as part of the runner’s acceptance criteria. If you are still choosing an execution environment, compare your current setup’s dependence on a developer’s local machine, limited macOS access, and the operational work of preserving results with a managed Mac workflow. Renting a Mac through VPSMAC can suit a temporary CI rollout or a test environment you need without buying hardware; it does not replace a locally owned Mac when your team needs permanent, high-volume capacity or direct access to physical peripherals. If you are comparing whether a hosted Mac fits your runner setup, review VPSMAC’s remote Mac service overview alongside your access and maintenance requirements.
If you’re evaluating a remote Mac for CI, review the available VPSMAC Mac options and choose based on your project’s build cadence, access requirements, and who will maintain the runner. For a pipeline that must preserve test evidence, validate the artifact flow before relying on it for release diagnosis.