@@ -13,6 +13,20 @@ import {
1313} from './migrate' ;
1414
1515describe ( 'cli/commands/migrate' , ( ) => {
16+ const withConvexDeployKey = async (
17+ deployKey : string ,
18+ run : ( ) => Promise < void >
19+ ) => {
20+ const originalDeployKey = process . env . CONVEX_DEPLOY_KEY ;
21+ process . env . CONVEX_DEPLOY_KEY = deployKey ;
22+
23+ try {
24+ await run ( ) ;
25+ } finally {
26+ process . env . CONVEX_DEPLOY_KEY = originalDeployKey ;
27+ }
28+ } ;
29+
1630 test ( 'parseMigrateCommandArgs parses create/list/up/down/status/cancel shapes' , ( ) => {
1731 expect ( parseMigrateCommandArgs ( [ 'create' , 'Add' , 'field' ] ) ) . toEqual ( {
1832 subcommand : 'create' ,
@@ -254,4 +268,128 @@ describe('cli/commands/migrate', () => {
254268 expect ( calls ) . toHaveLength ( 2 ) ;
255269 expect ( calls [ 1 ] ?. args ) . toContain ( 'generated/server:migrationStatus' ) ;
256270 } ) ;
271+
272+ test ( 'handleMigrateCommand(up) forwards ambient Convex deployment env for convex backend' , async ( ) => {
273+ const calls : Array < {
274+ args : string [ ] ;
275+ env : Record < string , string | undefined > ;
276+ } > = [ ] ;
277+ const execaStub = mock (
278+ async ( _cmd : string , args : string [ ] , options ?: { env ?: unknown } ) => {
279+ calls . push ( {
280+ args,
281+ env : ( options ?. env ?? { } ) as Record < string , string | undefined > ,
282+ } ) ;
283+ return {
284+ exitCode : 0 ,
285+ stdout : `${ JSON . stringify ( { status : 'noop' } ) } \n` ,
286+ stderr : '' ,
287+ } as any ;
288+ }
289+ ) ;
290+ const loadConfigStub = mock ( ( ) => {
291+ const config = createDefaultConfig ( ) ;
292+ config . deploy . migrations . wait = false ;
293+ return config ;
294+ } ) ;
295+
296+ await withConvexDeployKey ( 'prod:demo|secret' , async ( ) => {
297+ const exitCode = await handleMigrateCommand (
298+ [ 'migrate' , 'up' , '--prod' , '--yes' ] ,
299+ {
300+ realConvex : '/fake/convex/main.js' ,
301+ execa : execaStub as any ,
302+ loadCliConfig : loadConfigStub as any ,
303+ }
304+ ) ;
305+
306+ expect ( exitCode ) . toBe ( 0 ) ;
307+ } ) ;
308+
309+ expect ( calls ) . toHaveLength ( 1 ) ;
310+ expect ( calls [ 0 ] ?. args ) . toContain ( '--prod' ) ;
311+ expect ( calls [ 0 ] ?. env ) . toEqual (
312+ expect . objectContaining ( {
313+ CONVEX_DEPLOY_KEY : 'prod:demo|secret' ,
314+ } )
315+ ) ;
316+ } ) ;
317+
318+ test ( 'handleMigrateCommand(status) forwards ambient Convex deployment env for convex backend' , async ( ) => {
319+ const calls : Record < string , string | undefined > [ ] = [ ] ;
320+ const execaStub = mock (
321+ async (
322+ _cmd : string ,
323+ _args : string [ ] ,
324+ options ?: { env ?: Record < string , string | undefined > }
325+ ) => {
326+ calls . push ( options ?. env ?? { } ) ;
327+ return {
328+ exitCode : 0 ,
329+ stdout : '{}\n' ,
330+ stderr : '' ,
331+ } as any ;
332+ }
333+ ) ;
334+ const loadConfigStub = mock ( ( ) => createDefaultConfig ( ) ) ;
335+
336+ await withConvexDeployKey ( 'prod:demo|secret' , async ( ) => {
337+ const exitCode = await handleMigrateCommand (
338+ [ 'migrate' , 'status' , '--prod' ] ,
339+ {
340+ realConvex : '/fake/convex/main.js' ,
341+ execa : execaStub as any ,
342+ loadCliConfig : loadConfigStub as any ,
343+ }
344+ ) ;
345+
346+ expect ( exitCode ) . toBe ( 0 ) ;
347+ } ) ;
348+
349+ expect ( calls ) . toHaveLength ( 1 ) ;
350+ expect ( calls [ 0 ] ) . toEqual (
351+ expect . objectContaining ( {
352+ CONVEX_DEPLOY_KEY : 'prod:demo|secret' ,
353+ } )
354+ ) ;
355+ } ) ;
356+
357+ test ( 'handleMigrateCommand(cancel) forwards ambient Convex deployment env for convex backend' , async ( ) => {
358+ const calls : Record < string , string | undefined > [ ] = [ ] ;
359+ const execaStub = mock (
360+ async (
361+ _cmd : string ,
362+ _args : string [ ] ,
363+ options ?: { env ?: Record < string , string | undefined > }
364+ ) => {
365+ calls . push ( options ?. env ?? { } ) ;
366+ return {
367+ exitCode : 0 ,
368+ stdout : '{}\n' ,
369+ stderr : '' ,
370+ } as any ;
371+ }
372+ ) ;
373+ const loadConfigStub = mock ( ( ) => createDefaultConfig ( ) ) ;
374+
375+ await withConvexDeployKey ( 'prod:demo|secret' , async ( ) => {
376+ const exitCode = await handleMigrateCommand (
377+ [ 'migrate' , 'cancel' , '--prod' , '--run-id' , 'mr_123' ] ,
378+ {
379+ realConvex : '/fake/convex/main.js' ,
380+ execa : execaStub as any ,
381+ loadCliConfig : loadConfigStub as any ,
382+ }
383+ ) ;
384+
385+ expect ( exitCode ) . toBe ( 0 ) ;
386+ } ) ;
387+
388+ expect ( calls ) . toHaveLength ( 1 ) ;
389+ expect ( calls [ 0 ] ) . toEqual (
390+ expect . objectContaining ( {
391+ CONVEX_DEPLOY_KEY : 'prod:demo|secret' ,
392+ } )
393+ ) ;
394+ } ) ;
257395} ) ;
0 commit comments