From 4b650616d1ecfc9ec0796dd304c4baa918ac04e5 Mon Sep 17 00:00:00 2001 From: szdziedzic Date: Thu, 23 Apr 2026 11:30:42 +0200 Subject: [PATCH] [eas-cli] add eas simulator:stop command --- .../eas-cli/src/commands/simulator/stop.ts | 46 +++++++++++++++++++ packages/eas-cli/src/graphql/generated.ts | 7 +++ .../mutations/DeviceRunSessionMutation.ts | 26 +++++++++++ 3 files changed, 79 insertions(+) create mode 100644 packages/eas-cli/src/commands/simulator/stop.ts diff --git a/packages/eas-cli/src/commands/simulator/stop.ts b/packages/eas-cli/src/commands/simulator/stop.ts new file mode 100644 index 0000000000..7d216f1b14 --- /dev/null +++ b/packages/eas-cli/src/commands/simulator/stop.ts @@ -0,0 +1,46 @@ +import { Flags } from '@oclif/core'; + +import EasCommand from '../../commandUtils/EasCommand'; +import { EASNonInteractiveFlag } from '../../commandUtils/flags'; +import { DeviceRunSessionMutation } from '../../graphql/mutations/DeviceRunSessionMutation'; +import { ora } from '../../ora'; + +export default class SimulatorStop extends EasCommand { + static override hidden = true; + static override description = + '[EXPERIMENTAL] stop a remote simulator session on EAS by its device run session ID'; + + static override flags = { + id: Flags.string({ + description: 'Device run session ID', + required: true, + }), + ...EASNonInteractiveFlag, + }; + + static override contextDefinition = { + ...this.ContextOptions.LoggedIn, + }; + + async runAsync(): Promise { + const { flags } = await this.parse(SimulatorStop); + + const { + loggedIn: { graphqlClient }, + } = await this.getContextAsync(SimulatorStop, { + nonInteractive: flags['non-interactive'], + }); + + const stopSpinner = ora(`🛑 Stopping device run session ${flags.id}`).start(); + try { + const session = await DeviceRunSessionMutation.stopDeviceRunSessionAsync( + graphqlClient, + flags.id + ); + stopSpinner.succeed(`🎉 Device run session ${session.id} is ${session.status.toLowerCase()}`); + } catch (err) { + stopSpinner.fail(`Failed to stop device run session ${flags.id}`); + throw err; + } + } +} diff --git a/packages/eas-cli/src/graphql/generated.ts b/packages/eas-cli/src/graphql/generated.ts index 320ada9579..bdded1c0a4 100644 --- a/packages/eas-cli/src/graphql/generated.ts +++ b/packages/eas-cli/src/graphql/generated.ts @@ -11754,6 +11754,13 @@ export type CreateDeviceRunSessionMutationVariables = Exact<{ export type CreateDeviceRunSessionMutation = { __typename?: 'RootMutation', deviceRunSession: { __typename?: 'DeviceRunSessionMutation', createDeviceRunSession: { __typename?: 'DeviceRunSession', id: string, status: DeviceRunSessionStatus, app: { __typename?: 'App', id: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, turtleJobRun?: { __typename?: 'JobRun', id: string } | null } } }; +export type StopDeviceRunSessionMutationVariables = Exact<{ + deviceRunSessionId: Scalars['ID']['input']; +}>; + + +export type StopDeviceRunSessionMutation = { __typename?: 'RootMutation', deviceRunSession: { __typename?: 'DeviceRunSessionMutation', stopDeviceRunSession: { __typename?: 'DeviceRunSession', id: string, status: DeviceRunSessionStatus } } }; + export type CreateEnvironmentSecretForAccountMutationVariables = Exact<{ input: CreateEnvironmentSecretInput; accountId: Scalars['String']['input']; diff --git a/packages/eas-cli/src/graphql/mutations/DeviceRunSessionMutation.ts b/packages/eas-cli/src/graphql/mutations/DeviceRunSessionMutation.ts index 7de3db2018..39d18637ce 100644 --- a/packages/eas-cli/src/graphql/mutations/DeviceRunSessionMutation.ts +++ b/packages/eas-cli/src/graphql/mutations/DeviceRunSessionMutation.ts @@ -6,6 +6,8 @@ import { CreateDeviceRunSessionInput, CreateDeviceRunSessionMutation, CreateDeviceRunSessionMutationVariables, + StopDeviceRunSessionMutation, + StopDeviceRunSessionMutationVariables, } from '../generated'; export const DeviceRunSessionMutation = { @@ -44,4 +46,28 @@ export const DeviceRunSessionMutation = { ); return data.deviceRunSession.createDeviceRunSession; }, + async stopDeviceRunSessionAsync( + graphqlClient: ExpoGraphqlClient, + deviceRunSessionId: string + ): Promise { + const data = await withErrorHandlingAsync( + graphqlClient + .mutation( + gql` + mutation StopDeviceRunSessionMutation($deviceRunSessionId: ID!) { + deviceRunSession { + stopDeviceRunSession(deviceRunSessionId: $deviceRunSessionId) { + id + status + } + } + } + `, + { deviceRunSessionId }, + { noRetry: true } + ) + .toPromise() + ); + return data.deviceRunSession.stopDeviceRunSession; + }, };