Build number (part after +) is documented as optional, use entire app version if not present (#37036)
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 7234890..af96308 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -152,12 +152,17 @@ xcodeBuildSettings.add('FLUTTER_FRAMEWORK_DIR=$frameworkDir'); } - final String buildName = validatedBuildNameForPlatform(TargetPlatform.ios, buildInfo?.buildName ?? project.manifest.buildName); + 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 String buildNumber = validatedBuildNumberForPlatform(TargetPlatform.ios, buildInfo?.buildNumber ?? project.manifest.buildNumber); + 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); + if (buildNumber != null) { xcodeBuildSettings.add('FLUTTER_BUILD_NUMBER=$buildNumber'); }
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 e4bc22a..1f12d08 100644 --- a/packages/flutter_tools/test/general.shard/build_info_test.dart +++ b/packages/flutter_tools/test/general.shard/build_info_test.dart
@@ -17,6 +17,8 @@ testUsingContext('CFBundleVersion for iOS', () async { String buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, 'xyz'); expect(buildName, '0'); + buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '0.0.1'); + expect(buildName, '0.0.1'); buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '123.xyz'); expect(buildName, '123'); buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '123.456.xyz'); @@ -37,6 +39,8 @@ testUsingContext('CFBundleShortVersionString for iOS', () async { String buildName = validatedBuildNameForPlatform(TargetPlatform.ios, 'xyz'); expect(buildName, '0.0.0'); + buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '0.0.1'); + expect(buildName, '0.0.1'); buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '123.456.xyz'); expect(buildName, '123.456.0'); buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '123.xyz');
diff --git a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart index d3bb870..231a2b8 100644 --- a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart +++ b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart
@@ -415,6 +415,23 @@ ); }); + test('parses major.minor.patch with no build version', () async { + const String manifest = ''' +name: test +version: 0.0.1 +dependencies: + flutter: + sdk: flutter +flutter: +'''; + await checkManifestVersion( + manifest: manifest, + expectedAppVersion: '0.0.1', + expectedBuildName: '0.0.1', + expectedBuildNumber: null, + ); + }); + test('parses major.minor.patch+build version clause 2', () async { const String manifest = ''' name: test
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 ec81949..ef36055 100644 --- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -413,6 +413,7 @@ final File localPropertiesFile = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); expect(propertyFor('FLUTTER_BUILD_NAME', localPropertiesFile), expectedBuildName); expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), expectedBuildNumber); + expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), isNotNull); } testUsingOsxContext('extract build name and number from pubspec.yaml', () async { @@ -448,7 +449,7 @@ manifestString: manifest, buildInfo: buildInfo, expectedBuildName: '1.0.0', - expectedBuildNumber: null, + expectedBuildNumber: '1.0.0', ); }); @@ -470,6 +471,24 @@ ); }); + testUsingOsxContext('allow build info to override build name with build number fallback', () async { + const String manifest = ''' +name: test +version: 1.0.0 +dependencies: + flutter: + sdk: flutter +flutter: +'''; + const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: '1.0.2'); + await checkBuildVersion( + manifestString: manifest, + buildInfo: buildInfo, + expectedBuildName: '1.0.2', + expectedBuildNumber: '1.0.2', + ); + }); + testUsingOsxContext('allow build info to override build number', () async { const String manifest = ''' name: test