mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Log XCResult before other build issues (#100787)
This commit is contained in:
parent
74cdc42207
commit
1755819cb1
@ -574,37 +574,14 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa
|
||||
).send();
|
||||
}
|
||||
|
||||
// Building for iOS Simulator, but the linked and embedded framework 'App.framework' was built for iOS.
|
||||
// or
|
||||
// Building for iOS, but the linked and embedded framework 'App.framework' was built for iOS Simulator.
|
||||
if ((result.stdout?.contains('Building for iOS') ?? false)
|
||||
&& (result.stdout?.contains('but the linked and embedded framework') ?? false)
|
||||
&& (result.stdout?.contains('was built for iOS') ?? false)) {
|
||||
logger.printError('');
|
||||
logger.printError('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.');
|
||||
logger.printError('');
|
||||
logger.printError('You can temporarily work around this issue by running:');
|
||||
logger.printError(' flutter clean');
|
||||
return;
|
||||
}
|
||||
if (xcodeBuildExecution != null
|
||||
&& xcodeBuildExecution.environmentType == EnvironmentType.physical
|
||||
&& (result.stdout?.contains('BCEROR') ?? false)
|
||||
// May need updating if Xcode changes its outputs.
|
||||
&& (result.stdout?.contains("Xcode couldn't find a provisioning profile matching") ?? false)) {
|
||||
logger.printError(noProvisioningProfileInstruction, emphasis: true);
|
||||
return;
|
||||
}
|
||||
// Make sure the user has specified one of:
|
||||
// * DEVELOPMENT_TEAM (automatic signing)
|
||||
// * PROVISIONING_PROFILE (manual signing)
|
||||
if (xcodeBuildExecution != null &&
|
||||
xcodeBuildExecution.environmentType == EnvironmentType.physical &&
|
||||
!<String>['DEVELOPMENT_TEAM', 'PROVISIONING_PROFILE'].any(
|
||||
xcodeBuildExecution.buildSettings.containsKey)) {
|
||||
logger.printError(noDevelopmentTeamInstruction, emphasis: true);
|
||||
return;
|
||||
// Handle errors.
|
||||
final bool issueDetected = _handleIssues(result.xcResult, logger, xcodeBuildExecution);
|
||||
|
||||
if (!issueDetected && xcodeBuildExecution != null) {
|
||||
// Fallback to use stdout to detect and print issues.
|
||||
_parseIssueInStdout(xcodeBuildExecution, logger, result);
|
||||
}
|
||||
|
||||
if (xcodeBuildExecution != null
|
||||
&& xcodeBuildExecution.environmentType == EnvironmentType.physical
|
||||
&& (xcodeBuildExecution.buildSettings['PRODUCT_BUNDLE_IDENTIFIER']?.contains('com.example') ?? false)) {
|
||||
@ -614,19 +591,6 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa
|
||||
logger.printError(' open ios/Runner.xcworkspace');
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle xcresult errors.
|
||||
final XCResult? xcResult = result.xcResult;
|
||||
if (xcResult == null) {
|
||||
return;
|
||||
}
|
||||
if (!xcResult.parseSuccess) {
|
||||
globals.printTrace('XCResult parsing error: ${xcResult.parsingErrorMessage}');
|
||||
return;
|
||||
}
|
||||
for (final XCResultIssue issue in xcResult.issues) {
|
||||
_handleXCResultIssue(issue: issue, logger: logger);
|
||||
}
|
||||
}
|
||||
|
||||
/// xcodebuild <buildaction> parameter (see man xcodebuild for details).
|
||||
@ -724,7 +688,7 @@ bool upgradePbxProjWithFlutterAssets(IosProject project, Logger logger) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void _handleXCResultIssue({required XCResultIssue issue, required Logger logger}) {
|
||||
_XCResultIssueHandlingResult _handleXCResultIssue({required XCResultIssue issue, required Logger logger}) {
|
||||
// Issue summary from xcresult.
|
||||
final StringBuffer issueSummaryBuffer = StringBuffer();
|
||||
issueSummaryBuffer.write(issue.subType ?? 'Unknown');
|
||||
@ -744,16 +708,89 @@ void _handleXCResultIssue({required XCResultIssue issue, required Logger logger}
|
||||
break;
|
||||
}
|
||||
|
||||
// Add more custom output for flutter users.
|
||||
if (issue.message != null && issue.message!.toLowerCase().contains('provisioning profile')) {
|
||||
final String? message = issue.message;
|
||||
if (message == null) {
|
||||
return _XCResultIssueHandlingResult(requiresProvisioningProfile: false, hasProvisioningProfileIssue: false);
|
||||
}
|
||||
|
||||
// Add more error messages for flutter users for some special errors.
|
||||
if (message.toLowerCase().contains('requires a provisioning profile.')) {
|
||||
return _XCResultIssueHandlingResult(requiresProvisioningProfile: true, hasProvisioningProfileIssue: true);
|
||||
} else if (message.toLowerCase().contains('provisioning profile')) {
|
||||
return _XCResultIssueHandlingResult(requiresProvisioningProfile: false, hasProvisioningProfileIssue: true);
|
||||
}
|
||||
return _XCResultIssueHandlingResult(requiresProvisioningProfile: false, hasProvisioningProfileIssue: false);
|
||||
}
|
||||
|
||||
// Returns `true` if at least one issue is detected.
|
||||
bool _handleIssues(XCResult? xcResult, Logger logger, XcodeBuildExecution? xcodeBuildExecution) {
|
||||
bool requiresProvisioningProfile = false;
|
||||
bool hasProvisioningProfileIssue = false;
|
||||
bool issueDetected = false;
|
||||
|
||||
if (xcResult != null && xcResult.parseSuccess) {
|
||||
for (final XCResultIssue issue in xcResult.issues) {
|
||||
final _XCResultIssueHandlingResult handlingResult = _handleXCResultIssue(issue: issue, logger: logger);
|
||||
if (handlingResult.hasProvisioningProfileIssue) {
|
||||
hasProvisioningProfileIssue = true;
|
||||
}
|
||||
if (handlingResult.requiresProvisioningProfile) {
|
||||
requiresProvisioningProfile = true;
|
||||
}
|
||||
issueDetected = true;
|
||||
}
|
||||
} else if (xcResult != null) {
|
||||
globals.printTrace('XCResult parsing error: ${xcResult.parsingErrorMessage}');
|
||||
}
|
||||
|
||||
if (requiresProvisioningProfile) {
|
||||
logger.printError(noProvisioningProfileInstruction, emphasis: true);
|
||||
} else if (_missingDevelopmentTeam(xcodeBuildExecution)) {
|
||||
issueDetected = true;
|
||||
logger.printError(noDevelopmentTeamInstruction, emphasis: true);
|
||||
} else if (hasProvisioningProfileIssue) {
|
||||
logger.printError('');
|
||||
logger.printError('It appears that there was a problem signing your application prior to installation on the device.');
|
||||
logger.printError('');
|
||||
logger.printError('Verify that the Bundle Identifier in your project is your signing id in Xcode');
|
||||
logger.printError(' open ios/Runner.xcworkspace');
|
||||
logger.printError('');
|
||||
logger.printError("Also try selecting 'Product > Build' to fix the problem:");
|
||||
logger.printError("Also try selecting 'Product > Build' to fix the problem.");
|
||||
}
|
||||
return issueDetected;
|
||||
}
|
||||
|
||||
// Return 'true' a missing development team issue is detected.
|
||||
bool _missingDevelopmentTeam(XcodeBuildExecution? xcodeBuildExecution) {
|
||||
// Make sure the user has specified one of:
|
||||
// * DEVELOPMENT_TEAM (automatic signing)
|
||||
// * PROVISIONING_PROFILE (manual signing)
|
||||
return xcodeBuildExecution != null && xcodeBuildExecution.environmentType == EnvironmentType.physical &&
|
||||
!<String>['DEVELOPMENT_TEAM', 'PROVISIONING_PROFILE'].any(
|
||||
xcodeBuildExecution.buildSettings.containsKey);
|
||||
}
|
||||
// Detects and handles errors from stdout.
|
||||
//
|
||||
// As detecting issues in stdout is not usually accurate, this should be used as a fallback when other issue detecting methods failed.
|
||||
void _parseIssueInStdout(XcodeBuildExecution xcodeBuildExecution, Logger logger, XcodeBuildResult result) {
|
||||
if (xcodeBuildExecution.environmentType == EnvironmentType.physical
|
||||
// May need updating if Xcode changes its outputs.
|
||||
&& (result.stdout?.contains('requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor') ?? false)) {
|
||||
logger.printError(noProvisioningProfileInstruction, emphasis: true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The result of [_handleXCResultIssue].
|
||||
class _XCResultIssueHandlingResult {
|
||||
|
||||
_XCResultIssueHandlingResult({required this.requiresProvisioningProfile, required this.hasProvisioningProfileIssue});
|
||||
|
||||
// An issue indicates that user didn't provide the provisioning profile.
|
||||
final bool requiresProvisioningProfile;
|
||||
|
||||
// An issue indicates that there is a provisioning profile issue.
|
||||
final bool hasProvisioningProfileIssue;
|
||||
}
|
||||
|
||||
const String _kResultBundlePath = 'temporary_xcresult_bundle';
|
||||
|
@ -8,9 +8,11 @@ import 'package:args/command_runner.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/commands/build.dart';
|
||||
import 'package:flutter_tools/src/commands/build_ios.dart';
|
||||
import 'package:flutter_tools/src/ios/code_signing.dart';
|
||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
|
||||
@ -20,6 +22,9 @@ import '../../src/context.dart';
|
||||
import '../../src/test_flutter_command_runner.dart';
|
||||
|
||||
class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInterpreter {
|
||||
|
||||
FakeXcodeProjectInterpreterWithBuildSettings({this.productBundleIdentifier, this.developmentTeam = 'abc'});
|
||||
|
||||
@override
|
||||
Future<Map<String, String>> getBuildSettings(
|
||||
String projectPath, {
|
||||
@ -27,12 +32,17 @@ class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInter
|
||||
Duration timeout = const Duration(minutes: 1),
|
||||
}) async {
|
||||
return <String, String>{
|
||||
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
|
||||
'DEVELOPMENT_TEAM': 'abc',
|
||||
'PRODUCT_BUNDLE_IDENTIFIER': productBundleIdentifier ?? 'io.flutter.someProject',
|
||||
'TARGET_BUILD_DIR': 'build/ios/Release-iphoneos',
|
||||
'WRAPPER_NAME': 'Runner.app',
|
||||
if (developmentTeam != null) 'DEVELOPMENT_TEAM': developmentTeam,
|
||||
};
|
||||
}
|
||||
|
||||
/// The value of 'PRODUCT_BUNDLE_IDENTIFIER'.
|
||||
final String productBundleIdentifier;
|
||||
|
||||
final String developmentTeam;
|
||||
}
|
||||
|
||||
final Platform macosPlatform = FakePlatform(
|
||||
@ -117,6 +127,7 @@ void main() {
|
||||
bool simulator = false,
|
||||
String deviceId,
|
||||
int exitCode = 0,
|
||||
String stdout,
|
||||
void Function() onRun,
|
||||
}) {
|
||||
return FakeCommand(
|
||||
@ -159,6 +170,7 @@ void main() {
|
||||
stdout: '''
|
||||
TARGET_BUILD_DIR=build/ios/Release-iphoneos
|
||||
WRAPPER_NAME=Runner.app
|
||||
$stdout
|
||||
''',
|
||||
exitCode: exitCode,
|
||||
onRun: onRun,
|
||||
@ -439,7 +451,7 @@ void main() {
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||
});
|
||||
|
||||
testUsingContext('Extra error message for provision profile issue in xcresulb bundle.', () async {
|
||||
testUsingContext('Extra error message for provision profile issue in xcresult bundle.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
@ -453,7 +465,7 @@ void main() {
|
||||
expect(testLogger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.'));
|
||||
expect(testLogger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode'));
|
||||
expect(testLogger.errorText, contains('open ios/Runner.xcworkspace'));
|
||||
expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem:"));
|
||||
expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem."));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
@ -467,6 +479,241 @@ void main() {
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||
});
|
||||
|
||||
testUsingContext('Display xcresult issues with default bundle identifier.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'"));
|
||||
expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56'));
|
||||
expect(testLogger.errorText, contains('It appears that your application still contains the default signing identifier.'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonWithIssues),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
Platform: () => macosPlatform,
|
||||
EnvironmentType: () => EnvironmentType.physical,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(productBundleIdentifier: 'com.example'),
|
||||
});
|
||||
|
||||
testUsingContext('Display xcresult issues with no provisioning profile.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains('Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor'));
|
||||
expect(testLogger.errorText, contains(noProvisioningProfileInstruction));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(
|
||||
exitCode: 1,
|
||||
onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}
|
||||
),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||
});
|
||||
|
||||
testUsingContext('Failed to parse xcresult but display missing provisioning profile issue from stdout.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains(noProvisioningProfileInstruction));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(
|
||||
exitCode: 1,
|
||||
stdout: '''
|
||||
Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor
|
||||
''',
|
||||
onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}
|
||||
),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||
});
|
||||
|
||||
testUsingContext('Failed to parse xcresult but detected no development team issue.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains(noDevelopmentTeamInstruction));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(
|
||||
exitCode: 1,
|
||||
onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}
|
||||
),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
|
||||
});
|
||||
|
||||
|
||||
testUsingContext('xcresult did not detect issue but detected by stdout.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains(noProvisioningProfileInstruction));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(
|
||||
exitCode: 1,
|
||||
stdout: '''
|
||||
Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor
|
||||
''',
|
||||
onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}
|
||||
),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonNoIssues),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
EnvironmentType: () => EnvironmentType.physical,
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
|
||||
});
|
||||
|
||||
testUsingContext('xcresult did not detect issue, no development team is detected from build setting.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains(noDevelopmentTeamInstruction));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(
|
||||
exitCode: 1,
|
||||
onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}
|
||||
),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
|
||||
});
|
||||
|
||||
testUsingContext('No development team issue error message is not displayed if no provisioning profile issue is detected from xcresult first.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains(noProvisioningProfileInstruction));
|
||||
expect(testLogger.errorText, isNot(contains(noDevelopmentTeamInstruction)));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(
|
||||
exitCode: 1,
|
||||
onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}
|
||||
),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
|
||||
});
|
||||
|
||||
testUsingContext('General provisioning profile issue error message is not displayed if no development team issue is detected first.', () async {
|
||||
final BuildCommand command = BuildCommand();
|
||||
|
||||
_createMinimalMockProjectFiles();
|
||||
|
||||
await expectLater(
|
||||
createTestCommandRunner(command).run(const <String>['build', 'ios', '--no-pub']),
|
||||
throwsToolExit(),
|
||||
);
|
||||
|
||||
expect(testLogger.errorText, contains(noDevelopmentTeamInstruction));
|
||||
expect(testLogger.errorText, isNot(contains('It appears that there was a problem signing your application prior to installation on the device.')));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
xattrCommand,
|
||||
_setUpFakeXcodeBuildHandler(
|
||||
exitCode: 1,
|
||||
onRun: () {
|
||||
fileSystem.systemTempDirectory.childDirectory(_xcBundleFilePath).createSync();
|
||||
}
|
||||
),
|
||||
_setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue),
|
||||
_setUpRsyncCommand(),
|
||||
]),
|
||||
Platform: () => macosPlatform,
|
||||
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
|
||||
});
|
||||
});
|
||||
|
||||
group('xcresults simulator', () {
|
||||
|
@ -721,7 +721,7 @@ void main() {
|
||||
expect(testLogger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.'));
|
||||
expect(testLogger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode'));
|
||||
expect(testLogger.errorText, contains('open ios/Runner.xcworkspace'));
|
||||
expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem:"));
|
||||
expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem."));
|
||||
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
|
@ -10,6 +10,7 @@ import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/process.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/ios/code_signing.dart';
|
||||
import 'package:flutter_tools/src/ios/iproxy.dart';
|
||||
import 'package:flutter_tools/src/ios/mac.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
@ -166,7 +167,11 @@ void main() {
|
||||
));
|
||||
});
|
||||
|
||||
testWithoutContext('No provisioning profile shows message', () async {
|
||||
testWithoutContext('fallback to stdout: No provisioning profile shows message', () async {
|
||||
final Map<String, String> buildSettingsWithDevTeam = <String, String>{
|
||||
'PRODUCT_BUNDLE_IDENTIFIER': 'test.app',
|
||||
'DEVELOPMENT_TEAM': 'a team',
|
||||
};
|
||||
final XcodeBuildResult buildResult = XcodeBuildResult(
|
||||
success: false,
|
||||
stdout: '''
|
||||
@ -194,7 +199,7 @@ Xcode's output:
|
||||
=== CLEAN TARGET Runner OF PROJECT Runner WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
[BCEROR]No profiles for 'com.example.test' were found: Xcode couldn't find a provisioning profile matching 'com.example.test'.
|
||||
[BCEROR]"Runner" requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor.
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
@ -228,14 +233,14 @@ Error launching application on iPhone.''',
|
||||
buildCommands: <String>['xcrun', 'xcodebuild', 'blah'],
|
||||
appDirectory: '/blah/blah',
|
||||
environmentType: EnvironmentType.physical,
|
||||
buildSettings: buildSettings,
|
||||
buildSettings: buildSettingsWithDevTeam,
|
||||
),
|
||||
);
|
||||
|
||||
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
|
||||
expect(
|
||||
logger.errorText,
|
||||
contains("No Provisioning Profile was found for your project's Bundle Identifier or your \ndevice."),
|
||||
contains(noProvisioningProfileInstruction),
|
||||
);
|
||||
});
|
||||
|
||||
@ -319,80 +324,6 @@ Could not build the precompiled application for the device.''',
|
||||
contains('Building a deployable iOS app requires a selected Development Team with a \nProvisioning Profile.'),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('embedded and linked framework iOS mismatch shows message', () async {
|
||||
final XcodeBuildResult buildResult = XcodeBuildResult(
|
||||
success: false,
|
||||
stdout: '''
|
||||
Launching lib/main.dart on iPhone in debug mode...
|
||||
Automatically signing iOS for device deployment using specified development team in Xcode project: blah
|
||||
Xcode build done. 5.7s
|
||||
Failed to build iOS app
|
||||
Error output from Xcode build:
|
||||
↳
|
||||
** BUILD FAILED **
|
||||
Xcode's output:
|
||||
↳
|
||||
note: Using new build system
|
||||
note: Building targets in parallel
|
||||
note: Planning build
|
||||
note: Constructing build description
|
||||
error: Building for iOS Simulator, but the linked and embedded framework 'App.framework' was built for iOS. (in target 'Runner' from project 'Runner')
|
||||
Could not build the precompiled application for the device.
|
||||
|
||||
Error launching application on iPhone.
|
||||
Exited (sigterm)''',
|
||||
xcodeBuildExecution: XcodeBuildExecution(
|
||||
buildCommands: <String>['xcrun', 'xcodebuild', 'blah'],
|
||||
appDirectory: '/blah/blah',
|
||||
environmentType: EnvironmentType.physical,
|
||||
buildSettings: buildSettings,
|
||||
),
|
||||
);
|
||||
|
||||
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
|
||||
expect(
|
||||
logger.errorText,
|
||||
contains('Your Xcode project requires migration.'),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('embedded and linked framework iOS simulator mismatch shows message', () async {
|
||||
final XcodeBuildResult buildResult = XcodeBuildResult(
|
||||
success: false,
|
||||
stdout: '''
|
||||
Launching lib/main.dart on iPhone in debug mode...
|
||||
Automatically signing iOS for device deployment using specified development team in Xcode project: blah
|
||||
Xcode build done. 5.7s
|
||||
Failed to build iOS app
|
||||
Error output from Xcode build:
|
||||
↳
|
||||
** BUILD FAILED **
|
||||
Xcode's output:
|
||||
↳
|
||||
note: Using new build system
|
||||
note: Building targets in parallel
|
||||
note: Planning build
|
||||
note: Constructing build description
|
||||
error: Building for iOS, but the linked and embedded framework 'App.framework' was built for iOS Simulator. (in target 'Runner' from project 'Runner')
|
||||
Could not build the precompiled application for the device.
|
||||
|
||||
Error launching application on iPhone.
|
||||
Exited (sigterm)''',
|
||||
xcodeBuildExecution: XcodeBuildExecution(
|
||||
buildCommands: <String>['xcrun', 'xcodebuild', 'blah'],
|
||||
appDirectory: '/blah/blah',
|
||||
environmentType: EnvironmentType.physical,
|
||||
buildSettings: buildSettings,
|
||||
),
|
||||
);
|
||||
|
||||
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
|
||||
expect(
|
||||
logger.errorText,
|
||||
contains('Your Xcode project requires migration.'),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Upgrades project.pbxproj for old asset usage', () {
|
||||
|
@ -181,6 +181,82 @@ const String kSampleResultJsonWithIssues = r'''
|
||||
}
|
||||
''';
|
||||
|
||||
/// An example xcresult bundle json that contains some warning and some errors.
|
||||
const String kSampleResultJsonWithNoProvisioningProfileIssue = r'''
|
||||
{
|
||||
"issues" : {
|
||||
"_type" : {
|
||||
"_name" : "ResultIssueSummaries"
|
||||
},
|
||||
"errorSummaries" : {
|
||||
"_type" : {
|
||||
"_name" : "Array"
|
||||
},
|
||||
"_values" : [
|
||||
{
|
||||
"_type" : {
|
||||
"_name" : "IssueSummary"
|
||||
},
|
||||
"documentLocationInCreatingWorkspace" : {
|
||||
"_type" : {
|
||||
"_name" : "DocumentLocation"
|
||||
},
|
||||
"concreteTypeName" : {
|
||||
"_type" : {
|
||||
"_name" : "String"
|
||||
},
|
||||
"_value" : "DVTTextDocumentLocation"
|
||||
},
|
||||
"url" : {
|
||||
"_type" : {
|
||||
"_name" : "String"
|
||||
},
|
||||
"_value" : "file:\/\/\/Users\/m\/Projects\/test_create\/ios\/Runner\/AppDelegate.m#CharacterRangeLen=0&CharacterRangeLoc=263&EndingColumnNumber=56&EndingLineNumber=7&LocationEncoding=1&StartingColumnNumber=56&StartingLineNumber=7"
|
||||
}
|
||||
},
|
||||
"issueType" : {
|
||||
"_type" : {
|
||||
"_name" : "String"
|
||||
},
|
||||
"_value" : "Error"
|
||||
},
|
||||
"message" : {
|
||||
"_type" : {
|
||||
"_name" : "String"
|
||||
},
|
||||
"_value" : "Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"warningSummaries" : {
|
||||
"_type" : {
|
||||
"_name" : "Array"
|
||||
},
|
||||
"_values" : [
|
||||
{
|
||||
"_type" : {
|
||||
"_name" : "IssueSummary"
|
||||
},
|
||||
"issueType" : {
|
||||
"_type" : {
|
||||
"_name" : "String"
|
||||
},
|
||||
"_value" : "Warning"
|
||||
},
|
||||
"message" : {
|
||||
"_type" : {
|
||||
"_name" : "String"
|
||||
},
|
||||
"_value" : "The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
/// An example xcresult bundle json that contains some warning and some errors.
|
||||
const String kSampleResultJsonWithIssuesAndInvalidUrl = r'''
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user