From e2813492eb02a0a77015748b515d076bd9246950 Mon Sep 17 00:00:00 2001 From: Yoli Hodde Date: Wed, 9 Oct 2024 12:30:48 -0700 Subject: [PATCH 1/2] Added example to 'vip sync' --- src/bin/vip-sync.js | 297 ++++++++++++++++++++++---------------------- src/bin/vip.js | 2 +- 2 files changed, 152 insertions(+), 147 deletions(-) diff --git a/src/bin/vip-sync.js b/src/bin/vip-sync.js index 753ee3356..b09ef9b52 100755 --- a/src/bin/vip-sync.js +++ b/src/bin/vip-sync.js @@ -22,182 +22,187 @@ command( { childEnvContext: true, module: 'sync', requireConfirm: 'Are you sure you want to sync from production?', -} ).argv( process.argv, async ( arg, opts ) => { - const api = API(); - let syncing = false; - - await trackEvent( 'sync_command_execute' ); - - try { - await api.mutate( { - mutation: gql` - mutation SyncEnvironmentMutation($input: AppEnvironmentSyncInput) { - syncEnvironment(input: $input) { - environment { - id +} ) + .example( + 'vip @example-app.develop sync', + 'Sync the production environment database of the "example-app" application to the development environment.' + ) + .argv( process.argv, async ( arg, opts ) => { + const api = API(); + let syncing = false; + + await trackEvent( 'sync_command_execute' ); + + try { + await api.mutate( { + mutation: gql` + mutation SyncEnvironmentMutation($input: AppEnvironmentSyncInput) { + syncEnvironment(input: $input) { + environment { + id + } } } - } - `, - variables: { - input: { - id: opts.app.id, - environmentId: opts.env.id, + `, + variables: { + input: { + id: opts.app.id, + environmentId: opts.env.id, + }, }, - }, - } ); - } catch ( error ) { - if ( error.graphQLErrors ) { - let bail = false; - - for ( const err of error.graphQLErrors ) { - if ( err.message !== 'Site is already syncing' ) { - bail = true; - console.log( chalk.red( 'Error:' ), err.message ); + } ); + } catch ( error ) { + if ( error.graphQLErrors ) { + let bail = false; + + for ( const err of error.graphQLErrors ) { + if ( err.message !== 'Site is already syncing' ) { + bail = true; + console.log( chalk.red( 'Error:' ), err.message ); + } } - } - // TODO: Log e + // TODO: Log e - if ( bail ) { - return; + if ( bail ) { + return; + } } + + syncing = true; + await trackEvent( 'sync_command_execute_error', { + error: `Already syncing: ${ error.message }`, + } ); } - syncing = true; - await trackEvent( 'sync_command_execute_error', { - error: `Already syncing: ${ error.message }`, - } ); - } + const sprite = { + count: 0, + sprite: [ '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏' ], + next() { + this.count++; - const sprite = { - count: 0, - sprite: [ '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏' ], - next() { - this.count++; + if ( this.count >= this.sprite.length ) { + this.count = 0; + } - if ( this.count >= this.sprite.length ) { - this.count = 0; - } + return { + value: this.sprite[ this.count ], + done: false, + }; + }, + }; - return { - value: this.sprite[ this.count ], - done: false, - }; - }, - }; - - const application = await app( opts.app.id, appQuery ); - let environment = application.environments.find( env => env.id === opts.env.id ); - - if ( syncing ) { - if ( environment.syncProgress.status === 'running' ) { - console.log( chalk.yellow( 'Note:' ), 'A data sync is already running.' ); - } else { - console.log( chalk.yellow( 'Note:' ), 'Someone recently ran a data sync on this site.' ); - console.log( chalk.yellow( 'Note:' ), 'Please wait a few minutes before trying again.' ); + const application = await app( opts.app.id, appQuery ); + let environment = application.environments.find( env => env.id === opts.env.id ); + + if ( syncing ) { + if ( environment.syncProgress.status === 'running' ) { + console.log( chalk.yellow( 'Note:' ), 'A data sync is already running.' ); + } else { + console.log( chalk.yellow( 'Note:' ), 'Someone recently ran a data sync on this site.' ); + console.log( chalk.yellow( 'Note:' ), 'Please wait a few minutes before trying again.' ); + } } - } - - console.log(); - console.log( ` syncing: ${ chalk.yellow( opts.app.name ) }` ); - console.log( ` from: ${ formatEnvironment( 'production' ) }` ); - console.log( ` to: ${ formatEnvironment( opts.env.type ) }` ); - - let count = 0; - const progress = setInterval( async () => { - if ( count++ % 10 === 0 ) { - // Query the API 1/10 of the time (every 1s) - // The rest of the iterations are just for moving the spinner - api - .query( { - query: gql` - query App($id: Int, $sync: Int) { - app(id: $id) { - id - name - environments { + + console.log(); + console.log( ` syncing: ${ chalk.yellow( opts.app.name ) }` ); + console.log( ` from: ${ formatEnvironment( 'production' ) }` ); + console.log( ` to: ${ formatEnvironment( opts.env.type ) }` ); + + let count = 0; + const progress = setInterval( async () => { + if ( count++ % 10 === 0 ) { + // Query the API 1/10 of the time (every 1s) + // The rest of the iterations are just for moving the spinner + api + .query( { + query: gql` + query App($id: Int, $sync: Int) { + app(id: $id) { id name - defaultDomain - branch - datacenter - syncProgress(sync: $sync) { - status - sync - steps { - name + environments { + id + name + defaultDomain + branch + datacenter + syncProgress(sync: $sync) { status + sync + steps { + name + status + } } } } } - } - `, - fetchPolicy: 'network-only', - variables: { - id: opts.app.id, - sync: environment.syncProgress.sync, - }, - } ) - .then( res => res.data.app ) - .then( _app => { - environment = _app.environments.find( env => env.id === opts.env.id ); - } ); - } + `, + fetchPolicy: 'network-only', + variables: { + id: opts.app.id, + sync: environment.syncProgress.sync, + }, + } ) + .then( res => res.data.app ) + .then( _app => { + environment = _app.environments.find( env => env.id === opts.env.id ); + } ); + } - const marks = { - pending: '○', - running: chalk.blueBright( sprite.next().value ), - success: chalk.green( '✓' ), - failed: chalk.red( '✕' ), - unknown: chalk.yellow( '✕' ), - }; + const marks = { + pending: '○', + running: chalk.blueBright( sprite.next().value ), + success: chalk.green( '✓' ), + failed: chalk.red( '✕' ), + unknown: chalk.yellow( '✕' ), + }; - const out = []; - const steps = environment.syncProgress.steps || []; + const out = []; + const steps = environment.syncProgress.steps || []; - out.push( '' ); + out.push( '' ); - steps.forEach( step => { - if ( step.status === 'pending' ) { - out.push( chalk.dim( ` ${ marks[ step.status ] } ${ step.name }` ) ); - } else { - out.push( ` ${ marks[ step.status ] } ${ step.name }` ); - } - } ); + steps.forEach( step => { + if ( step.status === 'pending' ) { + out.push( chalk.dim( ` ${ marks[ step.status ] } ${ step.name }` ) ); + } else { + out.push( ` ${ marks[ step.status ] } ${ step.name }` ); + } + } ); - out.push( '' ); + out.push( '' ); - switch ( environment.syncProgress.status ) { - case 'running': - out.push( - `${ marks.running } Press ^C to hide progress. Data sync will continue in the background.` - ); - break; + switch ( environment.syncProgress.status ) { + case 'running': + out.push( + `${ marks.running } Press ^C to hide progress. Data sync will continue in the background.` + ); + break; - case 'failed': - clearInterval( progress ); + case 'failed': + clearInterval( progress ); - await trackEvent( 'sync_command_error', { - error: 'API returned `failed` status', - } ); + await trackEvent( 'sync_command_error', { + error: 'API returned `failed` status', + } ); - out.push( `${ marks.failed } Data Sync is finished for ${ opts.app.name }.` ); - out.push( '' ); - break; + out.push( `${ marks.failed } Data Sync is finished for ${ opts.app.name }.` ); + out.push( '' ); + break; - case 'success': - default: - clearInterval( progress ); + case 'success': + default: + clearInterval( progress ); - await trackEvent( 'sync_command_success' ); + await trackEvent( 'sync_command_success' ); - out.push( `${ marks.success } Data Sync is finished for ${ opts.app.name }.` ); - out.push( '' ); - break; - } + out.push( `${ marks.success } Data Sync is finished for ${ opts.app.name }.` ); + out.push( '' ); + break; + } - stdout( out.join( '\n' ) ); - }, 100 ); -} ); + stdout( out.join( '\n' ) ); + }, 100 ); + } ); diff --git a/src/bin/vip.js b/src/bin/vip.js index 35d474a2a..7888cbb9b 100755 --- a/src/bin/vip.js +++ b/src/bin/vip.js @@ -40,7 +40,7 @@ const runCmd = async function () { .command( 'search-replace', 'Perform search and replace tasks on files' ) .command( 'slowlogs', 'Retrieve MySQL slow query logs from an environment.' ) .command( 'db', "Access an environment's database." ) - .command( 'sync', 'Sync production to a development environment' ) + .command( 'sync', 'Sync a database from production to a non-production environment.' ) .command( 'whoami', 'Retrieve details about the current authenticated VIP-CLI user.' ) .command( 'validate', 'Validate your VIP application and environment' ) .command( 'wp', 'Run WP CLI commands against an environment' ); From e7ebf23bf5e8368d812b2a6d96a3d443158f7e22 Mon Sep 17 00:00:00 2001 From: Yoli Hodde Date: Wed, 9 Oct 2024 12:50:03 -0700 Subject: [PATCH 2/2] Addressing feedback --- src/bin/vip-sync.js | 2 +- src/bin/vip.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/vip-sync.js b/src/bin/vip-sync.js index b09ef9b52..45c093597 100755 --- a/src/bin/vip-sync.js +++ b/src/bin/vip-sync.js @@ -25,7 +25,7 @@ command( { } ) .example( 'vip @example-app.develop sync', - 'Sync the production environment database of the "example-app" application to the development environment.' + 'Sync the production environment database of the "example-app" application to the develop environment.' ) .argv( process.argv, async ( arg, opts ) => { const api = API(); diff --git a/src/bin/vip.js b/src/bin/vip.js index 7888cbb9b..5a5543576 100755 --- a/src/bin/vip.js +++ b/src/bin/vip.js @@ -40,7 +40,7 @@ const runCmd = async function () { .command( 'search-replace', 'Perform search and replace tasks on files' ) .command( 'slowlogs', 'Retrieve MySQL slow query logs from an environment.' ) .command( 'db', "Access an environment's database." ) - .command( 'sync', 'Sync a database from production to a non-production environment.' ) + .command( 'sync', 'Sync the database from production to a non-production environment.' ) .command( 'whoami', 'Retrieve details about the current authenticated VIP-CLI user.' ) .command( 'validate', 'Validate your VIP application and environment' ) .command( 'wp', 'Run WP CLI commands against an environment' );