Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
81c6d8c
test: require isolated app-host user state
lawrencecchen Aug 6, 2026
56aa78d
ci: isolate app-host user configuration
lawrencecchen Aug 6, 2026
5beeaa3
test(ci): scope app-host isolation guard to jobs
lawrencecchen Aug 6, 2026
945f370
test(ci): reject malformed isolation workflow
lawrencecchen Aug 6, 2026
2ef782f
test: require app-host launch home isolation
lawrencecchen Aug 6, 2026
8b8856f
test: reject app-host config path leaks
lawrencecchen Aug 6, 2026
c42f766
fix: isolate launched app-host user state
lawrencecchen Aug 6, 2026
047ad6c
test: require nonempty app-host XDG default
lawrencecchen Aug 6, 2026
1ba2484
fix: default app-host XDG path safely
lawrencecchen Aug 6, 2026
14d0359
test: keep app-host redirects off xcodebuild
lawrencecchen Aug 6, 2026
468bf90
fix: scope redirects to launched app host
lawrencecchen Aug 6, 2026
695659d
test: require XCTest runner home isolation
lawrencecchen Aug 6, 2026
552ae7b
fix: isolate XCTest app host through runner environment
lawrencecchen Aug 6, 2026
3f2d757
test: close app-host isolation validation gaps
lawrencecchen Aug 6, 2026
ba91848
fix: harden app-host isolation validation
lawrencecchen Aug 6, 2026
8250217
test: cover optional app-host isolation validation
lawrencecchen Aug 6, 2026
883f2b9
fix: keep app-host isolation assertions opt in
lawrencecchen Aug 6, 2026
56ea1f4
test: reject app-host XDG and scheme overrides
lawrencecchen Aug 6, 2026
2ae885e
fix: bind app-host XDG to isolated home
lawrencecchen Aug 6, 2026
fad91f4
test: cover non-isolated macOS Bash wrapper
lawrencecchen Aug 6, 2026
600a406
fix: support optional isolation on macOS Bash
lawrencecchen Aug 6, 2026
234e73b
test: cover app-host child isolation boundaries
lawrencecchen Aug 6, 2026
592a76a
fix: isolate app-host child process state
lawrencecchen Aug 6, 2026
5022f30
test: require fail-closed app-host cleanup
lawrencecchen Aug 6, 2026
b1491f4
fix: fail closed and clean app-host homes
lawrencecchen Aug 6, 2026
0a9de06
test: require cleanup after XDG removal
lawrencecchen Aug 6, 2026
42e5fd2
fix: clean homes after XDG removal
lawrencecchen Aug 6, 2026
a164928
Merge remote-tracking branch 'origin/main' into fix-app-host-user-con…
lawrencecchen Aug 6, 2026
50beb70
style: restore process helper indentation
lawrencecchen Aug 6, 2026
bbb381a
test: require robust app-host teardown discovery
lawrencecchen Aug 6, 2026
879598a
fix: make app-host teardown robust
lawrencecchen Aug 6, 2026
33e9656
test: preserve long-path app-host fixture
lawrencecchen Aug 6, 2026
e095c75
test: keep app-host isolation out of driver environment
lawrencecchen Aug 6, 2026
991d9ec
fix: isolate app-host redirects at launch boundary
lawrencecchen Aug 6, 2026
b17616b
Merge remote-tracking branch 'origin/main' into fix-app-host-user-con…
lawrencecchen Aug 6, 2026
8718178
test: reject ambient Ghostty configuration reads
lawrencecchen Aug 6, 2026
6a882f9
fix: validate every Ghostty config path
lawrencecchen Aug 6, 2026
4dd956f
test: clean mutated app-host XDG entries
lawrencecchen Aug 6, 2026
9684a02
fix: clean mutated app-host XDG entries
lawrencecchen Aug 6, 2026
c414754
Merge remote-tracking branch 'origin/main' into fix-app-host-user-con…
lawrencecchen Aug 6, 2026
9999aa7
test: require durable app-host isolation evidence
lawrencecchen Aug 6, 2026
d6efb15
fix: require durable app-host isolation evidence
lawrencecchen Aug 6, 2026
b8ab901
test: enforce short symlink-safe app-host homes
lawrencecchen Aug 6, 2026
df068f0
fix: use short symlink-safe app-host homes
lawrencecchen Aug 6, 2026
024c139
Merge remote-tracking branch 'origin/main' into fix-app-host-user-con…
lawrencecchen Aug 6, 2026
6faea3b
test: exercise app-host home symlink guard
lawrencecchen Aug 7, 2026
158a1b5
test: require app-host identity receipts
lawrencecchen Aug 7, 2026
471ce8a
fix: bind app-host cleanup to run identity
lawrencecchen Aug 7, 2026
82125af
Merge remote-tracking branch 'origin/main' into fix-app-host-user-con…
lawrencecchen Aug 7, 2026
8e830f7
Merge remote-tracking branch 'origin/main' into fix-app-host-user-con…
lawrencecchen Aug 7, 2026
d605f32
test: keep app-host receipts across CI jobs
lawrencecchen Aug 7, 2026
5a59e8c
fix: persist app-host process authority
lawrencecchen Aug 7, 2026
ca1ac9e
Merge remote-tracking branch 'origin/main' into fix-app-host-user-con…
lawrencecchen Aug 7, 2026
687f65a
test: inject lsof into app-host retry guard
lawrencecchen Aug 7, 2026
c221490
test: preserve existing app-host authority scope
lawrencecchen Aug 7, 2026
e083962
fix: preserve existing app-host authority scope
lawrencecchen Aug 7, 2026
226ef0e
test: model dead-pid lsof diagnostics
lawrencecchen Aug 7, 2026
accca0a
fix: classify dead-pid lsof diagnostics as stale
lawrencecchen Aug 7, 2026
248c855
test: authenticate cleanup before ownership transfer
lawrencecchen Aug 7, 2026
f15dcb8
fix: authenticate app-host scope before ownership transfer
lawrencecchen Aug 7, 2026
a89bcc2
test: bind app-host receipts to process incarnation
lawrencecchen Aug 7, 2026
ef40365
fix: bind app-host receipts to process incarnation
lawrencecchen Aug 7, 2026
2ca686f
test: make app-host owner fixture portable
lawrencecchen Aug 7, 2026
4f94aad
test: require atomic app-host receipt publication
lawrencecchen Aug 7, 2026
465d819
fix: publish app-host receipts atomically
lawrencecchen Aug 7, 2026
9791ac1
test: cover app-host recovery review gaps
lawrencecchen Aug 7, 2026
b9be11c
fix: harden app-host recovery
lawrencecchen Aug 7, 2026
d29d25d
test: cover app-host ownership lifecycle gaps
lawrencecchen Aug 7, 2026
74b7718
fix: scope app-host recovery to one run
lawrencecchen Aug 7, 2026
406ed58
test: recover authenticated prior-run app hosts
lawrencecchen Aug 7, 2026
3f7e9c5
test: cover multiple current app-host owners
lawrencecchen Aug 7, 2026
aced3f7
test: bound prior app-host recovery eligibility
lawrencecchen Aug 7, 2026
d7d98a9
test: model lsof machine descriptor fields
lawrencecchen Aug 7, 2026
6609970
test: recover deleted prior app-host owners
lawrencecchen Aug 7, 2026
8a97cb8
fix: recover authenticated prior app hosts
lawrencecchen Aug 7, 2026
cb159ca
test: model lsof access mode fields
lawrencecchen Aug 7, 2026
c978816
fix: verify lsof receipt access mode
lawrencecchen Aug 7, 2026
c6f1906
test: include lsof access mode in cleanup fixture
lawrencecchen Aug 7, 2026
82b5c67
test: reject untrusted newest confirmations
lawrencecchen Aug 7, 2026
e2522e4
fix: authenticate newest app-host confirmations
lawrencecchen Aug 7, 2026
4a290ce
test: cover app-host machine ownership boundaries
lawrencecchen Aug 7, 2026
276101a
fix: bind app-host recovery to machine ownership
lawrencecchen Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ jobs:
- name: Validate app-host xcodebuild attempt budget
run: ./tests/test_ci_app_host_xcodebuild_attempts.sh

