feat(shorebird_cli): add new flavors to shorebird.yaml if detected by shorebird init (#1251)
This commit is contained in:
@@ -13,6 +13,7 @@ import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/xcodebuild.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
import 'package:yaml_edit/yaml_edit.dart';
|
||||
|
||||
@@ -63,13 +64,6 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
|
||||
final force = results['force'] == true;
|
||||
|
||||
if (!force && shorebirdEnv.hasShorebirdYaml) {
|
||||
logger.err('''
|
||||
A "shorebird.yaml" already exists.
|
||||
If you want to reinitialize Shorebird, please run "shorebird init --force".''');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
Set<String>? androidFlavors;
|
||||
Set<String>? iosFlavors;
|
||||
var productFlavors = <String>{};
|
||||
@@ -92,6 +86,60 @@ If you want to reinitialize Shorebird, please run "shorebird init --force".''');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final shorebirdYaml = shorebirdEnv.getShorebirdYaml();
|
||||
final existingFlavors = shorebirdYaml?.flavors;
|
||||
Set<String> newFlavors;
|
||||
if (existingFlavors != null) {
|
||||
final existingFlavorNames = existingFlavors.keys.toSet();
|
||||
newFlavors = productFlavors.difference(existingFlavorNames);
|
||||
} else {
|
||||
newFlavors = {};
|
||||
}
|
||||
|
||||
// New flavors not being empty means that we have existing flavors, which
|
||||
// means that there is already an existing app.
|
||||
// If the --force flag is present, we will completely reinit the app and
|
||||
// don't care about which flavors are new.
|
||||
if (!force && newFlavors.isNotEmpty) {
|
||||
logger.info('New flavors detected: ${newFlavors.join(', ')}');
|
||||
final updateShorebirdYamlProgress =
|
||||
logger.progress('Adding flavors to shorebird.yaml');
|
||||
|
||||
final AppMetadata existingApp;
|
||||
try {
|
||||
existingApp =
|
||||
await codePushClientWrapper.getApp(appId: shorebirdYaml!.appId);
|
||||
} catch (e) {
|
||||
updateShorebirdYamlProgress.fail('Failed to get existing app info: $e');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final deflavoredAppName =
|
||||
existingApp.displayName.replaceAll(RegExp(r'\(.*\)'), '').trim();
|
||||
final flavorsToAppIds = shorebirdYaml.flavors!;
|
||||
for (final flavor in newFlavors) {
|
||||
final app = await codePushClientWrapper.createApp(
|
||||
appName: '$deflavoredAppName ($flavor)',
|
||||
);
|
||||
flavorsToAppIds[flavor] = app.id;
|
||||
}
|
||||
_addShorebirdYamlToProject(
|
||||
shorebirdYaml.appId,
|
||||
flavors: flavorsToAppIds,
|
||||
);
|
||||
updateShorebirdYamlProgress.complete('Flavors added to shorebird.yaml');
|
||||
return ExitCode.success.code;
|
||||
}
|
||||
|
||||
if (!force && shorebirdEnv.hasShorebirdYaml) {
|
||||
logger
|
||||
..err('A "shorebird.yaml" file already exists and seems up-to-date.')
|
||||
..info(
|
||||
'''If you want to reinitialize Shorebird, please run ${lightCyan.wrap('shorebird init --force')}.''',
|
||||
);
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final String appId;
|
||||
Map<String, String>? flavors;
|
||||
try {
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:platform/platform.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
import 'package:shorebird_cli/src/commands/init_command.dart';
|
||||
import 'package:shorebird_cli/src/config/config.dart';
|
||||
import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/gradlew.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
@@ -38,6 +39,8 @@ class _MockProgress extends Mock implements Progress {}
|
||||
|
||||
class _MockShorebirdEnv extends Mock implements ShorebirdEnv {}
|
||||
|
||||
class _MockShorebirdYaml extends Mock implements ShorebirdYaml {}
|
||||
|
||||
class _MockShorebirdValidator extends Mock implements ShorebirdValidator {}
|
||||
|
||||
class _MockXcodeBuild extends Mock implements XcodeBuild {}
|
||||
@@ -59,6 +62,7 @@ environment:
|
||||
late Gradlew gradlew;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late File shorebirdYamlFile;
|
||||
late ShorebirdYaml shorebirdYaml;
|
||||
late File pubspecYamlFile;
|
||||
late Logger logger;
|
||||
late Platform platform;
|
||||
@@ -90,6 +94,7 @@ environment:
|
||||
doctor = _MockDoctor();
|
||||
gradlew = _MockGradlew();
|
||||
codePushClientWrapper = _MockCodePushClientWrapper();
|
||||
shorebirdYaml = _MockShorebirdYaml();
|
||||
shorebirdYamlFile = _MockFile();
|
||||
pubspecYamlFile = _MockFile();
|
||||
logger = _MockLogger();
|
||||
@@ -184,9 +189,11 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.err(
|
||||
'''
|
||||
A "shorebird.yaml" already exists.
|
||||
If you want to reinitialize Shorebird, please run "shorebird init --force".''',
|
||||
'A "shorebird.yaml" file already exists and seems up-to-date.'),
|
||||
).called(1);
|
||||
verify(
|
||||
() => logger.info(
|
||||
'''If you want to reinitialize Shorebird, please run ${lightCyan.wrap('shorebird init --force')}.''',
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
@@ -198,9 +205,7 @@ If you want to reinitialize Shorebird, please run "shorebird init --force".''',
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verifyNever(
|
||||
() => logger.err(
|
||||
'''
|
||||
A "shorebird.yaml" already exists.
|
||||
If you want to reinitialize Shorebird, please run "shorebird init --force".''',
|
||||
'A "shorebird.yaml" file already exists and seems up-to-date.',
|
||||
),
|
||||
);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
@@ -786,6 +791,93 @@ flavors:
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
group('with new flavors added', () {
|
||||
final existingFlavors = {
|
||||
'a': 'test-appId-1',
|
||||
'b': 'test-appId-2',
|
||||
};
|
||||
|
||||
setUp(() {
|
||||
const androidVariants = {'a', 'b', 'c', 'd'};
|
||||
when(
|
||||
() => gradlew.productFlavors(any()),
|
||||
).thenAnswer((_) async => androidVariants);
|
||||
|
||||
when(() => shorebirdEnv.hasShorebirdYaml).thenReturn(true);
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdYaml.appId).thenReturn(appId);
|
||||
when(() => shorebirdYaml.flavors).thenReturn(existingFlavors);
|
||||
});
|
||||
|
||||
test('exits with software error if retrieving existing app fails',
|
||||
() async {
|
||||
when(() => codePushClientWrapper.getApp(appId: any(named: 'appId')))
|
||||
.thenThrow(Exception('oh no'));
|
||||
final result = await runWithOverrides(command.run);
|
||||
expect(result, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('creates new flavor entries in shorebird.yaml', () async {
|
||||
const newAppIds = [
|
||||
'test-appId-3',
|
||||
'test-appId-4',
|
||||
];
|
||||
const appName = 'my-app';
|
||||
var index = 0;
|
||||
|
||||
when(() => codePushClientWrapper.getApp(appId: any(named: 'appId')))
|
||||
.thenAnswer(
|
||||
(_) async => const AppMetadata(appId: appId, displayName: appName),
|
||||
);
|
||||
when(
|
||||
() =>
|
||||
codePushClientWrapper.createApp(appName: any(named: 'appName')),
|
||||
).thenAnswer((invocation) async {
|
||||
final appName = invocation.namedArguments[#appName] as String?;
|
||||
return App(id: newAppIds[index++], displayName: appName ?? '-');
|
||||
});
|
||||
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(() => logger.info('New flavors detected: c, d')).called(1);
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.createApp(
|
||||
appName: '$appName (a)',
|
||||
),
|
||||
);
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.createApp(
|
||||
appName: '$appName (b)',
|
||||
),
|
||||
);
|
||||
verify(
|
||||
() => codePushClientWrapper.createApp(
|
||||
appName: '$appName (c)',
|
||||
),
|
||||
).called(1);
|
||||
verify(
|
||||
() => codePushClientWrapper.createApp(
|
||||
appName: '$appName (d)',
|
||||
),
|
||||
).called(1);
|
||||
verify(
|
||||
() => shorebirdYamlFile.writeAsStringSync(
|
||||
any(
|
||||
that: contains(
|
||||
'''
|
||||
app_id: test_app_id
|
||||
flavors:
|
||||
a: test-appId-1
|
||||
b: test-appId-2
|
||||
c: test-appId-3
|
||||
d: test-appId-4''',
|
||||
),
|
||||
),
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('detects existing shorebird.yaml in pubspec.yaml assets', () async {
|
||||
|
||||
Reference in New Issue
Block a user