@@ -11,6 +11,41 @@ type SandboxContext = GlobalOptions & {
1111 org ?: string ;
1212} ;
1313
14+ export const sandboxNewCommand = new Command < SandboxContext > ( )
15+ . description ( "Create a new sandbox in an organization" )
16+ . action ( async ( options ) => {
17+ const org = await ensureOrg ( options ) ;
18+ const client = createTrpcClient ( options . debug , options . endpoint ) ;
19+
20+ // deno-lint-ignore no-explicit-any
21+ const token = await ( client . orgs as any ) . accessTokens . create . mutate ( {
22+ org,
23+ description : "$$DENO_DEPLOY_CLI_SSH_TOKEN$$" ,
24+ expiresAt : new Date ( Date . now ( ) + 1000 * 60 * 60 ) . toISOString ( ) , // 1 hour
25+ } ) ;
26+
27+ const sandbox = await Sandbox . create ( {
28+ debug : options . debug ,
29+ token : token . token ,
30+ } ) ;
31+
32+ const success = await sshIntoSandbox ( sandbox ) ;
33+ const stopMessage = "Stopping the sandbox..." ;
34+ if ( success ) {
35+ // Closes the sandbox only when ssh session was established and finished successfully
36+ await sandbox . close ( ) ;
37+ console . log ( stopMessage ) ;
38+ } else {
39+ // Otherwise, keep the sandbox running and wait for Ctrl+C
40+ console . log ( "\nCtrl+C to stop the sandbox." ) ;
41+ Deno . addSignalListener ( "SIGINT" , async ( ) => {
42+ console . log ( "\n" + stopMessage ) ;
43+ await sandbox . close ( ) ;
44+ Deno . exit ( ) ;
45+ } ) ;
46+ }
47+ } ) ;
48+
1449export const sandboxListCommand = new Command < SandboxContext > ( )
1550 . description ( "List all sandboxes in an organization" )
1651 . action ( async ( options ) => {
@@ -130,37 +165,7 @@ export const sandboxSshCommand = new Command<SandboxContext>()
130165 debug : options . debug ,
131166 token : token . token ,
132167 } ) ;
133-
134- const ssh = await sandbox . exposeSsh ( ) ;
135-
136- const connectInfo = ssh . username + "@" + ssh . hostname ;
137-
138- const which = await new Deno . Command ( "which" , {
139- args : [ "ssh" ] ,
140- stdout : "null" ,
141- stderr : "null" ,
142- } ) . output ( ) ;
143-
144- if ( which . success ) {
145- // If ssh is available, directly spawn ssh process
146- console . log ( `ssh ${ connectInfo } ` ) ;
147- const command = new Deno . Command ( "ssh" , {
148- args : [ connectInfo ] ,
149- stdin : "inherit" ,
150- stdout : "inherit" ,
151- stderr : "inherit" ,
152- } ) ;
153-
154- const _sshProcess = command . spawn ( ) ;
155- } else {
156- // Fallback: just print the connection info
157- console . log (
158- `Started ssh session. You can now connect to ${ magenta ( connectInfo ) }
159-
160- Example:
161- ssh ${ connectInfo } ` ,
162- ) ;
163- }
168+ await sshIntoSandbox ( sandbox ) ;
164169 } ) ;
165170
166171async function ensureOrg ( options : SandboxContext ) {
@@ -176,6 +181,43 @@ async function ensureOrg(options: SandboxContext) {
176181 ) ) . org ;
177182}
178183
184+ /**
185+ * Make an ssh connection to the running sandbox. Returns true if ssh session
186+ * was successfully created and finished, false when ssh is not available and
187+ * connection info was printed instead.
188+ */
189+ async function sshIntoSandbox ( sandbox : Sandbox ) : Promise < boolean > {
190+ const ssh = await sandbox . exposeSsh ( ) ;
191+ const connectInfo = ssh . username + "@" + ssh . hostname ;
192+
193+ const which = await new Deno . Command ( "which" , {
194+ args : [ "ssh_" ] ,
195+ stdout : "null" ,
196+ stderr : "null" ,
197+ } ) . output ( ) ;
198+ if ( which . success ) {
199+ console . log ( `ssh ${ connectInfo } ` ) ;
200+ const command = new Deno . Command ( "ssh" , {
201+ args : [ connectInfo ] ,
202+ stdin : "inherit" ,
203+ stdout : "inherit" ,
204+ stderr : "inherit" ,
205+ } ) ;
206+ const sshProcess = await command . spawn ( ) ;
207+ await sshProcess . output ( ) ;
208+ await sandbox . close ( ) ;
209+ return true ;
210+ } else {
211+ console . log (
212+ `Started ssh session. You can now connect to ${ magenta ( connectInfo ) }
213+
214+ Example:
215+ ssh ${ connectInfo } ` ,
216+ ) ;
217+ return false ;
218+ }
219+ }
220+
179221/**
180222 * Format duration in ms to human readable string
181223 *
0 commit comments