- name: Validate app-host user configuration isolation
run: python3 tests/test_ci_app_host_home_isolation.py

- name: Validate cmux profiling support scripts
run: ./tests/test_start_cmux_profiling.sh

Expand Down Expand Up @@ -548,6 +551,24 @@ jobs:
mkdir -p "$DERIVED_DATA_PATH"
echo "CMUX_DERIVED_DATA_PATH=$DERIVED_DATA_PATH" >> "$GITHUB_ENV"

- name: Prepare isolated app-host home
run: |
set -euo pipefail
APP_HOST_HOME="${RUNNER_TEMP}/cmux-app-host-home-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-shard-${{ matrix.shard }}"
rm -rf "$APP_HOST_HOME"
mkdir -p \
"$APP_HOST_HOME/.config/cmux" \
"$APP_HOST_HOME/.config/ghostty" \
"$APP_HOST_HOME/Library/Application Support" \
"$APP_HOST_HOME/Library/Caches" \
"$APP_HOST_HOME/Library/Logs/DiagnosticReports" \
"$APP_HOST_HOME/Library/Preferences"
chmod -R a+rwX "$APP_HOST_HOME"
echo "CFFIXED_USER_HOME=$APP_HOST_HOME" >> "$GITHUB_ENV"
echo "XDG_CONFIG_HOME=$APP_HOST_HOME/.config" >> "$GITHUB_ENV"
echo "CARGO_HOME=${HOME}/.cargo" >> "$GITHUB_ENV"
echo "RUSTUP_HOME=${HOME}/.rustup" >> "$GITHUB_ENV"

