From df01615536340d9bcfe3b1c7d090f5d561080c4a Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Wed, 29 Mar 2023 11:40:22 -0500 Subject: [PATCH] feat(shorebird_cli): `shorebird init` creates app when `shorebird.yaml` exists (#198) --- .../lib/src/commands/init_command.dart | 44 +++++++++++---- .../test/src/commands/init_command_test.dart | 54 +++++++++++++++++-- 2 files changed, 83 insertions(+), 15 deletions(-) diff --git a/packages/shorebird_cli/lib/src/commands/init_command.dart b/packages/shorebird_cli/lib/src/commands/init_command.dart index 221fd125..49f38c7f 100644 --- a/packages/shorebird_cli/lib/src/commands/init_command.dart +++ b/packages/shorebird_cli/lib/src/commands/init_command.dart @@ -1,7 +1,10 @@ +import 'package:collection/collection.dart'; import 'package:mason_logger/mason_logger.dart'; import 'package:shorebird_cli/src/command.dart'; +import 'package:shorebird_cli/src/config/config.dart'; import 'package:shorebird_cli/src/shorebird_config_mixin.dart'; import 'package:shorebird_cli/src/shorebird_create_app_mixin.dart'; +import 'package:shorebird_code_push_client/shorebird_code_push_client.dart'; /// {@template init_command} /// @@ -41,16 +44,39 @@ Please make sure you are running "shorebird init" from the root of your Flutter return ExitCode.software.code; } - late final bool shorebirdYamlExists; + final ShorebirdYaml? shorebirdYaml; try { - shorebirdYamlExists = hasShorebirdYaml; + shorebirdYaml = getShorebirdYaml(); } catch (_) { progress.fail('Error parsing "shorebird.yaml".'); return ExitCode.software.code; } - late final String appId; - if (!shorebirdYamlExists) { + String? appId; + + if (shorebirdYaml != null) { + final codePushClient = buildCodePushClient( + apiKey: session.apiKey, + hostedUri: hostedUri, + ); + + final List apps; + final fetchAppsProgress = logger.progress('Fetching apps'); + try { + apps = (await codePushClient.getApps()) + .map((a) => App(id: a.appId, displayName: a.displayName)) + .toList(); + fetchAppsProgress.complete(); + } catch (error) { + fetchAppsProgress.fail('$error'); + return ExitCode.software.code; + } + + final app = apps.firstWhereOrNull((a) => a.id == shorebirdYaml!.appId); + appId = app?.id; + } + + if (appId == null) { try { final app = await createApp(); appId = app.id; @@ -58,18 +84,16 @@ Please make sure you are running "shorebird init" from the root of your Flutter progress.fail('$error'); return ExitCode.software.code; } - } else { - appId = getShorebirdYaml()!.appId; } - if (shorebirdYamlExists) { - progress.update('"shorebird.yaml" already exists.'); + if (shorebirdYaml != null) { + progress.update('Updating "shorebird.yaml"'); } else { progress.update('Creating "shorebird.yaml"'); - addShorebirdYamlToProject(appId); - progress.update('Generated a "shorebird.yaml".'); } + addShorebirdYamlToProject(appId); + progress.update('Adding "shorebird.yaml" to "pubspec.yaml" assets'); if (pubspecContainsShorebirdYaml) { 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 cefaef05..8a237ea4 100644 --- a/packages/shorebird_cli/test/src/commands/init_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/init_command_test.dart @@ -24,6 +24,7 @@ void main() { const appId = 'test_app_id'; const appName = 'test_app_name'; const app = App(id: appId, displayName: appName); + const appMetadata = AppMetadata(appId: appId, displayName: appName); const pubspecYamlContent = ''' name: $appName version: $version @@ -54,6 +55,9 @@ environment: when( () => codePushClient.createApp(displayName: any(named: 'displayName')), ).thenAnswer((_) async => app); + when( + () => codePushClient.getApps(), + ).thenAnswer((_) async => [appMetadata]); when(() => logger.progress(any())).thenReturn(progress); when( () => logger.prompt(any(), defaultValue: any(named: 'defaultValue')), @@ -134,24 +138,64 @@ Please make sure you are running "shorebird init" from the root of your Flutter expect(exitCode, ExitCode.software.code); }); - test('detects existing shorebird.yaml', () async { - const existingAppId = 'existing-app-id'; + test('throws software error when unable to fetch apps.', () async { + const error = 'oops something went wrong'; + final tempDir = Directory.systemTemp.createTempSync(); + when(() => codePushClient.getApps()).thenThrow(error); + File( + p.join(tempDir.path, 'pubspec.yaml'), + ).writeAsStringSync(pubspecYamlContent); + File( + p.join(tempDir.path, 'shorebird.yaml'), + ).writeAsStringSync('app_id: $appId'); + final exitCode = await IOOverrides.runZoned( + command.run, + getCurrentDirectory: () => tempDir, + ); + verify(() => progress.fail(error)).called(1); + expect(exitCode, ExitCode.software.code); + }); + + test('detects existing shorebird.yaml with existing app_id', () async { final tempDir = Directory.systemTemp.createTempSync(); File( p.join(tempDir.path, 'pubspec.yaml'), ).writeAsStringSync(pubspecYamlContent); File( p.join(tempDir.path, 'shorebird.yaml'), - ).writeAsStringSync('app_id: $existingAppId'); + ).writeAsStringSync('app_id: $appId'); + await IOOverrides.runZoned( + command.run, + getCurrentDirectory: () => tempDir, + ); + verifyNever( + () => codePushClient.createApp(displayName: any(named: 'displayName')), + ); + verify(() => progress.update('Updating "shorebird.yaml"')); + }); + + test('detects existing shorebird.yaml with non-existent app_id', () async { + const nonExisting = 'non-existing-app-id'; + when(() => codePushClient.getApps()).thenAnswer((_) async => []); + final tempDir = Directory.systemTemp.createTempSync(); + File( + p.join(tempDir.path, 'pubspec.yaml'), + ).writeAsStringSync(pubspecYamlContent); + File( + p.join(tempDir.path, 'shorebird.yaml'), + ).writeAsStringSync('app_id: $nonExisting'); await IOOverrides.runZoned( command.run, getCurrentDirectory: () => tempDir, ); expect( File(p.join(tempDir.path, 'shorebird.yaml')).readAsStringSync(), - contains('app_id: $existingAppId'), + contains('app_id: $appId'), ); - verify(() => progress.update('"shorebird.yaml" already exists.')); + verify( + () => codePushClient.createApp(displayName: any(named: 'displayName')), + ).called(1); + verify(() => progress.update('Updating "shorebird.yaml"')); }); test('creates shorebird.yaml', () async {