diff --git a/packages/shorebird_cli/lib/src/shorebird_build_mixin.dart b/packages/shorebird_cli/lib/src/shorebird_build_mixin.dart index 125bbe05..40e0ac73 100644 --- a/packages/shorebird_cli/lib/src/shorebird_build_mixin.dart +++ b/packages/shorebird_cli/lib/src/shorebird_build_mixin.dart @@ -5,6 +5,7 @@ import 'package:mason_logger/mason_logger.dart'; import 'package:path/path.dart' as p; import 'package:shorebird_cli/src/cache.dart'; import 'package:shorebird_cli/src/command.dart'; +import 'package:shorebird_cli/src/logger.dart'; import 'package:shorebird_cli/src/process.dart'; import 'package:shorebird_cli/src/shorebird_env.dart'; @@ -106,6 +107,8 @@ mixin ShorebirdBuildMixin on ShorebirdCommand { result.exitCode, ); } + + await _systemFlutterPubGet(); } Future buildAar({required String buildNumber}) async { @@ -133,6 +136,8 @@ mixin ShorebirdBuildMixin on ShorebirdCommand { result.exitCode, ); } + + await _systemFlutterPubGet(); } Future buildApk({ @@ -165,6 +170,8 @@ mixin ShorebirdBuildMixin on ShorebirdCommand { result.exitCode, ); } + + await _systemFlutterPubGet(); } Future buildIpa({ @@ -198,7 +205,11 @@ mixin ShorebirdBuildMixin on ShorebirdCommand { result.stderr.toString(), result.exitCode, ); - } else if (result.stderr + } + + await _systemFlutterPubGet(); + + if (result.stderr .toString() .contains('Encountered error while creating the IPA')) { final errorMessage = _failedToCreateIpaErrorMessage( @@ -234,6 +245,35 @@ mixin ShorebirdBuildMixin on ShorebirdCommand { result.exitCode, ); } + + await _systemFlutterPubGet(); + } + + /// This is a hack to reset `.dart_tool/package_config.json` to point to the + /// Flutter SDK on the user's PATH. This is necessary because Flutter commands + /// run by shorebird update the package_config.json file to point to + /// shorebird's version of Flutter, which confuses VS Code. See + /// https://github.com/shorebirdtech/shorebird/issues/1101 for more info. + Future _systemFlutterPubGet() async { + const executable = 'flutter'; + final arguments = ['pub', 'get', '--offline']; + + final result = await process.run( + executable, + arguments, + runInShell: true, + useVendedFlutter: false, + ); + + if (result.exitCode != ExitCode.success.code) { + logger.warn( + ''' +Build was successful, but `flutter pub get` failed to run after the build completed. You may see unexpected behavior in VS Code. + +Either run `flutter pub get` manually, or follow the steps in ${link(uri: Uri.parse('https://docs.shorebird.dev/troubleshooting#i-installed-shorebird-and-now-i-cant-run-my-app-in-vs-code'))}. +''', + ); + } } /// Creates an ExportOptions.plist file, which is used to tell xcodebuild to diff --git a/packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart index f9b12763..345e56ce 100644 --- a/packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart @@ -34,7 +34,8 @@ void main() { late Progress progress; late ShorebirdEnv shorebirdEnv; late ShorebirdProcess shorebirdProcess; - late ShorebirdProcessResult processResult; + late ShorebirdProcessResult buildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdValidator shorebirdValidator; late BuildAarCommand command; @@ -53,7 +54,8 @@ void main() { setUp(() { argResults = _MockArgResults(); logger = _MockLogger(); - processResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); + buildProcessResult = _MockProcessResult(); progress = _MockProgress(); shorebirdEnv = _MockShorebirdEnv(); shorebirdProcess = _MockShorebirdProcess(); @@ -63,6 +65,16 @@ void main() { when(() => argResults.rest).thenReturn([]); when(() => logger.progress(any())).thenReturn(progress); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when( () => shorebirdProcess.run( any(), @@ -70,7 +82,7 @@ void main() { runInShell: any(named: 'runInShell'), ), ).thenAnswer((invocation) async { - return processResult; + return buildProcessResult; }); when( @@ -119,8 +131,8 @@ void main() { }); test('exits with code 70 when building aar fails', () async { - when(() => processResult.exitCode).thenReturn(1); - when(() => processResult.stderr).thenReturn('oops'); + when(() => buildProcessResult.exitCode).thenReturn(1); + when(() => buildProcessResult.stderr).thenReturn('oops'); final result = await runWithOverrides(command.run); @@ -144,7 +156,7 @@ void main() { }); test('exits with code 0 when building aar succeeds', () async { - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final result = await runWithOverrides(command.run); expect(result, equals(ExitCode.success.code)); @@ -183,5 +195,20 @@ ${lightCyan.wrap( ), ).called(1); }); + + test('runs flutter pub get with system flutter after successful build', + () async { + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); + await runWithOverrides(command.run); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); }); } diff --git a/packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart index e5c275f4..d96f060c 100644 --- a/packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart @@ -37,7 +37,8 @@ void main() { late ArgResults argResults; late Doctor doctor; late Logger logger; - late ShorebirdProcessResult processResult; + late ShorebirdProcessResult flutterPubGetProcessResult; + late ShorebirdProcessResult buildProcessResult; late BuildApkCommand command; late ShorebirdFlutterValidator flutterValidator; late ShorebirdProcess shorebirdProcess; @@ -64,17 +65,28 @@ void main() { doctor = _MockDoctor(); logger = _MockLogger(); shorebirdProcess = _MockShorebirdProcess(); - processResult = _MockProcessResult(); + buildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); flutterValidator = _MockShorebirdFlutterValidator(); shorebirdValidator = _MockShorebirdValidator(); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when( () => shorebirdProcess.run( any(), any(), runInShell: any(named: 'runInShell'), ), - ).thenAnswer((_) async => processResult); + ).thenAnswer((_) async => buildProcessResult); when(() => argResults.rest).thenReturn([]); when(() => logger.progress(any())).thenReturn(_MockProgress()); when(() => logger.info(any())).thenReturn(null); @@ -120,8 +132,8 @@ void main() { }); test('exits with code 70 when building apk fails', () async { - when(() => processResult.exitCode).thenReturn(1); - when(() => processResult.stderr).thenReturn('oops'); + when(() => buildProcessResult.exitCode).thenReturn(1); + when(() => buildProcessResult.stderr).thenReturn('oops'); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( @@ -140,7 +152,7 @@ void main() { }); test('exits with code 0 when building apk succeeds', () async { - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), @@ -165,6 +177,26 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', 'release', 'app-releas ).called(1); }); + test('runs flutter pub get with system flutter after successful build', + () async { + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); + final tempDir = Directory.systemTemp.createTempSync(); + + await IOOverrides.runZoned( + () async => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test( 'exits with code 0 when building apk succeeds ' 'with flavor and target', () async { @@ -172,7 +204,7 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', 'release', 'app-releas final target = p.join('lib', 'main_development.dart'); when(() => argResults['flavor']).thenReturn(flavor); when(() => argResults['target']).thenReturn(target); - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), diff --git a/packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart index 086fb557..9ad19fdc 100644 --- a/packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart @@ -37,7 +37,8 @@ void main() { late ArgResults argResults; late Doctor doctor; late Logger logger; - late ShorebirdProcessResult processResult; + late ShorebirdProcessResult flutterPubGetProcessResult; + late ShorebirdProcessResult buildProcessResult; late BuildAppBundleCommand command; late ShorebirdFlutterValidator flutterValidator; late ShorebirdProcess shorebirdProcess; @@ -64,18 +65,29 @@ void main() { argResults = _MockArgResults(); doctor = _MockDoctor(); logger = _MockLogger(); - processResult = _MockProcessResult(); + buildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); flutterValidator = _MockShorebirdFlutterValidator(); shorebirdProcess = _MockShorebirdProcess(); shorebirdValidator = _MockShorebirdValidator(); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when( () => shorebirdProcess.run( any(), any(), runInShell: any(named: 'runInShell'), ), - ).thenAnswer((_) async => processResult); + ).thenAnswer((_) async => buildProcessResult); when(() => argResults.rest).thenReturn([]); when(() => logger.progress(any())).thenReturn(_MockProgress()); when(() => logger.info(any())).thenReturn(null); @@ -121,8 +133,8 @@ void main() { }); test('exits with code 70 when building appbundle fails', () async { - when(() => processResult.exitCode).thenReturn(1); - when(() => processResult.stderr).thenReturn('oops'); + when(() => buildProcessResult.exitCode).thenReturn(1); + when(() => buildProcessResult.stderr).thenReturn('oops'); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( @@ -141,7 +153,7 @@ void main() { }); test('exits with code 0 when building appbundle succeeds', () async { - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), @@ -173,7 +185,7 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', 'release', 'app-rel final target = p.join('lib', 'main_development.dart'); when(() => argResults['flavor']).thenReturn(flavor); when(() => argResults['target']).thenReturn(target); - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), @@ -241,5 +253,25 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', '${flavor}Release', throwsException, ); }); + + test('runs flutter pub get with system flutter after successful build', + () async { + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); + final tempDir = Directory.systemTemp.createTempSync(); + + await IOOverrides.runZoned( + () async => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); }); } diff --git a/packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart index 27f3809d..5ddaf7d9 100644 --- a/packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart @@ -38,7 +38,8 @@ void main() { late ArgResults argResults; late Doctor doctor; late Logger logger; - late ShorebirdProcessResult processResult; + late ShorebirdProcessResult buildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late BuildIpaCommand command; late ShorebirdFlutterValidator flutterValidator; late ShorebirdProcess shorebirdProcess; @@ -65,17 +66,28 @@ void main() { doctor = _MockDoctor(); logger = _MockLogger(); shorebirdProcess = _MockShorebirdProcess(); - processResult = _MockProcessResult(); + buildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); flutterValidator = _MockShorebirdFlutterValidator(); shorebirdValidator = _MockShorebirdValidator(); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when( () => shorebirdProcess.run( any(), any(), runInShell: any(named: 'runInShell'), ), - ).thenAnswer((_) async => processResult); + ).thenAnswer((_) async => buildProcessResult); when(() => argResults['codesign']).thenReturn(true); when(() => argResults.rest).thenReturn([]); when(() => logger.progress(any())).thenReturn(_MockProgress()); @@ -120,8 +132,8 @@ void main() { }); test('exits with code 70 when building ipa fails', () async { - when(() => processResult.exitCode).thenReturn(1); - when(() => processResult.stderr).thenReturn('oops'); + when(() => buildProcessResult.exitCode).thenReturn(1); + when(() => buildProcessResult.stderr).thenReturn('oops'); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( @@ -144,7 +156,7 @@ void main() { }); test('exits with code 0 when building ipa succeeds', () async { - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), @@ -179,6 +191,26 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', ]); }); + test('runs flutter pub get with system flutter after successful build', + () async { + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); + final tempDir = Directory.systemTemp.createTempSync(); + + await IOOverrides.runZoned( + () async => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test( 'exits with code 0 when building ipa succeeds ' 'with flavor and target', () async { @@ -186,7 +218,7 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', final target = p.join('lib', 'main_development.dart'); when(() => argResults['flavor']).thenReturn(flavor); when(() => argResults['target']).thenReturn(target); - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), @@ -231,7 +263,7 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', 'exits with code 0 when building ipa succeeds ' 'with --no-codesign', () async { when(() => argResults['codesign']).thenReturn(false); - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), @@ -269,7 +301,7 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', test('provides appropriate ExportOptions.plist to build ipa command', () async { - when(() => processResult.exitCode).thenReturn(ExitCode.success.code); + when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code); final tempDir = Directory.systemTemp.createTempSync(); final result = await IOOverrides.runZoned( () async => runWithOverrides(command.run), 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 bb3a000c..4d98c324 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 @@ -114,6 +114,7 @@ void main() { late Progress progress; late Logger logger; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdProcessResult patchProcessResult; late http.Client httpClient; late Cache cache; @@ -194,6 +195,7 @@ void main() { progress = _MockProgress(); logger = _MockLogger(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); patchProcessResult = _MockProcessResult(); httpClient = _MockHttpClient(); cache = _MockCache(); @@ -213,6 +215,14 @@ void main() { when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml); when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision); when(() => shorebirdEnv.isRunningOnCI).thenReturn(false); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( 'flutter', @@ -257,6 +267,9 @@ void main() { when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when( + () => flutterPubGetProcessResult.exitCode, + ).thenReturn(ExitCode.success.code); when(() => patchProcessResult.exitCode).thenReturn(ExitCode.success.code); when(() => httpClient.send(any())).thenAnswer( (_) async => http.StreamedResponse(const Stream.empty(), HttpStatus.ok), @@ -807,6 +820,26 @@ Please re-run the release command for this version or create a new release.'''), ).called(1); }); + test('runs flutter pub get with system flutter after successful build', + () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test('does not prompt if running on CI', () async { when(() => shorebirdEnv.isRunningOnCI).thenReturn(true); final tempDir = setUpTempDir(); 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 fdd2a0f0..6eaf4277 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 @@ -136,6 +136,7 @@ flutter: late Logger logger; late ShorebirdEnv shorebirdEnv; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdProcessResult patchProcessResult; late http.Client httpClient; late Cache cache; @@ -223,6 +224,7 @@ flutter: progress = _MockProgress(); logger = _MockLogger(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); patchProcessResult = _MockProcessResult(); httpClient = _MockHttpClient(); flutterValidator = _MockShorebirdFlutterValidator(); @@ -249,6 +251,14 @@ flutter: runInShell: any(named: 'runInShell'), ), ).thenAnswer((_) async => flutterBuildProcessResult); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( any(that: endsWith('patch')), @@ -296,6 +306,9 @@ flutter: when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when(() => flutterPubGetProcessResult.exitCode).thenReturn( + ExitCode.success.code, + ); when(() => httpClient.send(any())).thenAnswer( (_) async => http.StreamedResponse(const Stream.empty(), HttpStatus.ok), ); @@ -751,6 +764,25 @@ Or change your Flutter version and try again using: expect(exitCode, ExitCode.success.code); }); + test('runs flutter pub get with system flutter after successful build', + () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test( 'succeeds when patch is successful ' 'with flavors and target', () async { 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 a2d2ed5e..aedb0f1d 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 @@ -135,6 +135,7 @@ flutter: late Platform platform; late ShorebirdProcessResult aotBuildProcessResult; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late http.Client httpClient; late ShorebirdEnv shorebirdEnv; late ShorebirdFlutter shorebirdFlutter; @@ -234,6 +235,7 @@ flutter: platform = _MockPlatform(); aotBuildProcessResult = _MockProcessResult(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); httpClient = _MockHttpClient(); patchDiffChecker = _MockPatchDiffChecker(); shorebirdEnv = _MockShorebirdEnv(); @@ -296,6 +298,16 @@ flutter: when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( 'flutter', @@ -785,6 +797,26 @@ Or change your Flutter version and try again using: expect(exitCode, ExitCode.success.code); }); + test('runs flutter pub get with system flutter after successful build', + () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test( 'succeeds when patch is successful ' 'with flavors and target', () async { 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 66074699..173d4f63 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 @@ -110,6 +110,7 @@ flutter: late Logger logger; late ShorebirdProcessResult aotBuildProcessResult; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdEnv shorebirdEnv; late ShorebirdFlutter shorebirdFlutter; late ShorebirdFlutterValidator flutterValidator; @@ -210,12 +211,21 @@ flutter: logger = _MockLogger(); aotBuildProcessResult = _MockProcessResult(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); shorebirdEnv = _MockShorebirdEnv(); shorebirdFlutter = _MockShorebirdFlutter(); flutterValidator = _MockShorebirdFlutterValidator(); shorebirdProcess = _MockShorebirdProcess(); shorebirdValidator = _MockShorebirdValidator(); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( 'flutter', @@ -251,6 +261,8 @@ flutter: when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when( () => codePushClientWrapper.getApp(appId: any(named: 'appId')), ).thenAnswer((_) async => appMetadata); @@ -717,6 +729,26 @@ Please re-run the release command for this version or create a new release.'''), expect(exitCode, ExitCode.success.code); }); + test('runs flutter pub get with system flutter after successful build', + () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test('does not prompt if running on CI', () async { when(() => shorebirdEnv.isRunningOnCI).thenReturn(true); final tempDir = setUpTempDir(); 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 e9e566d1..fe6ac0e2 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 @@ -82,6 +82,7 @@ void main() { late Progress progress; late Logger logger; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdEnv shorebirdEnv; late ShorebirdProcess shorebirdProcess; late ShorebirdValidator shorebirdValidator; @@ -151,6 +152,7 @@ void main() { progress = _MockProgress(); logger = _MockLogger(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); shorebirdProcess = _MockShorebirdProcess(); shorebirdRoot = Directory.systemTemp.createTempSync(); shorebirdEnv = _MockShorebirdEnv(); @@ -174,7 +176,18 @@ void main() { when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when( + () => flutterPubGetProcessResult.exitCode, + ).thenReturn(ExitCode.success.code); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( any(), @@ -385,6 +398,25 @@ void main() { ).called(1); }); + test('runs flutter pub get with system flutter after successful build', + () async { + final tempDir = setUpTempArtifacts(); + + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test('does not create new release if existing release is present', () async { when( 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 6a0d8d19..a4bcff96 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 @@ -98,6 +98,7 @@ void main() { late Progress progress; late Logger logger; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdFlutterValidator flutterValidator; late ShorebirdProcess shorebirdProcess; late ShorebirdEnv shorebirdEnv; @@ -145,6 +146,7 @@ void main() { progress = _MockProgress(); logger = _MockLogger(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); flutterValidator = _MockShorebirdFlutterValidator(); shorebirdProcess = _MockShorebirdProcess(); shorebirdEnv = _MockShorebirdEnv(); @@ -155,6 +157,14 @@ void main() { when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision); when(() => shorebirdEnv.isRunningOnCI).thenReturn(false); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( 'flutter', @@ -181,6 +191,8 @@ void main() { when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when( () => codePushClientWrapper.getApp(appId: any(named: 'appId')), ).thenAnswer((_) async => appMetadata); @@ -426,6 +438,36 @@ void main() { expect(exitCode, ExitCode.success.code); }); + test('runs flutter pub get with system flutter after successful build', + () async { + await runWithOverrides(command.run); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + + test('prints error message if system flutter pub get fails', () async { + when(() => flutterPubGetProcessResult.exitCode).thenReturn(1); + + await runWithOverrides(command.run); + + verify( + () => logger.warn( + ''' +Build was successful, but `flutter pub get` failed to run after the build completed. You may see unexpected behavior in VS Code. + +Either run `flutter pub get` manually, or follow the steps in ${link(uri: Uri.parse('https://docs.shorebird.dev/troubleshooting#i-installed-shorebird-and-now-i-cant-run-my-app-in-vs-code'))}. +''', + ), + ).called(1); + }); + test( 'succeeds when release is successful ' 'with flavors and target', () async { 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 072df803..71246649 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 @@ -107,6 +107,7 @@ flutter: late Progress progress; late Logger logger; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdFlutterValidator flutterValidator; late ShorebirdProcess shorebirdProcess; late ShorebirdEnv shorebirdEnv; @@ -165,6 +166,7 @@ flutter: progress = _MockProgress(); logger = _MockLogger(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); flutterValidator = _MockShorebirdFlutterValidator(); shorebirdProcess = _MockShorebirdProcess(); shorebirdEnv = _MockShorebirdEnv(); @@ -174,6 +176,14 @@ flutter: when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot); when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision); when(() => shorebirdEnv.isRunningOnCI).thenReturn(false); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( 'flutter', @@ -196,6 +206,8 @@ flutter: when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when( () => codePushClientWrapper.getApp(appId: any(named: 'appId')), ).thenAnswer((_) async => appMetadata); @@ -507,6 +519,25 @@ error: exportArchive: No signing certificate "iOS Distribution" found expect(exitCode, ExitCode.success.code); }); + test('runs flutter pub get with system flutter after successful build', + () async { + final tempDir = setUpTempDir(); + + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); + test( 'succeeds when release is successful ' 'with flavors and target', () async { 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 c5090202..91aaf2e6 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 @@ -88,6 +88,7 @@ flutter: late Progress progress; late Logger logger; late ShorebirdProcessResult flutterBuildProcessResult; + late ShorebirdProcessResult flutterPubGetProcessResult; late ShorebirdFlutterValidator flutterValidator; late ShorebirdProcess shorebirdProcess; late ShorebirdEnv shorebirdEnv; @@ -138,6 +139,7 @@ flutter: progress = _MockProgress(); logger = _MockLogger(); flutterBuildProcessResult = _MockProcessResult(); + flutterPubGetProcessResult = _MockProcessResult(); flutterValidator = _MockShorebirdFlutterValidator(); shorebirdProcess = _MockShorebirdProcess(); shorebirdEnv = _MockShorebirdEnv(); @@ -146,6 +148,14 @@ flutter: when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml); when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot); when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision); + when( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).thenAnswer((_) async => flutterPubGetProcessResult); when( () => shorebirdProcess.run( 'flutter', @@ -161,6 +171,8 @@ flutter: when( () => flutterBuildProcessResult.exitCode, ).thenReturn(ExitCode.success.code); + when(() => flutterPubGetProcessResult.exitCode) + .thenReturn(ExitCode.success.code); when(() => logger.progress(any())).thenReturn(progress); when(() => logger.confirm(any())).thenReturn(true); when(() => platform.operatingSystem).thenReturn(Platform.macOS); @@ -374,5 +386,24 @@ flutter: ).called(1); expect(exitCode, ExitCode.success.code); }); + + test('runs flutter pub get with system flutter after successful build', + () async { + final tempDir = setUpTempDir(); + + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => shorebirdProcess.run( + 'flutter', + ['pub', 'get', '--offline'], + runInShell: any(named: 'runInShell'), + useVendedFlutter: false, + ), + ).called(1); + }); }); }