- name: Resolve Swift packages
run: |
set -euo pipefail
Expand Down
4 changes: 4 additions & 0 deletions cmux.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11135,6 +11135,8 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa =
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-Debug";
CMUX_APP_HOST_HOME = "$(HOME)";
CMUX_APP_HOST_XDG_CONFIG_HOME = "$(XDG_CONFIG_HOME:default=$(HOME)/.config)";
CMUX_AUTH_CALLBACK_SCHEME = "cmux-dev";
CMUX_IROH_RELAY_POLICY_KEY_ID = "cmux-staging-relay-policy-2026-07";
CMUX_IROH_RELAY_POLICY_NEXT_KEY_ID = "cmux-staging-relay-policy-2026-08";
Expand Down Expand Up @@ -11185,6 +11187,8 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa =
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CMUX_APP_HOST_HOME = "$(HOME)";
CMUX_APP_HOST_XDG_CONFIG_HOME = "$(XDG_CONFIG_HOME:default=$(HOME)/.config)";
CMUX_AUTH_CALLBACK_SCHEME = cmux;
CMUX_IROH_RELAY_POLICY_KEY_ID = "cmux-production-relay-policy-2026-07";
CMUX_IROH_RELAY_POLICY_NEXT_KEY_ID = "cmux-production-relay-policy-2026-08";
Expand Down
5 changes: 5 additions & 0 deletions cmux.xcodeproj/xcshareddata/xcschemes/cmux-unit.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmux.app" BlueprintName="cmux" ReferencedContainer="container:cmux.xcodeproj"/>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable key="HOME" value="$(CMUX_APP_HOST_HOME)" isEnabled="YES"/>
<EnvironmentVariable key="CFFIXED_USER_HOME" value="$(CMUX_APP_HOST_HOME)" isEnabled="YES"/>
<EnvironmentVariable key="XDG_CONFIG_HOME" value="$(CMUX_APP_HOST_XDG_CONFIG_HOME)" isEnabled="YES"/>
<EnvironmentVariable key="CMUX_APP_HOST_EXPECTED_HOME" value="$(CMUX_APP_HOST_HOME)" isEnabled="YES"/>
<EnvironmentVariable key="CMUX_APP_HOST_EXPECTED_XDG_CONFIG_HOME" value="$(CMUX_APP_HOST_XDG_CONFIG_HOME)" isEnabled="YES"/>
<EnvironmentVariable key="SWIFT_BACKTRACE" value="interactive=no,timeout=0s,symbolicate=off,color=no" isEnabled="YES"/>
</EnvironmentVariables>
</TestAction>
Expand Down
38 changes: 38 additions & 0 deletions cmuxTests/MacSentryStartupPolicyTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Testing
import Foundation

#if canImport(cmux_DEV)
@testable import cmux_DEV
Expand All @@ -7,6 +8,43 @@ import Testing
#endif

