Warn when build number and version can't be parsed on iOS (#40611)
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index 57ee601..fefa80c 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -152,6 +152,9 @@
// See CFBundleVersion at https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
final RegExp disallowed = RegExp(r'[^\d\.]');
String tmpBuildNumber = buildNumber.replaceAll(disallowed, '');
+ if (tmpBuildNumber.isEmpty) {
+ return null;
+ }
final List<String> segments = tmpBuildNumber
.split('.')
.where((String segment) => segment.isNotEmpty)
@@ -196,6 +199,9 @@
// See CFBundleShortVersionString at https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
final RegExp disallowed = RegExp(r'[^\d\.]');
String tmpBuildName = buildName.replaceAll(disallowed, '');
+ if (tmpBuildName.isEmpty) {
+ return null;
+ }
final List<String> segments = tmpBuildName
.split('.')
.where((String segment) => segment.isNotEmpty)
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 4b81503..785f213 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -159,20 +159,52 @@
}
final String buildNameToParse = buildInfo?.buildName ?? project.manifest.buildName;
- final String buildName = validatedBuildNameForPlatform(TargetPlatform.ios, buildNameToParse);
- if (buildName != null) {
- xcodeBuildSettings.add('FLUTTER_BUILD_NAME=$buildName');
+ final bool buildNameIsMissing = buildNameToParse == null || buildNameToParse.isEmpty;
+ String buildName;
+ const String defaultBuildName = '1.0.0';
+ if (buildNameIsMissing) {
+ buildName = defaultBuildName;
+ } else {
+ buildName = validatedBuildNameForPlatform(TargetPlatform.ios, buildNameToParse);
}
- String buildNumber = validatedBuildNumberForPlatform(TargetPlatform.ios, buildInfo?.buildNumber ?? project.manifest.buildNumber);
- // Drop back to parsing build name if build number is not present. Build number is optional in the manifest, but
- // FLUTTER_BUILD_NUMBER is required as the backing value for the required CFBundleVersion.
- buildNumber ??= validatedBuildNumberForPlatform(TargetPlatform.ios, buildNameToParse);
+ final String buildNumberToParse = buildInfo?.buildNumber ?? project.manifest.buildNumber;
+ final bool buildNumberIsMissing =
+ (buildNumberToParse == null || buildNumberToParse.isEmpty) && buildNameIsMissing;
+ String buildNumber;
- if (buildNumber != null) {
- xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber');
+ const String defaultBuildNumber = '1';
+ if (buildNumberIsMissing) {
+ buildNumber = defaultBuildNumber;
+ } else {
+ buildNumber = validatedBuildNumberForPlatform(TargetPlatform.ios, buildNumberToParse);
+ // Drop back to parsing build name if build number is not present. Build number is optional in the manifest, but
+ // FLUTTER_BUILD_NUMBER is required as the backing value for the required CFBundleVersion.
+ buildNumber ??= validatedBuildNumberForPlatform(TargetPlatform.ios, buildNameToParse);
}
+ if (buildNameIsMissing) {
+ printError('Warning: Missing build name (CFBundleShortVersionString), defaulting to $defaultBuildName.');
+ }
+ if (buildNumberIsMissing) {
+ printError('Warning: Missing build number (CFBundleVersion), defaulting to $defaultBuildNumber.');
+ }
+ if (buildNameIsMissing || buildNumberIsMissing) {
+ printError('Action Required: You must set a build name and number in the pubspec.yaml '
+ 'file version field before submitting to the App Store.');
+ }
+
+ if (buildName == null && buildNumber == null) {
+ throwToolExit('Cannot parse build number $buildNumberToParse or build name $buildNameToParse, check pubspec.yaml version.');
+ } else if (buildName == null) {
+ throwToolExit('Cannot parse build name $buildNameToParse, check pubspec.yaml version.');
+ } else if (buildNumber == null) {
+ throwToolExit('Cannot parse build number $buildNumberToParse, check pubspec.yaml version.');
+ }
+
+ xcodeBuildSettings.add('FLUTTER_BUILD_NAME=$buildName');
+ xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber');
+
if (artifacts is LocalEngineArtifacts) {
final LocalEngineArtifacts localEngineArtifacts = artifacts;
final String engineOutPath = localEngineArtifacts.engineOutPath;
diff --git a/packages/flutter_tools/test/general.shard/build_info_test.dart b/packages/flutter_tools/test/general.shard/build_info_test.dart
index 1f12d08..d404696 100644
--- a/packages/flutter_tools/test/general.shard/build_info_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_info_test.dart
@@ -16,7 +16,7 @@
testUsingContext('CFBundleVersion for iOS', () async {
String buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, 'xyz');
- expect(buildName, '0');
+ expect(buildName, isNull);
buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '0.0.1');
expect(buildName, '0.0.1');
buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '123.xyz');
@@ -38,7 +38,7 @@
testUsingContext('CFBundleShortVersionString for iOS', () async {
String buildName = validatedBuildNameForPlatform(TargetPlatform.ios, 'xyz');
- expect(buildName, '0.0.0');
+ expect(buildName, isNull);
buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '0.0.1');
expect(buildName, '0.0.1');
buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '123.456.xyz');
diff --git a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
index 9e1b8ae..10765df 100644
--- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -629,6 +629,41 @@
expectedBuildNumber: '3',
);
});
+
+ testUsingOsxContext('default build name and number when version is missing', () async {
+ const String manifest = '''
+name: test
+dependencies:
+ flutter:
+ sdk: flutter
+flutter:
+''';
+ const BuildInfo buildInfo = BuildInfo(BuildMode.release, null);
+ await checkBuildVersion(
+ manifestString: manifest,
+ buildInfo: buildInfo,
+ expectedBuildName: '1.0.0',
+ expectedBuildNumber: '1',
+ );
+ });
+
+ testUsingOsxContext('fail when build name cannot be parsed', () async {
+ const String manifest = '''
+name: test
+dependencies:
+ flutter:
+ sdk: flutter
+flutter:
+''';
+ const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: 'abc', buildNumber: '1');
+
+ const String stderr = 'Cannot parse build name abc, check pubspec.yaml version.';
+ expect(() async => await checkBuildVersion(
+ manifestString: manifest,
+ buildInfo: buildInfo
+ ),
+ throwsToolExit(message: stderr));
+ });
});
}