diff --git a/packages/shorebird_cli/lib/src/commands/init_command.dart b/packages/shorebird_cli/lib/src/commands/init_command.dart index b7cc24faa..b87abb775 100644 --- a/packages/shorebird_cli/lib/src/commands/init_command.dart +++ b/packages/shorebird_cli/lib/src/commands/init_command.dart @@ -154,7 +154,7 @@ Please make sure you are running "shorebird init" from within your Flutter proje final String appId; Map? flavors; try { - final needsConfirmation = !force && !shorebirdEnv.isRunningOnCI; + final needsConfirmation = !force && shorebirdEnv.canAcceptUserInput; final pubspecName = shorebirdEnv.getPubspecYaml()!.name; final displayName = needsConfirmation ? logger.prompt( diff --git a/packages/shorebird_cli/lib/src/commands/patch/patch_aar_command.dart b/packages/shorebird_cli/lib/src/commands/patch/patch_aar_command.dart index 29a3b732e..ad3b15c6e 100644 --- a/packages/shorebird_cli/lib/src/commands/patch/patch_aar_command.dart +++ b/packages/shorebird_cli/lib/src/commands/patch/patch_aar_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart b/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart index 10cf12fc3..41a669e68 100644 --- a/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart +++ b/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart b/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart index d5e2d19e3..145908055 100644 --- a/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart +++ b/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/commands/patch/patch_ios_framework_command.dart b/packages/shorebird_cli/lib/src/commands/patch/patch_ios_framework_command.dart index 54cf2d798..7393d9f96 100644 --- a/packages/shorebird_cli/lib/src/commands/patch/patch_ios_framework_command.dart +++ b/packages/shorebird_cli/lib/src/commands/patch/patch_ios_framework_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/commands/release/release_aar_command.dart b/packages/shorebird_cli/lib/src/commands/release/release_aar_command.dart index 6da27312c..c62a21074 100644 --- a/packages/shorebird_cli/lib/src/commands/release/release_aar_command.dart +++ b/packages/shorebird_cli/lib/src/commands/release/release_aar_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/commands/release/release_android_command.dart b/packages/shorebird_cli/lib/src/commands/release/release_android_command.dart index daf8d57bc..907aab26c 100644 --- a/packages/shorebird_cli/lib/src/commands/release/release_android_command.dart +++ b/packages/shorebird_cli/lib/src/commands/release/release_android_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/commands/release/release_ios_command.dart b/packages/shorebird_cli/lib/src/commands/release/release_ios_command.dart index 4aca8b92f..93a7e07a0 100644 --- a/packages/shorebird_cli/lib/src/commands/release/release_ios_command.dart +++ b/packages/shorebird_cli/lib/src/commands/release/release_ios_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/commands/release/release_ios_framework_command.dart b/packages/shorebird_cli/lib/src/commands/release/release_ios_framework_command.dart index 95d2221f2..5c116c195 100644 --- a/packages/shorebird_cli/lib/src/commands/release/release_ios_framework_command.dart +++ b/packages/shorebird_cli/lib/src/commands/release/release_ios_framework_command.dart @@ -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) { diff --git a/packages/shorebird_cli/lib/src/patch_diff_checker.dart b/packages/shorebird_cli/lib/src/patch_diff_checker.dart index 4a341a89a..ec211e5d1 100644 --- a/packages/shorebird_cli/lib/src/patch_diff_checker.dart +++ b/packages/shorebird_cli/lib/src/patch_diff_checker.dart @@ -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(); } diff --git a/packages/shorebird_cli/lib/src/shorebird_env.dart b/packages/shorebird_cli/lib/src/shorebird_env.dart index 560067924..e9e5113ad 100644 --- a/packages/shorebird_cli/lib/src/shorebird_env.dart +++ b/packages/shorebird_cli/lib/src/shorebird_env.dart @@ -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: diff --git a/packages/shorebird_cli/test/src/commands/init_command_test.dart b/packages/shorebird_cli/test/src/commands/init_command_test.dart index f80eefa74..1bd8681fb 100644 --- a/packages/shorebird_cli/test/src/commands/init_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/init_command_test.dart @@ -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')), diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart index 74e7a039b..9b868328f 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart @@ -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); diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart index 794b0801c..fffb0ec3a 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart @@ -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(); diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart index 397af45f0..2da6ff6ba 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart @@ -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(); diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart index 5dd3ae701..78f18f69b 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart @@ -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(); diff --git a/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart index 7b6108506..642b19d0c 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart @@ -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); diff --git a/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart index 5fdd8b768..04e39939c 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart @@ -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); diff --git a/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart index 86d0a1372..74906f080 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart @@ -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); diff --git a/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart index a49484c99..2fe17a1a8 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart @@ -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(); diff --git a/packages/shorebird_cli/test/src/mocks.dart b/packages/shorebird_cli/test/src/mocks.dart index 6e70e1021..72fa976d9 100644 --- a/packages/shorebird_cli/test/src/mocks.dart +++ b/packages/shorebird_cli/test/src/mocks.dart @@ -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 {} diff --git a/packages/shorebird_cli/test/src/patch_diff_checker_test.dart b/packages/shorebird_cli/test/src/patch_diff_checker_test.dart index 71cc52409..d4f06dbd0 100644 --- a/packages/shorebird_cli/test/src/patch_diff_checker_test.dart +++ b/packages/shorebird_cli/test/src/patch_diff_checker_test.dart @@ -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( diff --git a/packages/shorebird_cli/test/src/shorebird_env_test.dart b/packages/shorebird_cli/test/src/shorebird_env_test.dart index bbe61775a..453e83e58 100644 --- a/packages/shorebird_cli/test/src/shorebird_env_test.dart +++ b/packages/shorebird_cli/test/src/shorebird_env_test.dart @@ -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({