@Suite struct MacSentryStartupPolicyTests {
@Test func appHostUsesSchemeScopedUserConfigurationHome() throws {
let environment = ProcessInfo.processInfo.environment
let expectedHome = try #require(
environment["CMUX_APP_HOST_EXPECTED_HOME"],
"The cmux-unit scheme must publish its resolved app-host home"
)
let expectedXDGConfigHome = try #require(
environment["CMUX_APP_HOST_EXPECTED_XDG_CONFIG_HOME"],
"The cmux-unit scheme must publish its resolved XDG config home"
)

#expect(environment["HOME"] == expectedHome)
#expect(environment["CFFIXED_USER_HOME"] == expectedHome)
#expect(environment["XDG_CONFIG_HOME"] == expectedXDGConfigHome)
#expect(FileManager.default.homeDirectoryForCurrentUser.path == expectedHome)
#expect(
FileManager.default.urls(
for: .applicationSupportDirectory,
in: .userDomainMask
).first?.path
== URL(fileURLWithPath: expectedHome, isDirectory: true)
.appendingPathComponent(
"Library/Application Support",
isDirectory: true
).path
)
#expect(
NSString(string: "~/Library/Application Support")
.expandingTildeInPath
== URL(fileURLWithPath: expectedHome, isDirectory: true)
.appendingPathComponent(
"Library/Application Support",
isDirectory: true
).path
)
}

@Test func xctestLaunchDoesNotStartSentry() {
#expect(
MacSentryStartupPolicy(
Expand Down
47 changes: 46 additions & 1 deletion scripts/ci/run-app-host-xcodebuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ if [ -z "${CMUX_APP_HOST_TEST_LOCK_ACTIVE:-}" ]; then
"$lock_file" "$lock_wait_seconds" "$0" "$@"
fi

# xcodebuild must retain the console user's real HOME so Xcode and its package
# toolchains remain available. Capture isolation only after the lock re-exec,
# pass it as build settings, then remove the app-host-only redirects from the
# driver environment. The cmux-unit TestAction applies them to the launched app.
app_host_xcodebuild_settings=()
app_host_home=""
if [ -n "${CFFIXED_USER_HOME:-}" ]; then
if [ -z "${XDG_CONFIG_HOME:-}" ]; then
echo "FAIL: CFFIXED_USER_HOME requires XDG_CONFIG_HOME for app-host isolation" >&2
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
exit 1
fi
app_host_home="$CFFIXED_USER_HOME"
app_host_xcodebuild_settings+=(
"CMUX_APP_HOST_HOME=$CFFIXED_USER_HOME"
"CMUX_APP_HOST_XDG_CONFIG_HOME=$XDG_CONFIG_HOME"
)
unset CFFIXED_USER_HOME XDG_CONFIG_HOME
fi

# Resolve a CI-scoped root so app-host cleanup targets every CI app-host on this
# Mac (this run AND orphans left by previous runs, which live under a different
# per-run DerivedData path), while never matching a human's tagged dev build
Expand All @@ -51,6 +70,27 @@ kill_stale_app_host() {
pkill -f "${ci_app_host_root%/}/.*Build/Products/.*cmux DEV" 2>/dev/null || true
}

validate_app_host_config_paths() {
local log_path="$1"
[ -n "$app_host_home" ] || return 0

local expected_root="${app_host_home%/}/Library/Application Support/com.mitchellh.ghostty"
local line
while IFS= read -r line; do
case "$line" in
*"path=$expected_root"*) ;;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
*)
echo "FAIL: Ghostty accessed configuration outside the isolated app-host home" >&2
echo "$line" >&2
return 1
;;
esac
done < <(
grep -E '\[(config|default)\].*path=.*Library/Application Support/com\.mitchellh\.ghostty' \
"$log_path" || true
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}

attempt=1
while [ "$attempt" -le "$max_attempts" ]; do
log_path="${log_stem}-attempt-${attempt}.log"
Expand All @@ -64,10 +104,15 @@ while [ "$attempt" -le "$max_attempts" ]; do
set +e
TEST_RUNNER_CMUX_TEST_PROCESS=1 \
CMUX_XCODEBUILD_NONINTERACTIVE_LOG_PATH="$log_path" \
scripts/ci/xcodebuild_noninteractive.py xcodebuild "$@"
scripts/ci/xcodebuild_noninteractive.py xcodebuild "$@" \
"${app_host_xcodebuild_settings[@]}"
status=$?
set -e

if ! validate_app_host_config_paths "$log_path"; then
exit 1
fi

if grep -Fq 'path = "/tmp/cmux-debug.sock"' "$log_path"; then
echo "FAIL: app-host used default debug socket instead of an XCTest-scoped socket" >&2
exit 1
Expand Down
10 changes: 9 additions & 1 deletion scripts/ci/run-in-console-session.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ if [ "$#" -eq 0 ]; then
exit 2
fi

# App-host CI redirects Apple and XDG state while retaining the console user's
# real HOME for Xcode and the GUI login session. Never let a reused runner's
# personal SSH agent leak into tests that model agent forwarding explicitly.
if [ -n "${CFFIXED_USER_HOME:-}" ]; then
unset SSH_AUTH_SOCK
fi

console_user="$(stat -f %Su /dev/console 2>/dev/null || true)"
if [ -n "$console_user" ] && [ "$console_user" != "root" ] \
&& console_uid="$(id -u "$console_user" 2>/dev/null)" && sudo -n true 2>/dev/null; then
Expand All @@ -43,7 +50,8 @@ if [ -n "$console_user" ] && [ "$console_user" != "root" ] \
CMUX_XCODEBUILD_NONINTERACTIVE_IDLE_TIMEOUT_SECONDS \
CMUX_XCODEBUILD_NONINTERACTIVE_POST_TEST_TIMEOUT_SECONDS \
CMUX_XCODEBUILD_NONINTERACTIVE_TIMEOUT_SECONDS \
CMUX_APP_HOST_XCODEBUILD_ATTEMPTS)
CMUX_APP_HOST_XCODEBUILD_ATTEMPTS \
CFFIXED_USER_HOME XDG_CONFIG_HOME CARGO_HOME RUSTUP_HOME)
env_pairs=()
for var in "${forward[@]}"; do
if [ -n "${!var+set}" ]; then
Expand Down
167 changes: 167 additions & 0 deletions tests/test_ci_app_host_home_isolation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/usr/bin/env python3
"""Guard app-host XCTest against persistent console-user configuration."""

