Skip to content

Commit fc7ba9a

Browse files
committed
Finalize commander move
1 parent ce6a987 commit fc7ba9a

File tree

3 files changed

+84
-4
lines changed

3 files changed

+84
-4
lines changed

src/bin/vip-dev-env-exec.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@ import UserError from '../lib/user-error';
1717

1818
const exampleUsage = 'vip dev-env exec';
1919
const usage = 'vip dev-env exec';
20+
const ENV_UP_CHECK_ATTEMPTS = 5;
21+
const ENV_UP_CHECK_DELAY_MS = 1500;
22+
23+
const sleep = ms => new Promise( resolve => setTimeout( resolve, ms ) );
24+
25+
async function waitForEnvironmentReadiness( lando, slug ) {
26+
const instancePath = getEnvironmentPath( slug );
27+
28+
for ( let attempt = 1; attempt <= ENV_UP_CHECK_ATTEMPTS; attempt++ ) {
29+
if ( await isEnvUp( lando, instancePath ) ) {
30+
return true;
31+
}
32+
33+
if ( attempt < ENV_UP_CHECK_ATTEMPTS ) {
34+
await sleep( ENV_UP_CHECK_DELAY_MS );
35+
}
36+
}
37+
38+
return false;
39+
}
2040

2141
const examples = [
2242
{
@@ -80,7 +100,7 @@ command( {
80100
}
81101

82102
if ( ! opt.force ) {
83-
const isUp = await isEnvUp( lando, getEnvironmentPath( slug ) );
103+
const isUp = await waitForEnvironmentReadiness( lando, slug );
84104
if ( ! isUp ) {
85105
throw new UserError(
86106
'A WP-CLI command can only be executed on a running local environment.'

src/lib/cli/command.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ process.on( 'unhandledRejection', uncaughtError );
3838
let _opts = {};
3939

4040
let alreadyConfirmedDebugAttachment = false;
41+
const RESERVED_AUTO_SHORT_ALIASES = new Set( [ 'h', 'v', 'd' ] );
4142

4243
function normalizeUsage( program, usage ) {
4344
if ( ! usage ) {
@@ -57,12 +58,29 @@ function normalizeUsage( program, usage ) {
5758
}
5859
}
5960

60-
function createOptionDefinition( name, description, defaultValue, parseFn ) {
61+
function createOptionDefinition( name, description, defaultValue, parseFn, usedShortNames ) {
6162
const isArray = Array.isArray( name );
6263
const shortName = isArray ? name[ 0 ] : null;
6364
const longName = isArray ? name[ 1 ] : name;
6465
const normalizedLongName = String( longName ).trim().replace( /^--?/, '' );
65-
const normalizedShortName = shortName ? String( shortName ).trim().replace( /^-/, '' ) : null;
66+
const explicitShortName = shortName ? String( shortName ).trim().replace( /^-/, '' ) : null;
67+
let normalizedShortName = explicitShortName;
68+
69+
if ( ! normalizedShortName ) {
70+
const autoShortName = normalizedLongName.charAt( 0 );
71+
const canUseAutoShortName =
72+
autoShortName &&
73+
! RESERVED_AUTO_SHORT_ALIASES.has( autoShortName ) &&
74+
! usedShortNames.has( autoShortName );
75+
76+
if ( canUseAutoShortName ) {
77+
normalizedShortName = autoShortName;
78+
}
79+
}
80+
81+
if ( normalizedShortName ) {
82+
usedShortNames.add( normalizedShortName );
83+
}
6684
const isBooleanOption = typeof defaultValue === 'boolean';
6785
const usesOptionalValue = ! isBooleanOption;
6886
const parseOptionValue = value => {
@@ -113,6 +131,7 @@ class CommanderArgsCompat {
113131
};
114132
this.sub = [];
115133
this.examplesList = [];
134+
this.usedShortNames = new Set();
116135
this._opts = opts;
117136
this.program = new Command();
118137
this.program.allowUnknownOption( true );
@@ -122,7 +141,13 @@ class CommanderArgsCompat {
122141
}
123142

124143
option( name, description, defaultValue, parseFn ) {
125-
const definition = createOptionDefinition( name, description, defaultValue, parseFn );
144+
const definition = createOptionDefinition(
145+
name,
146+
description,
147+
defaultValue,
148+
parseFn,
149+
this.usedShortNames
150+
);
126151
const { flags, parser } = definition;
127152

128153
if ( parser && defaultValue !== undefined ) {

src/lib/dev-environment/dev-environment-core.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
LandoLogsOptions,
2929
LandoExecOptions,
3030
getProxyContainer,
31+
isEnvUp,
3132
removeProxyCache,
3233
} from './dev-environment-lando';
3334
import { AppEnvironment } from '../../graphqlTypes';
@@ -99,6 +100,25 @@ interface WordPressTag {
99100
prerelease: boolean;
100101
}
101102

103+
const STARTUP_READY_ATTEMPTS = 6;
104+
const STARTUP_READY_DELAY_MS = 2000;
105+
106+
const sleep = ( ms: number ): Promise< void > => new Promise( resolve => setTimeout( resolve, ms ) );
107+
108+
async function waitForEnvironmentToBeUp( lando: Lando, instancePath: string ): Promise< boolean > {
109+
for ( let attempt = 1; attempt <= STARTUP_READY_ATTEMPTS; attempt++ ) {
110+
if ( await isEnvUp( lando, instancePath ) ) {
111+
return true;
112+
}
113+
114+
if ( attempt < STARTUP_READY_ATTEMPTS ) {
115+
await sleep( STARTUP_READY_DELAY_MS );
116+
}
117+
}
118+
119+
return false;
120+
}
121+
102122
export interface PostStartOptions {
103123
openVSCode: boolean;
104124
openCursor: boolean;
@@ -141,6 +161,21 @@ export async function startEnvironment(
141161
await landoRebuild( lando, instancePath );
142162
}
143163

164+
let isEnvironmentUp = await waitForEnvironmentToBeUp( lando, instancePath );
165+
if ( ! isEnvironmentUp ) {
166+
// A second startup pass helps recover after Docker network auto-cleanup edge cases.
167+
await landoStart( lando, instancePath );
168+
isEnvironmentUp = await waitForEnvironmentToBeUp( lando, instancePath );
169+
}
170+
171+
if ( ! isEnvironmentUp ) {
172+
throw new UserError(
173+
`Environment "${ slug }" did not reach a running state. Please try "${ chalk.bold(
174+
`vip dev-env start --slug ${ slug }`
175+
) }" again.`
176+
);
177+
}
178+
144179
await printEnvironmentInfo( lando, slug, { extended: false } );
145180
}
146181

0 commit comments

Comments
 (0)