ci: create iOS simulator when missing
This commit is contained in:
80
.github/workflows/ci.yml
vendored
80
.github/workflows/ci.yml
vendored
@@ -139,36 +139,72 @@ jobs:
|
|||||||
DEST_ID="$(
|
DEST_ID="$(
|
||||||
python3 - <<'PY'
|
python3 - <<'PY'
|
||||||
import json
|
import json
|
||||||
import re
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import uuid
|
||||||
|
|
||||||
data = json.loads(
|
def sh(args: list[str]) -> str:
|
||||||
subprocess.check_output(["xcrun", "simctl", "list", "devices", "available", "-j"], text=True)
|
return subprocess.check_output(args, text=True).strip()
|
||||||
)
|
|
||||||
runtimes = []
|
|
||||||
for runtime in data.get("devices", {}).keys():
|
|
||||||
m = re.search(r"\\.iOS-(\\d+)-(\\d+)$", runtime)
|
|
||||||
if m:
|
|
||||||
runtimes.append((int(m.group(1)), int(m.group(2)), runtime))
|
|
||||||
|
|
||||||
runtimes.sort(reverse=True)
|
# Prefer an already-created iPhone simulator if it exists.
|
||||||
|
devices = json.loads(sh(["xcrun", "simctl", "list", "devices", "-j"]))
|
||||||
|
candidates: list[tuple[str, str]] = []
|
||||||
|
for runtime, devs in (devices.get("devices") or {}).items():
|
||||||
|
for dev in devs or []:
|
||||||
|
if not dev.get("isAvailable"):
|
||||||
|
continue
|
||||||
|
name = str(dev.get("name") or "")
|
||||||
|
udid = str(dev.get("udid") or "")
|
||||||
|
if not udid or not name.startswith("iPhone"):
|
||||||
|
continue
|
||||||
|
candidates.append((name, udid))
|
||||||
|
|
||||||
def pick_device(devices):
|
candidates.sort(key=lambda it: (0 if "iPhone 16" in it[0] else 1, it[0]))
|
||||||
iphones = [d for d in devices if d.get("isAvailable") and d.get("name", "").startswith("iPhone")]
|
if candidates:
|
||||||
if not iphones:
|
print(candidates[0][1])
|
||||||
return None
|
|
||||||
prefer = [d for d in iphones if "iPhone 16" in d.get("name", "")]
|
|
||||||
return (prefer[0] if prefer else iphones[0]).get("udid")
|
|
||||||
|
|
||||||
for _, __, runtime in runtimes:
|
|
||||||
udid = pick_device(data["devices"].get(runtime, []))
|
|
||||||
if udid:
|
|
||||||
print(udid)
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
print("No available iPhone simulators found.", file=sys.stderr)
|
# Otherwise, create one from the newest available iOS runtime.
|
||||||
|
runtimes = json.loads(sh(["xcrun", "simctl", "list", "runtimes", "-j"])).get("runtimes") or []
|
||||||
|
ios = [rt for rt in runtimes if rt.get("platform") == "iOS" and rt.get("isAvailable")]
|
||||||
|
if not ios:
|
||||||
|
print("No available iOS runtimes found.", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
def version_key(rt: dict) -> tuple[int, ...]:
|
||||||
|
parts = []
|
||||||
|
for p in str(rt.get("version") or "0").split("."):
|
||||||
|
try:
|
||||||
|
parts.append(int(p))
|
||||||
|
except ValueError:
|
||||||
|
parts.append(0)
|
||||||
|
return tuple(parts)
|
||||||
|
|
||||||
|
ios.sort(key=version_key, reverse=True)
|
||||||
|
runtime = ios[0]
|
||||||
|
runtime_id = str(runtime.get("identifier") or "")
|
||||||
|
if not runtime_id:
|
||||||
|
print("Missing iOS runtime identifier.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
supported = runtime.get("supportedDeviceTypes") or []
|
||||||
|
iphones = [dt for dt in supported if dt.get("productFamily") == "iPhone"]
|
||||||
|
if not iphones:
|
||||||
|
print("No iPhone device types for iOS runtime.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
iphones.sort(key=lambda dt: (0 if "iPhone 16" in str(dt.get("name") or "") else 1, str(dt.get("name") or "")))
|
||||||
|
device_type_id = str(iphones[0].get("identifier") or "")
|
||||||
|
if not device_type_id:
|
||||||
|
print("Missing iPhone device type identifier.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
sim_name = f"CI iPhone {uuid.uuid4().hex[:8]}"
|
||||||
|
udid = sh(["xcrun", "simctl", "create", sim_name, device_type_id, runtime_id])
|
||||||
|
if not udid:
|
||||||
|
print("Failed to create iPhone simulator.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
print(udid)
|
||||||
PY
|
PY
|
||||||
)"
|
)"
|
||||||
echo "Using iOS Simulator id: $DEST_ID"
|
echo "Using iOS Simulator id: $DEST_ID"
|
||||||
|
|||||||
Reference in New Issue
Block a user