fix(shorebird_cli): don't prompt users for confirmation if we can't accept input via stdin (#1845)

This commit is contained in:
Bryan Oltman
2024-04-01 16:01:11 -04:00
committed by GitHub
parent 0e14f8b4f3
commit 7be7f4e9c8
23 changed files with 112 additions and 51 deletions
@@ -154,7 +154,7 @@ Please make sure you are running "shorebird init" from within your Flutter proje
final String appId;
Map<String, String>? flavors;
try {
final needsConfirmation = !force && !shorebirdEnv.isRunningOnCI;
final needsConfirmation = !force && shorebirdEnv.canAcceptUserInput;
final pubspecName = shorebirdEnv.getPubspecYaml()!.name;
final displayName = needsConfirmation
? logger.prompt(
@@ -265,8 +265,7 @@ ${summary.join('\n')}
''',
);
final needsConfirmation = !shorebirdEnv.isRunningOnCI;
if (needsConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -368,8 +368,7 @@ ${summary.join('\n')}
''',
);
final needsConfirmation = !shorebirdEnv.isRunningOnCI;
if (needsConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -397,8 +397,7 @@ ${summary.join('\n')}
''',
);
final needsConfirmation = !shorebirdEnv.isRunningOnCI;
if (needsConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -316,8 +316,7 @@ ${summary.join('\n')}
''',
);
final needsConfirmation = !shorebirdEnv.isRunningOnCI;
if (needsConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -194,8 +194,7 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to create a new release!'))}
${summary.join('\n')}
''');
final needsConfirmation = !shorebirdEnv.isRunningOnCI;
if (needsConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -253,8 +253,7 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to create a new release!'))}
${summary.join('\n')}
''');
final needConfirmation = !shorebirdEnv.isRunningOnCI;
if (needConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -282,8 +282,7 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to create a new release!'))}
${summary.join('\n')}
''');
final needConfirmation = !shorebirdEnv.isRunningOnCI;
if (needConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -174,8 +174,7 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to create a new release!'))}
${summary.join('\n')}
''');
final needsConfirmation = !shorebirdEnv.isRunningOnCI;
if (needsConfirmation) {
if (shorebirdEnv.canAcceptUserInput) {
final confirm = logger.confirm('Would you like to continue?');
if (!confirm) {
@@ -106,7 +106,7 @@ If you don't know why you're seeing this error, visit our troublshooting page at
);
if (!allowNativeChanges) {
if (shorebirdEnv.isRunningOnCI) {
if (!shorebirdEnv.canAcceptUserInput) {
throw UnpatchableChangeException();
}
@@ -128,7 +128,7 @@ If you don't know why you're seeing this error, visit our troublshooting page at
);
if (!allowAssetChanges) {
if (shorebirdEnv.isRunningOnCI) {
if (!shorebirdEnv.canAcceptUserInput) {
throw UnpatchableChangeException();
}
@@ -198,6 +198,9 @@ class ShorebirdEnv {
}
}
/// Whether the CLI can accept user input via stdin.
bool get canAcceptUserInput => stdin.hasTerminal && !isRunningOnCI;
/// Whether platform.environment indicates that we are running on a CI
/// platform. This implementation is intended to behave similar to the Flutter
/// tool's:
@@ -119,7 +119,7 @@ environment:
).thenReturn(Pubspec.parse(pubspecYamlContent));
when(() => shorebirdEnv.hasShorebirdYaml).thenReturn(false);
when(() => shorebirdEnv.pubspecContainsShorebirdYaml).thenReturn(false);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(
() => shorebirdValidator.validatePreconditions(
checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'),
@@ -190,8 +190,8 @@ Please make sure you are running "shorebird init" from within your Flutter proje
expect(exitCode, ExitCode.software.code);
});
test('does not prompt for name when running on ci', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt for name when unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
await runWithOverrides(command.run);
verifyNever(
() => logger.prompt(any(), defaultValue: any(named: 'defaultValue')),
@@ -222,7 +222,7 @@ void main() {
).thenReturn(androidPackageName);
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(
() => shorebirdProcess.run(
'flutter',
@@ -928,8 +928,8 @@ Please re-run the release command for this version or create a new release.'''),
).called(1);
});
test('does not prompt if running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt if unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
setUpProjectRootArtifacts();
final exitCode = await runWithOverrides(command.run);
@@ -389,7 +389,7 @@ flutter:
when(() => platform.operatingSystem).thenReturn(operatingSystem);
when(() => platform.operatingSystemVersion)
.thenReturn(operatingSystemVersion);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
});
test('has a description', () {
@@ -1079,8 +1079,8 @@ flavors:
expect(exitCode, ExitCode.success.code);
});
test('does not prompt if running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt if unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
setUpProjectRoot();
setUpProjectRootArtifacts();
@@ -460,7 +460,7 @@ flutter:
).thenReturn(analyzeSnapshotFile.path);
when(() => shorebirdEnv.flutterRevision)
.thenReturn(preLinkerFlutterRevision);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(
() => shorebirdFlutter.installRevision(
revision: any(named: 'revision'),
@@ -1692,8 +1692,8 @@ base_url: $baseUrl''',
await runWithOverrides(command.run);
});
test('does not prompt if running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt if unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
setUpProjectRoot();
setUpProjectRootArtifacts();
@@ -359,7 +359,7 @@ flutter:
);
return shorebirdEnv;
});
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(
() => aotBuildProcessResult.exitCode,
).thenReturn(ExitCode.success.code);
@@ -1010,8 +1010,8 @@ Please re-run the release command for this version or create a new release.'''),
).called(1);
});
test('does not prompt if running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt if unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
setUpProjectRoot();
setUpProjectRootArtifacts();
@@ -185,7 +185,7 @@ void main() {
() => shorebirdEnv.androidPackageName,
).thenReturn(androidPackageName);
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(
() => shorebirdFlutter.getVersionAndRevision(),
@@ -462,8 +462,9 @@ $exception''',
verify(() => logger.info('Aborting.')).called(1);
});
test('does not prompt for confirmation when running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt for confirmation if unable to accpet user input',
() async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
setUpProjectRootArtifacts();
final exitCode = await runWithOverrides(command.run);
expect(exitCode, ExitCode.success.code);
@@ -154,7 +154,7 @@ void main() {
() => shorebirdEnv.getShorebirdProjectRoot(),
).thenReturn(projectRoot);
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(
() => shorebirdFlutter.getVersionAndRevision(),
@@ -795,8 +795,8 @@ Either run `flutter pub get` manually, or follow the steps in ${link(uri: Uri.pa
);
});
test('does not prompt if running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt if unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
final exitCode = await runWithOverrides(command.run);
@@ -220,7 +220,7 @@ flutter:
() => shorebirdEnv.getShorebirdProjectRoot(),
).thenReturn(projectRoot);
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(
() => shorebirdEnv.copyWith(
flutterRevisionOverride: any(named: 'flutterRevisionOverride'),
@@ -1065,8 +1065,8 @@ flavors:
);
});
test('does not prompt if running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt if unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
setUpProjectRoot();
final exitCode = await runWithOverrides(command.run);
@@ -172,7 +172,7 @@ flutter:
when(
() => shorebirdEnv.getShorebirdProjectRoot(),
).thenReturn(projectRoot);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
when(
() => shorebirdFlutter.getVersionAndRevision(),
@@ -490,8 +490,9 @@ $exception''',
);
});
test('does not prompt for confirmation when running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt for confirmation if unable to accept user input',
() async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
when(() => argResults['release-version']).thenReturn(version);
setUpProjectRoot();
@@ -141,6 +141,8 @@ class MockShorebirdVersion extends Mock implements ShorebirdVersion {}
class MockShorebirdYaml extends Mock implements ShorebirdYaml {}
class MockStdin extends Mock implements Stdin {}
class MockValidator extends Mock implements Validator {}
class MockXcodeBuild extends Mock implements XcodeBuild {}
@@ -76,7 +76,7 @@ void main() {
when(() => logger.confirm(any())).thenReturn(true);
when(() => logger.progress(any())).thenReturn(progress);
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
when(() => assetsFileSetDiff.prettyString)
.thenReturn(assetsDiffPrettyString);
@@ -193,8 +193,8 @@ void main() {
verify(() => logger.confirm('Continue anyways?')).called(1);
});
test('does not prompt when running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt when unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
await expectLater(
() => runWithOverrides(
@@ -289,8 +289,8 @@ void main() {
verify(() => logger.confirm('Continue anyways?')).called(1);
});
test('does not prompt when running on CI', () async {
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
test('does not prompt when unable to accept user input', () async {
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(false);
await expectLater(
() => runWithOverrides(
@@ -550,6 +550,68 @@ base_url: https://example.com''');
});
});
group('canAcceptUserInput', () {
late Stdin stdin;
setUp(() {
stdin = MockStdin();
});
group('when stdin has terminal', () {
setUp(() {
when(() => stdin.hasTerminal).thenReturn(true);
});
group('when not running on CI', () {
setUp(() {
when(() => platform.environment).thenReturn({});
});
test('returns true', () {
expect(
IOOverrides.runZoned(
() => runWithOverrides(() => shorebirdEnv.canAcceptUserInput),
stdin: () => stdin,
),
isTrue,
);
});
});
group('when running on CI', () {
setUp(() {
when(() => platform.environment).thenReturn({'CI': ''});
});
test('returns false', () {
expect(
IOOverrides.runZoned(
() => runWithOverrides(() => shorebirdEnv.canAcceptUserInput),
stdin: () => stdin,
),
isFalse,
);
});
});
});
group('when stdin has terminal', () {
setUp(() {
when(() => stdin.hasTerminal).thenReturn(false);
});
test('returns true', () {
expect(
IOOverrides.runZoned(
() => runWithOverrides(() => shorebirdEnv.canAcceptUserInput),
stdin: () => stdin,
),
isFalse,
);
});
});
});
group('isRunningOnCI', () {
test('returns true if BOT variable is "true"', () {
when(() => platform.environment).thenReturn({