from pathlib import Path
import xml.etree.ElementTree as ET

import yaml


ROOT = Path(__file__).resolve().parents[1]
WORKFLOW_PATH = ROOT / ".github/workflows/ci.yml"
WORKFLOW = yaml.safe_load(WORKFLOW_PATH.read_text(encoding="utf-8"))
CONSOLE_WRAPPER = (ROOT / "scripts/ci/run-in-console-session.sh").read_text(
encoding="utf-8"
)
APP_HOST_WRAPPER = (ROOT / "scripts/ci/run-app-host-xcodebuild.sh").read_text(
encoding="utf-8"
)
UNIT_SCHEME_PATH = (
ROOT / "cmux.xcodeproj/xcshareddata/xcschemes/cmux-unit.xcscheme"
)
PROJECT = (ROOT / "cmux.xcodeproj/project.pbxproj").read_text(encoding="utf-8")


def require(text: str, needle: str, context: str) -> None:
if needle not in text:
raise SystemExit(f"FAIL: {context} is missing {needle!r}")


def require_step(job_name: str, step_name: str) -> dict:
if not isinstance(WORKFLOW, dict):
raise SystemExit("FAIL: workflow must be a mapping")

jobs = WORKFLOW.get("jobs")
if not isinstance(jobs, dict):
raise SystemExit("FAIL: workflow jobs must be a mapping")

job = jobs.get(job_name)
if not isinstance(job, dict):
raise SystemExit(f"FAIL: workflow job {job_name!r} is missing")

steps = job.get("steps")
if not isinstance(steps, list):
raise SystemExit(f"FAIL: workflow job {job_name!r} steps must be a list")

matches = []
for index, step in enumerate(steps):
if not isinstance(step, dict):
raise SystemExit(
f"FAIL: workflow job {job_name!r} step {index} must be a mapping"
)
if step.get("name") == step_name:
matches.append(step)
if len(matches) != 1:
raise SystemExit(
f"FAIL: workflow job {job_name!r} must contain exactly one "
f"{step_name!r} step"
)
return matches[0]


