Skip to content

Commit 4354835

Browse files
authored
add default-flavor field to flutter pubspec, which will be used as the flavor in flutter build/run if --flavor is not provided (flutter#147968)
This PR adds a new flag `default-flavor` in the `flutter` section of `pubspec.yaml`. It allows developers of multi-flavor android apps to specify a default flavor to be used for `flutter run`, `flutter build` etc. Using `flutter run` on flavored apps already works without specifying `--flavor` already works on iOS (it defaults to the `runner` schema), so I (and others in flutter#22856) figured this would be nice to have. fixes flutter#22856
1 parent ca198c8 commit 4354835

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

packages/flutter_tools/lib/src/flutter_manifest.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ class FlutterManifest {
388388
}
389389
return value;
390390
}
391+
392+
String? get defaultFlavor => _flutterDescriptor['default-flavor'] as String?;
391393
}
392394

393395
class Font {
@@ -557,6 +559,10 @@ void _validateFlutter(YamlMap? yaml, List<String> errors) {
557559
if (yamlValue is! bool) {
558560
errors.add('Expected "$yamlKey" to be a bool, but got $yamlValue (${yamlValue.runtimeType}).');
559561
}
562+
case 'default-flavor':
563+
if (yamlValue is! String) {
564+
errors.add('Expected "$yamlKey" to be a string, but got $yamlValue (${yamlValue.runtimeType}).');
565+
}
560566
default:
561567
errors.add('Unexpected child "$yamlKey" found under "flutter".');
562568
break;

packages/flutter_tools/lib/src/runner/flutter_command.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,8 @@ abstract class FlutterCommand extends Command<void> {
10941094
'flavor',
10951095
help: 'Build a custom app flavor as defined by platform-specific build setup.\n'
10961096
'Supports the use of product flavors in Android Gradle scripts, and '
1097-
'the use of custom Xcode schemes.',
1097+
'the use of custom Xcode schemes.\n'
1098+
'Overrides the value of the "default-flavor" entry in the flutter pubspec.',
10981099
);
10991100
}
11001101

@@ -1283,7 +1284,9 @@ abstract class FlutterCommand extends Command<void> {
12831284
}
12841285
}
12851286

1286-
final String? flavor = argParser.options.containsKey('flavor') ? stringArg('flavor') : null;
1287+
final String? defaultFlavor = FlutterProject.current().manifest.defaultFlavor;
1288+
final String? cliFlavor = argParser.options.containsKey('flavor') ? stringArg('flavor') : null;
1289+
final String? flavor = cliFlavor ?? defaultFlavor;
12871290
if (flavor != null) {
12881291
if (globals.platform.environment['FLUTTER_APP_FLAVOR'] != null) {
12891292
throwToolExit('FLUTTER_APP_FLAVOR is used by the framework and cannot be set in the environment.');

packages/flutter_tools/test/general.shard/flutter_manifest_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void main() {
3636
expect(flutterManifest.fonts, isEmpty);
3737
expect(flutterManifest.assets, isEmpty);
3838
expect(flutterManifest.additionalLicenses, isEmpty);
39+
expect(flutterManifest.defaultFlavor, null);
3940
});
4041

4142
testWithoutContext('FlutterManifest is null when the pubspec.yaml file is not a map', () async {
@@ -1448,6 +1449,37 @@ flutter:
14481449

14491450
expect(flutterManifest.disabledSwiftPackageManager, false);
14501451
});
1452+
1453+
testWithoutContext('FlutterManifest can parse default flavor', () async {
1454+
const String manifest = '''
1455+
name: test
1456+
flutter:
1457+
default-flavor: prod
1458+
''';
1459+
final FlutterManifest? flutterManifest = FlutterManifest.createFromString(
1460+
manifest,
1461+
logger: BufferLogger.test(),
1462+
);
1463+
1464+
expect(flutterManifest, isNotNull);
1465+
expect(flutterManifest!.defaultFlavor, 'prod');
1466+
});
1467+
1468+
testWithoutContext('FlutterManifest fails on invalid default flavor', () async {
1469+
const String manifest = '''
1470+
name: test
1471+
flutter:
1472+
default-flavor: 3
1473+
''';
1474+
1475+
final FlutterManifest? flutterManifest = FlutterManifest.createFromString(
1476+
manifest,
1477+
logger: logger,
1478+
);
1479+
1480+
expect(flutterManifest, null);
1481+
expect(logger.errorText, 'Expected "default-flavor" to be a string, but got 3 (int).\n');
1482+
});
14511483
}
14521484

14531485
Matcher matchesManifest({

packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,45 @@ void main() {
12171217
FileSystem: () => fileSystem,
12181218
ProcessManager: () => FakeProcessManager.any(),
12191219
});
1220+
1221+
testUsingContext('CLI option overrides default flavor from manifest', () async {
1222+
final File pubspec = fileSystem.file('pubspec.yaml');
1223+
await pubspec.create();
1224+
await pubspec.writeAsString('''
1225+
name: test
1226+
flutter:
1227+
default-flavor: foo
1228+
''');
1229+
1230+
final DummyFlutterCommand flutterCommand = DummyFlutterCommand();
1231+
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(forcedBuildMode: BuildMode.debug);
1232+
expect(buildInfo.flavor, 'foo');
1233+
}, overrides: <Type, Generator>{
1234+
FileSystem: () => fileSystem,
1235+
ProcessManager: () => FakeProcessManager.empty(),
1236+
});
1237+
1238+
testUsingContext('tool loads default flavor from manifest, but cli overrides', () async {
1239+
final File pubspec = fileSystem.file('pubspec.yaml');
1240+
await pubspec.create();
1241+
await pubspec.writeAsString('''
1242+
name: test
1243+
flutter:
1244+
default-flavor: foo
1245+
''');
1246+
1247+
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(commandFunction: () async {
1248+
return FlutterCommandResult.success();
1249+
},);
1250+
flutterCommand.usesFlavorOption();
1251+
final CommandRunner<void> runner = createTestCommandRunner(flutterCommand);
1252+
await runner.run(<String>['dummy', '--flavor', 'bar']);
1253+
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(forcedBuildMode: BuildMode.debug);
1254+
expect(buildInfo.flavor, 'bar');
1255+
}, overrides: <Type, Generator>{
1256+
FileSystem: () => fileSystem,
1257+
ProcessManager: () => FakeProcessManager.empty(),
1258+
});
12201259
});
12211260
});
12221261
}

0 commit comments

Comments
 (0)