Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This is the log of notable changes to EAS CLI and related packages.

- [eas-cli] Improve `eas workflow:create`: add a `--template` flag, generate a placeholder workflow when a file name is passed, use shorter default file names (`build.yml`, `update.yml`, `deploy.yml`), configure EAS Build and EAS Update automatically when the chosen template requires them, set default app identifiers without prompting for the development build and deploy templates, install `expo-dev-client` during development build setup, and tighten the generated comments and next steps. ([#3943](https://github.com/expo/eas-cli/pull/3943) by [@jonsamp](https://github.com/jonsamp))
- [eas-cli] `eas integrations:posthog:dashboard` now opens PostHog via a signed-in link, skipping the login prompt. ([#3975](https://github.com/expo/eas-cli/pull/3975) by [@gwdp](https://github.com/gwdp))
- [build-tools] Pass a metrics CORS origin to serve-sim so the dashboard can read a session's live CPU/memory stream cross-origin. ([#3990](https://github.com/expo/eas-cli/pull/3990) by [@gwdp](https://github.com/gwdp))

### 🐛 Bug fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { Sentry } from '../../../sentry';
import { turtleFetch } from '../../../utils/turtleFetch';
import {
fetchServeSimTurnArgsAsync,
getMetricsCorsOrigin,
metricsCorsOriginToServeSimArgs,
turnIceServersToServeSimArgs,
waitForDeviceRunSessionStoppedAsync,
} from '../remoteDeviceRunSession';
Expand Down Expand Up @@ -80,6 +82,40 @@ function createEnvMock(): BuildStepEnv {
return { DEVICE_RUN_SESSION_ID: 'drs-id' } as unknown as BuildStepEnv;
}

describe(getMetricsCorsOrigin, () => {
it('returns the env origin, or undefined when unset/empty', () => {
expect(
getMetricsCorsOrigin({
EAS_SIMULATOR_METRICS_CORS_ORIGIN: 'https://expo.dev',
} as BuildStepEnv)
).toBe('https://expo.dev');
expect(getMetricsCorsOrigin({} as BuildStepEnv)).toBeUndefined();
expect(
getMetricsCorsOrigin({ EAS_SIMULATOR_METRICS_CORS_ORIGIN: '' } as BuildStepEnv)
).toBeUndefined();
});
});

describe(metricsCorsOriginToServeSimArgs, () => {
it('returns no args when no origin is set', () => {
expect(metricsCorsOriginToServeSimArgs(undefined)).toEqual([]);
expect(metricsCorsOriginToServeSimArgs('')).toEqual([]);
});

it('builds one flag per comma-separated origin', () => {
expect(metricsCorsOriginToServeSimArgs('https://expo.dev')).toEqual([
'--metrics-cors-origin',
'https://expo.dev',
]);
expect(metricsCorsOriginToServeSimArgs('https://expo.dev, https://staging.expo.dev')).toEqual([
'--metrics-cors-origin',
'https://expo.dev',
'--metrics-cors-origin',
'https://staging.expo.dev',
]);
});
});

describe(turnIceServersToServeSimArgs, () => {
it('returns no args for an empty ICE server list', () => {
expect(turnIceServersToServeSimArgs([])).toEqual([]);
Expand Down
25 changes: 25 additions & 0 deletions packages/build-tools/src/steps/utils/remoteDeviceRunSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,29 @@ export function getNgrokAuthtokenOrThrow(env: BuildStepEnv): string {
return authtoken;
}

// Optional: the origin(s) allowed to read serve-sim's /metrics stream
// cross-origin (e.g. the expo.dev dashboard). Unset means no cross-origin
// access, which is fine for same-origin/loopback viewers.
export function getMetricsCorsOrigin(env: BuildStepEnv): string | undefined {
return env.EAS_SIMULATOR_METRICS_CORS_ORIGIN || undefined;
}

// serve-sim's `--metrics-cors-origin` flag is repeatable, so a comma-separated
// env value (e.g. prod + staging dashboards) becomes one flag per origin.
export function metricsCorsOriginToServeSimArgs(origin: string | undefined): string[] {
if (!origin) {
return [];
}
const args: string[] = [];
for (const value of origin.split(',')) {
const trimmed = value.trim();
if (trimmed) {
args.push('--metrics-cors-origin', trimmed);
}
}
return args;
}

const TurnIceServersSchema = z.array(
z.object({
urls: z.array(z.string()),
Expand Down Expand Up @@ -344,6 +367,7 @@ export async function startServeSimWithTunnelAsync(
): Promise<{ previewUrl: string; streamUrl: string }> {
logger.info('Launching serve-sim with tunnel.');
const turnArgs = await fetchServeSimTurnArgsAsync(ctx, { env, logger });
const metricsCorsArgs = metricsCorsOriginToServeSimArgs(getMetricsCorsOrigin(env));
const serveSim = spawnDetached({
command: 'npx',
args: [
Expand All @@ -360,6 +384,7 @@ export async function startServeSimWithTunnelAsync(
'--codec',
'webrtc',
...turnArgs,
...metricsCorsArgs,
],
env,
});
Expand Down
Loading