def main() -> int:
setup_step = require_step(
"app-host-unit-tests", "Prepare isolated app-host home"
)
setup_run = setup_step.get("run")
if not isinstance(setup_run, str):
raise SystemExit("FAIL: isolated app-host setup step has no run script")

requirements = {
"per-shard app-host home": (
"APP_HOST_HOME=\"${RUNNER_TEMP}/cmux-app-host-home-"
"${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-shard-${{ matrix.shard }}\""
),
"Core Foundation home redirect": (
'echo "CFFIXED_USER_HOME=$APP_HOST_HOME" >> "$GITHUB_ENV"'
),
"XDG configuration redirect": (
'echo "XDG_CONFIG_HOME=$APP_HOST_HOME/.config" >> "$GITHUB_ENV"'
),
"console-user write access": 'chmod -R a+rwX "$APP_HOST_HOME"',
"real Cargo toolchain home": 'echo "CARGO_HOME=${HOME}/.cargo" >> "$GITHUB_ENV"',
"real rustup toolchain home": 'echo "RUSTUP_HOME=${HOME}/.rustup" >> "$GITHUB_ENV"',
}
for context, needle in requirements.items():
require(setup_run, needle, context)

guard_step = require_step(
"workflow-guard-tests", "Validate app-host user configuration isolation"
)
if guard_step.get("run") != "python3 tests/test_ci_app_host_home_isolation.py":
raise SystemExit("FAIL: workflow-guard-tests does not run this guard")

require(
CONSOLE_WRAPPER,
"CFFIXED_USER_HOME XDG_CONFIG_HOME CARGO_HOME RUSTUP_HOME",
"console-session environment forwarding",
)
require(
CONSOLE_WRAPPER,
"unset SSH_AUTH_SOCK",
"ambient SSH agent removal",
)
require(
CONSOLE_WRAPPER,
'env HOME="$console_home"',
"console-session Unix home preservation",
)

scheme_root = ET.parse(UNIT_SCHEME_PATH).getroot()
test_action = scheme_root.find("TestAction")
if test_action is None:
raise SystemExit("FAIL: cmux-unit scheme has no TestAction")
environment_variables = test_action.find("EnvironmentVariables")
if environment_variables is None:
raise SystemExit("FAIL: cmux-unit TestAction has no environment variables")
scheme_environment = {
item.get("key"): item.get("value")
for item in environment_variables.findall("EnvironmentVariable")
if item.get("isEnabled") == "YES"
}
expected_scheme_environment = {
"HOME": "$(CMUX_APP_HOST_HOME)",
"CFFIXED_USER_HOME": "$(CMUX_APP_HOST_HOME)",
"XDG_CONFIG_HOME": "$(CMUX_APP_HOST_XDG_CONFIG_HOME)",
"CMUX_APP_HOST_EXPECTED_HOME": "$(CMUX_APP_HOST_HOME)",
"CMUX_APP_HOST_EXPECTED_XDG_CONFIG_HOME": (
"$(CMUX_APP_HOST_XDG_CONFIG_HOME)"
),
}
for key, value in expected_scheme_environment.items():
if scheme_environment.get(key) != value:
raise SystemExit(
f"FAIL: cmux-unit TestAction must set {key}={value}"
)

for context, needle in {
"app-host HOME build-setting default": 'CMUX_APP_HOST_HOME = "$(HOME)";',
"app-host XDG build-setting default": (
'CMUX_APP_HOST_XDG_CONFIG_HOME = '
'"$(XDG_CONFIG_HOME:default=$(HOME)/.config)";'
),
}.items():
if PROJECT.count(needle) < 2:
raise SystemExit(
f"FAIL: Debug and Release app targets need {context}: {needle}"
)

for context, needle in {
"app-host HOME xcodebuild override": (
'"CMUX_APP_HOST_HOME=$CFFIXED_USER_HOME"'
),
"app-host XDG xcodebuild override": (
'"CMUX_APP_HOST_XDG_CONFIG_HOME=$XDG_CONFIG_HOME"'
),
"Ghostty app-support path validation": (
"validate_app_host_config_paths"
),
}.items():
require(APP_HOST_WRAPPER, needle, context)

print("PASS: app-host XCTest receives an isolated launch home")
return 0


if __name__ == "__main__":
raise SystemExit(main())
Loading
Loading