Skip to content

Commit 3dfad1e

Browse files
committed
Delay iOS PR comments until public simulator access is ready
1 parent 9bc81ea commit 3dfad1e

4 files changed

Lines changed: 107 additions & 2 deletions

File tree

actions/run-ios-comment-session/action.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,58 @@ runs:
545545
fi
546546
date +%s > /tmp/sim-boot-end
547547
548+
- name: Wait for public SimDeck iOS session access
549+
shell: bash
550+
run: |
551+
set -euo pipefail
552+
553+
udid="${SIMULATOR_UDID}"
554+
public_simulators_url="${{ steps.stream.outputs.url }}/api/simulators?simdeckToken=${{ steps.stream.outputs.access_token }}"
555+
tunnel_host="${{ steps.stream.outputs.url }}"
556+
tunnel_host="${tunnel_host#https://}"
557+
tunnel_host="${tunnel_host%%/*}"
558+
559+
fetch_public_simulators() {
560+
curl -fsS "${public_simulators_url}" -o public-simulators.json ||
561+
curl -fsS --resolve "${tunnel_host}:443:104.16.230.132" "${public_simulators_url}" -o public-simulators.json ||
562+
curl -fsS --resolve "${tunnel_host}:443:104.16.231.132" "${public_simulators_url}" -o public-simulators.json
563+
}
564+
565+
verify_selected_simulator() {
566+
SIMDECK_READY_UDID="${udid}" python3 - <<'PY'
567+
import json
568+
import os
569+
570+
with open("public-simulators.json", "r", encoding="utf-8") as handle:
571+
data = json.load(handle)
572+
573+
udid = os.environ["SIMDECK_READY_UDID"]
574+
simulators = data.get("simulators", data if isinstance(data, list) else [])
575+
for simulator in simulators:
576+
if simulator.get("udid") == udid and simulator.get("isBooted") is True:
577+
raise SystemExit(0)
578+
579+
raise SystemExit(1)
580+
PY
581+
}
582+
583+
for attempt in {1..120}; do
584+
if fetch_public_simulators && verify_selected_simulator; then
585+
echo "Public SimDeck URL lists booted simulator ${udid}."
586+
exit 0
587+
fi
588+
echo "Waiting for public SimDeck simulator list (${attempt}/120)."
589+
sleep 1
590+
done
591+
592+
echo "SimDeck public simulator list did not become accessible for ${udid}" >&2
593+
if [[ -f public-simulators.json ]]; then
594+
cat public-simulators.json >&2 || true
595+
fi
596+
cat cloudflared.log >&2 || true
597+
cat simdeck-daemon.log >&2 || true
598+
exit 1
599+
548600
- name: Update status comment with booted simulator URL
549601
shell: bash
550602
run: |

docs/guide/github-actions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,5 +192,5 @@ Supported quality values include `tiny`, `low`, `economy`, `fast`, `smooth`, `ba
192192
- Picks or creates an iOS Simulator or Android emulator.
193193
- Downloads the app artifact for the PR head commit.
194194
- Installs and launches the app.
195-
- Posts a browser URL back to the pull request after the simulator or emulator is booted.
195+
- Posts a browser URL back to the pull request after the simulator or emulator is booted. The iOS action waits until the public URL can load the selected booted simulator from `/api/simulators`.
196196
- Stops after the configured keepalive window.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"format": "prettier --write . && cargo fmt --manifest-path server/Cargo.toml",
6565
"format:check": "prettier --check . && cargo fmt --manifest-path server/Cargo.toml --check",
6666
"lint": "npm run format:check && cargo clippy --manifest-path server/Cargo.toml --all-targets -- -D warnings && npm run --prefix client typecheck",
67-
"test": "cargo test --manifest-path server/Cargo.toml && npm run --prefix client test",
67+
"test": "cargo test --manifest-path server/Cargo.toml && npm run --prefix client test && npm run test:github-actions",
6868
"test:integration:cli": "node scripts/integration/cli.mjs",
6969
"test:integration:cli:verbose": "SIMDECK_INTEGRATION_VERBOSE=1 SIMDECK_INTEGRATION_SHOW_SIMULATOR=1 node scripts/integration/cli.mjs",
7070
"test:integration:fixture": "node scripts/integration/prebuild-fixture.mjs",
@@ -77,6 +77,7 @@
7777
"test:e2e:webrtc:headed": "SIMDECK_E2E_HEADFUL=1 node scripts/e2e-webrtc-reliability.mjs",
7878
"test:e2e:webrtc:stress": "node scripts/e2e-webrtc-stress.mjs",
7979
"test:studio-provider": "node --test scripts/studio-provider-bridge.test.mjs scripts/studio-host-provider.test.mjs",
80+
"test:github-actions": "node --test scripts/github-actions.test.mjs",
8081
"test:stress": "node scripts/stress/simdeck.mjs",
8182
"bench:encoder:build": "scripts/bench/build-encoder-benchmark.sh",
8283
"ci": "npm run lint && npm run build:all && npm run test && npm run package:vscode-extension",

scripts/github-actions.test.mjs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import assert from "node:assert/strict";
2+
import { readFileSync } from "node:fs";
3+
import { test } from "node:test";
4+
5+
const iosAction = readFileSync(
6+
new URL("../actions/run-ios-comment-session/action.yml", import.meta.url),
7+
"utf8",
8+
);
9+
10+
test("iOS PR comment waits for public simulator list access", () => {
11+
const prebootIndex = iosAction.indexOf(
12+
"- name: Select and preboot simulator",
13+
);
14+
const readinessIndex = iosAction.indexOf(
15+
"- name: Wait for public SimDeck iOS session access",
16+
);
17+
const commentIndex = iosAction.indexOf(
18+
"- name: Update status comment with booted simulator URL",
19+
);
20+
21+
assert.notEqual(prebootIndex, -1, "preboot step should exist");
22+
assert.notEqual(
23+
commentIndex,
24+
-1,
25+
"booted simulator comment step should exist",
26+
);
27+
assert(
28+
readinessIndex > prebootIndex,
29+
"readiness check should run after simulator preboot",
30+
);
31+
assert(
32+
readinessIndex < commentIndex,
33+
"readiness check should run before posting the PR URL",
34+
);
35+
36+
const readinessStep = iosAction.slice(readinessIndex, commentIndex);
37+
assert.match(
38+
readinessStep,
39+
/\$\{\{ steps\.stream\.outputs\.url \}\}\/api\/simulators\?simdeckToken=/,
40+
"readiness check should use the public tunnel URL",
41+
);
42+
assert.match(
43+
readinessStep,
44+
/SIMULATOR_UDID/,
45+
"readiness check should look for the selected simulator",
46+
);
47+
assert.match(
48+
readinessStep,
49+
/isBooted/,
50+
"readiness check should require the selected simulator to be booted",
51+
);
52+
});

0 commit comments

Comments
 (0)