mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Guess sign iOS with the first certificate when running in machine mode (#10870)
* Guess sign with the first certificate when multiple are available in machine mode * review
This commit is contained in:
parent
a41e354a55
commit
57746f38c0
@ -341,6 +341,7 @@ class AndroidDevice extends Device {
|
||||
String kernelPath,
|
||||
bool prebuiltApplication: false,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
}) async {
|
||||
if (!await _checkForSupportedAdbVersion() || !await _checkForSupportedAndroidVersion())
|
||||
return new LaunchResult.failed();
|
||||
|
||||
@ -260,6 +260,7 @@ Future<LaunchResult> _startApp(DriveCommand command) async {
|
||||
diagnosticPort: command.diagnosticPort,
|
||||
),
|
||||
platformArgs: platformArgs,
|
||||
usesTerminalUi: false,
|
||||
);
|
||||
|
||||
if (!result.started) {
|
||||
|
||||
@ -222,6 +222,11 @@ abstract class Device {
|
||||
///
|
||||
/// [platformArgs] allows callers to pass platform-specific arguments to the
|
||||
/// start call. The build mode is not used by all platforms.
|
||||
///
|
||||
/// If [usesTerminalUi] is true, Flutter Tools may attempt to prompt the
|
||||
/// user to resolve fixable issues such as selecting a signing certificate
|
||||
/// for iOS device deployment. Set to false if stdin cannot be read from while
|
||||
/// attempting to start the app.
|
||||
Future<LaunchResult> startApp(
|
||||
ApplicationPackage package,
|
||||
BuildMode mode, {
|
||||
@ -231,7 +236,8 @@ abstract class Device {
|
||||
Map<String, dynamic> platformArgs,
|
||||
String kernelPath,
|
||||
bool prebuiltApplication: false,
|
||||
bool applicationNeedsRebuild: false
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
});
|
||||
|
||||
/// Does this device implement support for hot reloading / restarting?
|
||||
|
||||
@ -68,6 +68,7 @@ class FuchsiaDevice extends Device {
|
||||
bool prebuiltApplication: false,
|
||||
String kernelPath,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: false,
|
||||
}) => new Future<Null>.error('unimplemented');
|
||||
|
||||
@override
|
||||
|
||||
@ -80,7 +80,7 @@ final RegExp _certificateOrganizationalUnitExtractionPattern = new RegExp(r'OU=(
|
||||
///
|
||||
/// Will return null if none are found, if the user cancels or if the Xcode
|
||||
/// project has a development team set in the project's build settings.
|
||||
Future<String> getCodeSigningIdentityDevelopmentTeam(BuildableIOSApp iosApp) async{
|
||||
Future<String> getCodeSigningIdentityDevelopmentTeam({BuildableIOSApp iosApp, bool usesTerminalUi: true}) async{
|
||||
if (iosApp.buildSettings == null)
|
||||
return null;
|
||||
|
||||
@ -115,7 +115,7 @@ Future<String> getCodeSigningIdentityDevelopmentTeam(BuildableIOSApp iosApp) asy
|
||||
.toSet() // Unique.
|
||||
.toList();
|
||||
|
||||
final String signingIdentity = await _chooseSigningIdentity(validCodeSigningIdentities);
|
||||
final String signingIdentity = await _chooseSigningIdentity(validCodeSigningIdentities, usesTerminalUi);
|
||||
|
||||
// If none are chosen, return null.
|
||||
if (signingIdentity == null)
|
||||
@ -153,7 +153,7 @@ Future<String> getCodeSigningIdentityDevelopmentTeam(BuildableIOSApp iosApp) asy
|
||||
?.group(1);
|
||||
}
|
||||
|
||||
Future<String> _chooseSigningIdentity(List<String> validCodeSigningIdentities) async {
|
||||
Future<String> _chooseSigningIdentity(List<String> validCodeSigningIdentities, bool usesTerminalUi) async {
|
||||
// The user has no valid code signing identities.
|
||||
if (validCodeSigningIdentities.isEmpty) {
|
||||
printError(noCertificatesInstruction, emphasis: true);
|
||||
@ -176,6 +176,11 @@ Future<String> _chooseSigningIdentity(List<String> validCodeSigningIdentities) a
|
||||
}
|
||||
}
|
||||
|
||||
// If terminal UI can't be used, just attempt with the first valid certificate
|
||||
// since we can't ask the user.
|
||||
if (!usesTerminalUi)
|
||||
return validCodeSigningIdentities.first;
|
||||
|
||||
final int count = validCodeSigningIdentities.length;
|
||||
printStatus(
|
||||
'Multiple valid development certificates available (your choice will be saved):',
|
||||
|
||||
@ -175,13 +175,20 @@ class IOSDevice extends Device {
|
||||
bool prebuiltApplication: false,
|
||||
String kernelPath,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
}) async {
|
||||
if (!prebuiltApplication) {
|
||||
// TODO(chinmaygarde): Use mainPath, route.
|
||||
printTrace('Building ${app.name} for $id');
|
||||
|
||||
// Step 1: Build the precompiled/DBC application if necessary.
|
||||
final XcodeBuildResult buildResult = await buildXcodeProject(app: app, mode: mode, target: mainPath, buildForDevice: true);
|
||||
final XcodeBuildResult buildResult = await buildXcodeProject(
|
||||
app: app,
|
||||
mode: mode,
|
||||
target: mainPath,
|
||||
buildForDevice: true,
|
||||
usesTerminalUi: usesTerminalUi,
|
||||
);
|
||||
if (!buildResult.success) {
|
||||
printError('Could not build the precompiled application for the device.');
|
||||
await diagnoseXcodeBuildFailure(buildResult, app);
|
||||
|
||||
@ -193,7 +193,8 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
BuildMode mode,
|
||||
String target: flx.defaultMainPath,
|
||||
bool buildForDevice,
|
||||
bool codesign: true
|
||||
bool codesign: true,
|
||||
bool usesTerminalUi: true,
|
||||
}) async {
|
||||
if (!_checkXcodeVersion())
|
||||
return new XcodeBuildResult(success: false);
|
||||
@ -205,7 +206,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
|
||||
String developmentTeam;
|
||||
if (codesign && buildForDevice)
|
||||
developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app, usesTerminalUi: usesTerminalUi);
|
||||
|
||||
// Before the build, all service definitions must be updated and the dylibs
|
||||
// copied over to a location that is suitable for Xcodebuild to find them.
|
||||
|
||||
@ -315,6 +315,7 @@ class IOSSimulator extends Device {
|
||||
String kernelPath,
|
||||
bool prebuiltApplication: false,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
}) async {
|
||||
if (!prebuiltApplication) {
|
||||
printTrace('Building ${app.name} for $id.');
|
||||
|
||||
@ -239,7 +239,8 @@ class FlutterDevice {
|
||||
route: route,
|
||||
prebuiltApplication: prebuiltMode,
|
||||
kernelPath: hotRunner.kernelFilePath,
|
||||
applicationNeedsRebuild: shouldBuild || hasDirtyDependencies
|
||||
applicationNeedsRebuild: shouldBuild || hasDirtyDependencies,
|
||||
usesTerminalUi: hotRunner.usesTerminalUI,
|
||||
);
|
||||
|
||||
final LaunchResult result = await futureResult;
|
||||
@ -298,7 +299,8 @@ class FlutterDevice {
|
||||
platformArgs: platformArgs,
|
||||
route: route,
|
||||
prebuiltApplication: prebuiltMode,
|
||||
applicationNeedsRebuild: shouldBuild || hasDirtyDependencies
|
||||
applicationNeedsRebuild: shouldBuild || hasDirtyDependencies,
|
||||
usesTerminalUi: coldRunner.usesTerminalUI,
|
||||
);
|
||||
|
||||
if (!result.started) {
|
||||
|
||||
@ -38,7 +38,7 @@ void main() {
|
||||
|
||||
testUsingContext('No auto-sign if Xcode project settings are not available', () async {
|
||||
app = new BuildableIOSApp(projectBundleId: 'test.app');
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
|
||||
expect(developmentTeam, isNull);
|
||||
});
|
||||
|
||||
@ -49,7 +49,7 @@ void main() {
|
||||
'DEVELOPMENT_TEAM': 'abc',
|
||||
},
|
||||
);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
|
||||
expect(developmentTeam, isNull);
|
||||
expect(testLogger.statusText, equals(
|
||||
'Automatically signing iOS for device deployment using specified development team in Xcode project: abc\n'
|
||||
@ -59,7 +59,7 @@ void main() {
|
||||
testUsingContext('No auto-sign if security or openssl not available', () async {
|
||||
when(mockProcessManager.runSync(<String>['which', 'security']))
|
||||
.thenReturn(exitsFail);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
|
||||
expect(developmentTeam, isNull);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
@ -77,7 +77,7 @@ void main() {
|
||||
|
||||
String developmentTeam;
|
||||
try {
|
||||
developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
|
||||
fail('No identity should throw tool error');
|
||||
} on ToolExit {
|
||||
expect(developmentTeam, isNull);
|
||||
@ -131,7 +131,7 @@ void main() {
|
||||
when(mockProcess.stderr).thenReturn(mockStdErr);
|
||||
when(mockProcess.exitCode).thenReturn(0);
|
||||
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
|
||||
|
||||
expect(testLogger.statusText, contains('iPhone Developer: Profile 1 (1111AAAA11)'));
|
||||
expect(testLogger.errorText, isEmpty);
|
||||
@ -189,7 +189,7 @@ void main() {
|
||||
when(mockOpenSslProcess.stderr).thenReturn(mockOpenSslStdErr);
|
||||
when(mockOpenSslProcess.exitCode).thenReturn(0);
|
||||
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
@ -211,6 +211,68 @@ void main() {
|
||||
AnsiTerminal: () => testTerminal,
|
||||
});
|
||||
|
||||
testUsingContext('Test multiple identity in machine mode works', () async {
|
||||
when(mockProcessManager.runSync(<String>['which', 'security']))
|
||||
.thenReturn(exitsHappy);
|
||||
when(mockProcessManager.runSync(<String>['which', 'openssl']))
|
||||
.thenReturn(exitsHappy);
|
||||
when(mockProcessManager.runSync(
|
||||
argThat(contains('find-identity')), environment: any, workingDirectory: any,
|
||||
)).thenReturn(new ProcessResult(
|
||||
1, // pid
|
||||
0, // exitCode
|
||||
'''
|
||||
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
|
||||
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)"
|
||||
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
|
||||
3 valid identities found''',
|
||||
''
|
||||
));
|
||||
mockTerminalStdInStream =
|
||||
new Stream<String>.fromFuture(new Future<String>.error(new Exception('Cannot read from StdIn')));
|
||||
when(mockProcessManager.runSync(
|
||||
<String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
|
||||
environment: any,
|
||||
workingDirectory: any,
|
||||
)).thenReturn(new ProcessResult(
|
||||
1, // pid
|
||||
0, // exitCode
|
||||
'This is a mock certificate',
|
||||
'',
|
||||
));
|
||||
|
||||
final MockProcess mockOpenSslProcess = new MockProcess();
|
||||
final MockStdIn mockOpenSslStdIn = new MockStdIn();
|
||||
final MockStream mockOpenSslStdErr = new MockStream();
|
||||
|
||||
when(mockProcessManager.start(
|
||||
argThat(contains('openssl')), environment: any, workingDirectory: any,
|
||||
)).thenReturn(new Future<Process>.value(mockOpenSslProcess));
|
||||
|
||||
when(mockOpenSslProcess.stdin).thenReturn(mockOpenSslStdIn);
|
||||
when(mockOpenSslProcess.stdout).thenReturn(new Stream<List<int>>.fromFuture(
|
||||
new Future<List<int>>.value(UTF8.encode(
|
||||
'subject= /CN=iPhone Developer: Profile 1 (1111AAAA11)/OU=5555EEEE55/O=My Team/C=US'
|
||||
)),
|
||||
));
|
||||
when(mockOpenSslProcess.stderr).thenReturn(mockOpenSslStdErr);
|
||||
when(mockOpenSslProcess.exitCode).thenReturn(0);
|
||||
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app, usesTerminalUi: false);
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
contains('Signing iOS app for device deployment using developer identity: "iPhone Developer: Profile 1 (1111AAAA11)"'),
|
||||
);
|
||||
expect(testLogger.errorText, isEmpty);
|
||||
verify(mockOpenSslStdIn.write('This is a mock certificate'));
|
||||
expect(developmentTeam, '5555EEEE55');
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
AnsiTerminal: () => testTerminal,
|
||||
});
|
||||
|
||||
testUsingContext('Test saved certificate used', () async {
|
||||
when(mockProcessManager.runSync(<String>['which', 'security']))
|
||||
.thenReturn(exitsHappy);
|
||||
@ -257,7 +319,7 @@ void main() {
|
||||
when(mockOpenSslProcess.exitCode).thenReturn(0);
|
||||
when(mockConfig.getValue('ios-signing-cert')).thenReturn('iPhone Developer: Profile 3 (3333CCCC33)');
|
||||
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
|
||||
|
||||
expect(
|
||||
testLogger.statusText,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user