From 3d77a82d2d8f91d0fdd3f325234839066a1a9db7 Mon Sep 17 00:00:00 2001 From: Panayot Cankov Date: Fri, 9 Dec 2016 17:32:46 +0200 Subject: [PATCH 1/2] Add initial code for manual and automatic Xcode signing --- lib/definitions/project.d.ts | 4 + lib/services/ios-project-service.ts | 242 ++++++++++++++++++++++------ package.json | 2 + 3 files changed, 195 insertions(+), 53 deletions(-) diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 28c0679972..e2e7ce1d46 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -58,6 +58,10 @@ interface IiOSBuildConfig extends IBuildConfig { * Code sign identity used for build. If not set iPhone Developer is used as a default when building for device. */ codeSignIdentity?: string; + /** + * Team identifier. + */ + teamIdentifier?: string; } interface IPlatformProjectService { diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index fa1cb53293..1850c601e6 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -11,6 +11,10 @@ import { PlistSession } from "plist-merge-patch"; import {EOL} from "os"; import * as temp from "temp"; import * as plist from "plist"; +import { cert, provision } from "ios-mobileprovision-finder"; +import { Xcode } from "pbxproj-dom/xcode"; + +type XcodeSigningStyle = "Manual" | "Automatic"; export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase implements IPlatformProjectService { private static XCODE_PROJECT_EXT_NAME = ".xcodeproj"; @@ -300,9 +304,62 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ let xcodeBuildVersion = this.getXcodeVersion(); if (helpers.versionCompare(xcodeBuildVersion, "8.0") >= 0) { - let teamId = this.getDevelopmentTeam(); - if (teamId) { - args = args.concat("DEVELOPMENT_TEAM=" + teamId); + // TRICKY: I am not sure why we totally disregard the buildConfig parameter here. + buildConfig = buildConfig || {}; + + if (this.$options.teamId) { + buildConfig.teamIdentifier = this.$options.teamId; + } else { + buildConfig = this.readXCConfigSigning(); + if (!buildConfig.codeSignIdentity && !buildConfig.mobileProvisionIdentifier && !buildConfig.teamIdentifier) { + buildConfig = this.readBuildConfigFromPlatforms(); + } + } + + let signingStyle: XcodeSigningStyle; + if (buildConfig.codeSignIdentity || buildConfig.mobileProvisionIdentifier) { + signingStyle = "Manual"; + } else if (buildConfig.teamIdentifier) { + signingStyle = "Automatic"; + } else { + let signingStyles = [ + "Manual - Select existing provisioning profile for use", + "Automatic - Select Team ID for signing and let Xcode select managed provisioning profile" + ]; + let signingStyleIndex = signingStyles.indexOf(this.$prompter.promptForChoice("Select codesiging style", signingStyles).wait()); + signingStyle = new Array("Manual", "Automatic")[signingStyleIndex]; + + switch(signingStyle) { + case "Manual": + let profile = this.getProvisioningProfile(); + if (!profile) { + this.$logger.error("No matching provisioning profile found."); + } + this.persistProvisioningProfiles(profile.UUID); + this.$logger.info("Apply provisioning profile: " + profile.Name + " (" + profile.TeamName + ") " + profile.Type + " UUID: " + profile.UUID); + buildConfig.mobileProvisionIdentifier = profile.UUID; + buildConfig.teamIdentifier = profile.TeamIdentifier[0]; + break; + case "Automatic": + buildConfig.teamIdentifier = this.getDevelopmentTeam(); + this.persistDevelopmentTeam(buildConfig.teamIdentifier); + break; + } + } + + switch(signingStyle) { + case "Manual": { + const pbxprojPath = path.join(projectRoot, this.$projectData.projectName + ".xcodeproj", "project.pbxproj"); + const xcode = Xcode.open(pbxprojPath); + xcode.setManualSigningStyle(this.$projectData.projectName); + xcode.save(); + } break; + case "Automatic": { + const pbxprojPath = path.join(projectRoot, this.$projectData.projectName + ".xcodeproj", "project.pbxproj"); + const xcode = Xcode.open(pbxprojPath); + xcode.setAutomaticSigningStyle(this.$projectData.projectName, buildConfig.teamIdentifier); + xcode.save(); + } break; } } @@ -314,6 +371,10 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ args.push(`PROVISIONING_PROFILE=${buildConfig.mobileProvisionIdentifier}`); } + if (buildConfig && buildConfig.teamIdentifier) { + args.push(`DEVELOPMENT_TEAM=${buildConfig.teamIdentifier}`); + } + this.$childProcess.spawnFromEvent("xcodebuild", args, "exit", { cwd: this.$options, stdio: 'inherit' }).wait(); this.createIpa(projectRoot).wait(); @@ -1045,73 +1106,148 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return null; } - private readTeamId(): string { + private readXCConfigSigning(): IiOSBuildConfig { + const result: IiOSBuildConfig = {}; let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); if (this.$fs.exists(xcconfigFile).wait()) { let text = this.$fs.readText(xcconfigFile).wait(); - let teamId: string; text.split(/\r?\n/).forEach((line) => { line = line.replace(/\/(\/)[^\n]*$/, ""); - if (line.indexOf("DEVELOPMENT_TEAM") >= 0) { - teamId = line.split("=")[1].trim(); - if (teamId[teamId.length - 1] === ';') { - teamId = teamId.slice(0, -1); + const read = (name: string) => { + if (line.indexOf(name) >= 0) { + let value = line.substr(line.lastIndexOf("=") + 1).trim(); + if (value.charAt(value.length - 1) === ';') { + value = value.substr(0, value.length - 1).trim(); + } + return value; } - } + return undefined; + }; + result.teamIdentifier = read("DEVELOPMENT_TEAM") || result.teamIdentifier; + result.codeSignIdentity = read("CODE_SIGN_IDENTITY") || result.codeSignIdentity; + result.mobileProvisionIdentifier = read("PROVISIONING_PROFILE[sdk=iphoneos*]") || result.mobileProvisionIdentifier; }); - if (teamId) { - return teamId; - } } - let fileName = path.join(this.platformData.projectRoot, "teamid"); - if (this.$fs.exists(fileName).wait()) { - return this.$fs.readText(fileName).wait(); + return result; + } + + private getProvisioningProfile(): provision.MobileProvision { + let profile: provision.MobileProvision; + + const allCertificates = cert.read(); + const allProfiles = provision.read(); + const query: provision.Query = { + Certificates: allCertificates.valid, + AppId: this.$projectData.projectId, + Type: "Development" + }; + + if (this.$options.device) { + query.ProvisionedDevices = [this.$options.device]; + } else { + this.$devicesService.initialize().wait(); + let deviceUDIDs = _(this.$devicesService.getDeviceInstances()) + .filter(d => this.$mobileHelper.isiOSPlatform(d.deviceInfo.platform)) + .map(d => d.deviceInfo.identifier) + .toJSON(); + query.ProvisionedDevices = deviceUDIDs; + } + + const result = provision.select(allProfiles, query); + const choiceMap = result.eligable.reduce((acc, p) => { + acc[`'${p.Name}' (${p.TeamName}) ${p.Type}`] = p; + return acc; + }, <{ [display: string]: provision.MobileProvision }>{}); + + const choices = Object.keys(choiceMap); + if (choices.length > 0) { + const choice = this.$prompter.promptForChoice( + `Select provisioning profiles (found ${result.eligable.length} eligable, and ${result.nonEligable.length} non-eligable)`, + choices + ).wait(); + profile = choiceMap[choice]; } - return null; + + return profile; } private getDevelopmentTeam(): string { let teamId: string; - if (this.$options.teamId) { - teamId = this.$options.teamId; - } else { - teamId = this.readTeamId(); + let teams = this.getDevelopmentTeams(); + this.$logger.warn("Xcode 8 requires a team id to be specified when building for device."); + this.$logger.warn("You can specify the team id by setting the DEVELOPMENT_TEAM setting in build.xcconfig file located in App_Resources folder of your app, or by using the --teamId option when calling run, debug or livesync commnads."); + if (teams.length === 1) { + teamId = teams[0].id; + this.$logger.warn("Found and using the following development team installed on your system: " + teams[0].name + " (" + teams[0].id + ")"); + } else if (teams.length > 0) { + let choices: string[] = []; + for (let team of teams) { + choices.push(team.name + " (" + team.id + ")"); + } + let choice = this.$prompter.promptForChoice('Found multiple development teams, select one:', choices).wait(); + teamId = teams[choices.indexOf(choice)].id; } - if (!teamId) { - let teams = this.getDevelopmentTeams(); - this.$logger.warn("Xcode 8 requires a team id to be specified when building for device."); - this.$logger.warn("You can specify the team id by setting the DEVELOPMENT_TEAM setting in build.xcconfig file located in App_Resources folder of your app, or by using the --teamId option when calling run, debug or livesync commnads."); - if (teams.length === 1) { - teamId = teams[0].id; - this.$logger.warn("Found and using the following development team installed on your system: " + teams[0].name + " (" + teams[0].id + ")"); - } else if (teams.length > 0) { - let choices: string[] = []; - for (let team of teams) { - choices.push(team.name + " (" + team.id + ")"); + return teamId; + } + + private persistProvisioningProfiles(uuid: string) { + let choicesPersist = [ + "Yes, set the PROVISIONING_PROFILE[sdk=iphoneos*] setting in build.xcconfig file.", + "Yes, persist the mobileprovision uuid in platforms folder.", + "No, don't persist this setting." + ]; + let choicePersist = this.$prompter.promptForChoice("Do you want to make mobileprovision: " + uuid + " a persistent choice for your app?", choicesPersist).wait(); + switch (choicesPersist.indexOf(choicePersist)) { + case 0: + let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); + this.$fs.appendFile(xcconfigFile, "\nPROVISIONING_PROFILE[sdk=iphoneos*] = " + uuid + "\n").wait(); + break; + case 1: + this.$fs.writeFile(path.join(this.platformData.projectRoot, "mobileprovision"), uuid).wait(); + const teamidPath = path.join(this.platformData.projectRoot, "teamid"); + if (this.$fs.exists(teamidPath).wait()) { + this.$fs.deleteFile(teamidPath).wait(); } - let choice = this.$prompter.promptForChoice('Found multiple development teams, select one:', choices).wait(); - teamId = teams[choices.indexOf(choice)].id; - - let choicesPersist = [ - "Yes, set the DEVELOPMENT_TEAM setting in build.xcconfig file.", - "Yes, persist the team id in platforms folder.", - "No, don't persist this setting." - ]; - let choicePersist = this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist).wait(); - switch (choicesPersist.indexOf(choicePersist)) { - case 0: - let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); - this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n").wait(); - break; - case 1: - this.$fs.writeFile(path.join(this.platformData.projectRoot, "teamid"), teamId); - break; - default: - break; + break; + default: + break; + } + } + + private persistDevelopmentTeam(teamId: string) { + let choicesPersist = [ + "Yes, set the DEVELOPMENT_TEAM setting in build.xcconfig file.", + "Yes, persist the team id in platforms folder.", + "No, don't persist this setting." + ]; + let choicePersist = this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist).wait(); + switch (choicesPersist.indexOf(choicePersist)) { + case 0: + let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); + this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n").wait(); + break; + case 1: + this.$fs.writeFile(path.join(this.platformData.projectRoot, "teamid"), teamId).wait(); + const mobileprovisionPath = path.join(this.platformData.projectRoot, "mobileprovision"); + if (this.$fs.exists(mobileprovisionPath).wait()) { + this.$fs.deleteFile(mobileprovisionPath).wait(); } - } + break; + default: + break; } - return teamId; + } + + private readBuildConfigFromPlatforms(): IiOSBuildConfig { + let mobileprovisionPath = path.join(this.platformData.projectRoot, "mobileprovision"); + if (this.$fs.exists(mobileprovisionPath).wait()) { + return { mobileProvisionIdentifier: this.$fs.readText(mobileprovisionPath).wait() }; + } + let teamidPath = path.join(this.platformData.projectRoot, "teamid"); + if (this.$fs.exists(teamidPath).wait()) { + return { teamIdentifier: this.$fs.readText(teamidPath).wait() }; + } + return {}; } } diff --git a/package.json b/package.json index 33b058d2af..ef667d6fcc 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "glob": "^7.0.3", "iconv-lite": "0.4.11", "inquirer": "0.9.0", + "ios-mobileprovision-finder": "1.0.4", "ios-sim-portable": "~1.6.0", "lockfile": "1.0.1", "lodash": "4.13.1", @@ -57,6 +58,7 @@ "node-inspector": "https://github.com/NativeScript/node-inspector/tarball/v0.7.4.2", "open": "0.0.5", "osenv": "0.1.3", + "pbxproj-dom": "1.0.3", "plist": "1.1.0", "plist-merge-patch": "0.0.9", "plistlib": "0.2.1", From cb9eaed0cfb0d7b4d9679afb02732d66d0638f32 Mon Sep 17 00:00:00 2001 From: Panayot Cankov Date: Mon, 12 Dec 2016 16:22:58 +0200 Subject: [PATCH 2/2] Apply minor changes after PR review --- lib/services/ios-project-service.ts | 393 +++++++++++++++------------- package.json | 2 +- 2 files changed, 207 insertions(+), 188 deletions(-) diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index 1850c601e6..9b5d0e8b78 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -304,63 +304,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ let xcodeBuildVersion = this.getXcodeVersion(); if (helpers.versionCompare(xcodeBuildVersion, "8.0") >= 0) { - // TRICKY: I am not sure why we totally disregard the buildConfig parameter here. - buildConfig = buildConfig || {}; - - if (this.$options.teamId) { - buildConfig.teamIdentifier = this.$options.teamId; - } else { - buildConfig = this.readXCConfigSigning(); - if (!buildConfig.codeSignIdentity && !buildConfig.mobileProvisionIdentifier && !buildConfig.teamIdentifier) { - buildConfig = this.readBuildConfigFromPlatforms(); - } - } - - let signingStyle: XcodeSigningStyle; - if (buildConfig.codeSignIdentity || buildConfig.mobileProvisionIdentifier) { - signingStyle = "Manual"; - } else if (buildConfig.teamIdentifier) { - signingStyle = "Automatic"; - } else { - let signingStyles = [ - "Manual - Select existing provisioning profile for use", - "Automatic - Select Team ID for signing and let Xcode select managed provisioning profile" - ]; - let signingStyleIndex = signingStyles.indexOf(this.$prompter.promptForChoice("Select codesiging style", signingStyles).wait()); - signingStyle = new Array("Manual", "Automatic")[signingStyleIndex]; - - switch(signingStyle) { - case "Manual": - let profile = this.getProvisioningProfile(); - if (!profile) { - this.$logger.error("No matching provisioning profile found."); - } - this.persistProvisioningProfiles(profile.UUID); - this.$logger.info("Apply provisioning profile: " + profile.Name + " (" + profile.TeamName + ") " + profile.Type + " UUID: " + profile.UUID); - buildConfig.mobileProvisionIdentifier = profile.UUID; - buildConfig.teamIdentifier = profile.TeamIdentifier[0]; - break; - case "Automatic": - buildConfig.teamIdentifier = this.getDevelopmentTeam(); - this.persistDevelopmentTeam(buildConfig.teamIdentifier); - break; - } - } - - switch(signingStyle) { - case "Manual": { - const pbxprojPath = path.join(projectRoot, this.$projectData.projectName + ".xcodeproj", "project.pbxproj"); - const xcode = Xcode.open(pbxprojPath); - xcode.setManualSigningStyle(this.$projectData.projectName); - xcode.save(); - } break; - case "Automatic": { - const pbxprojPath = path.join(projectRoot, this.$projectData.projectName + ".xcodeproj", "project.pbxproj"); - const xcode = Xcode.open(pbxprojPath); - xcode.setAutomaticSigningStyle(this.$projectData.projectName, buildConfig.teamIdentifier); - xcode.save(); - } break; - } + buildConfig = this.getBuildConfig(projectRoot, buildConfig).wait(); } if (buildConfig && buildConfig.codeSignIdentity) { @@ -1071,6 +1015,69 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return xcodeBuildVersion; } + private getBuildConfig(projectRoot: string, buildConfig: IiOSBuildConfig): IFuture { + return (() => { + // TRICKY: I am not sure why we totally disregard the buildConfig parameter here. + buildConfig = buildConfig || {}; + + if (this.$options.teamId) { + buildConfig.teamIdentifier = this.$options.teamId; + } else { + buildConfig = this.readXCConfigSigning().wait(); + if (!buildConfig.codeSignIdentity && !buildConfig.mobileProvisionIdentifier && !buildConfig.teamIdentifier) { + buildConfig = this.readBuildConfigFromPlatforms().wait(); + } + } + + let signingStyle: XcodeSigningStyle; + if (buildConfig.codeSignIdentity || buildConfig.mobileProvisionIdentifier) { + signingStyle = "Manual"; + } else if (buildConfig.teamIdentifier) { + signingStyle = "Automatic"; + } else if (helpers.isInteractive()) { + let signingStyles = [ + "Manual - Select existing provisioning profile for use", + "Automatic - Select Team ID for signing and let Xcode select managed provisioning profile" + ]; + let signingStyleIndex = signingStyles.indexOf(this.$prompter.promptForChoice("Select codesiging style", signingStyles).wait()); + signingStyle = new Array("Manual", "Automatic")[signingStyleIndex]; + + switch(signingStyle) { + case "Manual": + let profile = this.getProvisioningProfile().wait(); + if (!profile) { + this.$errors.failWithoutHelp("No matching provisioning profile found."); + } + this.persistProvisioningProfiles(profile.UUID).wait(); + this.$logger.info("Apply provisioning profile: " + profile.Name + " (" + profile.TeamName + ") " + profile.Type + " UUID: " + profile.UUID); + buildConfig.mobileProvisionIdentifier = profile.UUID; + buildConfig.teamIdentifier = profile.TeamIdentifier[0]; + break; + case "Automatic": + buildConfig.teamIdentifier = this.getDevelopmentTeam().wait(); + this.persistDevelopmentTeam(buildConfig.teamIdentifier).wait(); + break; + } + } + + if (signingStyle) { + const pbxprojPath = path.join(projectRoot, this.$projectData.projectName + ".xcodeproj", "project.pbxproj"); + const xcode = Xcode.open(pbxprojPath); + switch(signingStyle) { + case "Manual": + xcode.setManualSigningStyle(this.$projectData.projectName); + break; + case "Automatic": + xcode.setAutomaticSigningStyle(this.$projectData.projectName, buildConfig.teamIdentifier); + break; + } + xcode.save(); + } + + return buildConfig; + }).future()(); + } + private getDevelopmentTeams(): Array<{ id: string, name: string }> { let dir = path.join(process.env.HOME, "Library/MobileDevice/Provisioning Profiles/"); let files = this.$fs.readDirectory(dir).wait(); @@ -1106,148 +1113,160 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return null; } - private readXCConfigSigning(): IiOSBuildConfig { - const result: IiOSBuildConfig = {}; - let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); - if (this.$fs.exists(xcconfigFile).wait()) { - let text = this.$fs.readText(xcconfigFile).wait(); - text.split(/\r?\n/).forEach((line) => { - line = line.replace(/\/(\/)[^\n]*$/, ""); - const read = (name: string) => { - if (line.indexOf(name) >= 0) { - let value = line.substr(line.lastIndexOf("=") + 1).trim(); - if (value.charAt(value.length - 1) === ';') { - value = value.substr(0, value.length - 1).trim(); + private readXCConfigSigning(): IFuture { + return (() => { + const result: IiOSBuildConfig = {}; + let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); + if (this.$fs.exists(xcconfigFile).wait()) { + let text = this.$fs.readText(xcconfigFile).wait(); + text.split(/\r?\n/).forEach((line) => { + line = line.replace(/\/(\/)[^\n]*$/, ""); + const read = (name: string) => { + if (line.indexOf(name) >= 0) { + let value = line.substr(line.lastIndexOf("=") + 1).trim(); + if (value.charAt(value.length - 1) === ';') { + value = value.substr(0, value.length - 1).trim(); + } + return value; } - return value; - } - return undefined; - }; - result.teamIdentifier = read("DEVELOPMENT_TEAM") || result.teamIdentifier; - result.codeSignIdentity = read("CODE_SIGN_IDENTITY") || result.codeSignIdentity; - result.mobileProvisionIdentifier = read("PROVISIONING_PROFILE[sdk=iphoneos*]") || result.mobileProvisionIdentifier; - }); - } - return result; + return undefined; + }; + result.teamIdentifier = read("DEVELOPMENT_TEAM") || result.teamIdentifier; + result.codeSignIdentity = read("CODE_SIGN_IDENTITY") || result.codeSignIdentity; + result.mobileProvisionIdentifier = read("PROVISIONING_PROFILE[sdk=iphoneos*]") || result.mobileProvisionIdentifier; + }); + } + return result; + }).future()(); } - private getProvisioningProfile(): provision.MobileProvision { - let profile: provision.MobileProvision; + private getProvisioningProfile(): IFuture { + return (() => { + let profile: provision.MobileProvision; + + const allCertificates = cert.read(); + const allProfiles = provision.read(); + const query: provision.Query = { + Certificates: allCertificates.valid, + AppId: this.$projectData.projectId, + Type: "Development" + }; - const allCertificates = cert.read(); - const allProfiles = provision.read(); - const query: provision.Query = { - Certificates: allCertificates.valid, - AppId: this.$projectData.projectId, - Type: "Development" - }; + if (this.$options.device) { + query.ProvisionedDevices = [this.$options.device]; + } else { + this.$devicesService.initialize().wait(); + let deviceUDIDs = _(this.$devicesService.getDeviceInstances()) + .filter(d => this.$mobileHelper.isiOSPlatform(d.deviceInfo.platform)) + .map(d => d.deviceInfo.identifier) + .toJSON(); + query.ProvisionedDevices = deviceUDIDs; + } - if (this.$options.device) { - query.ProvisionedDevices = [this.$options.device]; - } else { - this.$devicesService.initialize().wait(); - let deviceUDIDs = _(this.$devicesService.getDeviceInstances()) - .filter(d => this.$mobileHelper.isiOSPlatform(d.deviceInfo.platform)) - .map(d => d.deviceInfo.identifier) - .toJSON(); - query.ProvisionedDevices = deviceUDIDs; - } + const result = provision.select(allProfiles, query); + const choiceMap = result.eligable.reduce((acc, p) => { + acc[`'${p.Name}' (${p.TeamName}) ${p.Type}`] = p; + return acc; + }, <{ [display: string]: provision.MobileProvision }>{}); + + const choices = Object.keys(choiceMap); + if (choices.length > 0) { + const choice = this.$prompter.promptForChoice( + `Select provisioning profiles (found ${result.eligable.length} eligable, and ${result.nonEligable.length} non-eligable)`, + choices + ).wait(); + profile = choiceMap[choice]; + } - const result = provision.select(allProfiles, query); - const choiceMap = result.eligable.reduce((acc, p) => { - acc[`'${p.Name}' (${p.TeamName}) ${p.Type}`] = p; - return acc; - }, <{ [display: string]: provision.MobileProvision }>{}); - - const choices = Object.keys(choiceMap); - if (choices.length > 0) { - const choice = this.$prompter.promptForChoice( - `Select provisioning profiles (found ${result.eligable.length} eligable, and ${result.nonEligable.length} non-eligable)`, - choices - ).wait(); - profile = choiceMap[choice]; - } + return profile; + }).future()(); + } - return profile; - } - - private getDevelopmentTeam(): string { - let teamId: string; - let teams = this.getDevelopmentTeams(); - this.$logger.warn("Xcode 8 requires a team id to be specified when building for device."); - this.$logger.warn("You can specify the team id by setting the DEVELOPMENT_TEAM setting in build.xcconfig file located in App_Resources folder of your app, or by using the --teamId option when calling run, debug or livesync commnads."); - if (teams.length === 1) { - teamId = teams[0].id; - this.$logger.warn("Found and using the following development team installed on your system: " + teams[0].name + " (" + teams[0].id + ")"); - } else if (teams.length > 0) { - let choices: string[] = []; - for (let team of teams) { - choices.push(team.name + " (" + team.id + ")"); - } - let choice = this.$prompter.promptForChoice('Found multiple development teams, select one:', choices).wait(); - teamId = teams[choices.indexOf(choice)].id; - } - return teamId; - } - - private persistProvisioningProfiles(uuid: string) { - let choicesPersist = [ - "Yes, set the PROVISIONING_PROFILE[sdk=iphoneos*] setting in build.xcconfig file.", - "Yes, persist the mobileprovision uuid in platforms folder.", - "No, don't persist this setting." - ]; - let choicePersist = this.$prompter.promptForChoice("Do you want to make mobileprovision: " + uuid + " a persistent choice for your app?", choicesPersist).wait(); - switch (choicesPersist.indexOf(choicePersist)) { - case 0: - let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); - this.$fs.appendFile(xcconfigFile, "\nPROVISIONING_PROFILE[sdk=iphoneos*] = " + uuid + "\n").wait(); - break; - case 1: - this.$fs.writeFile(path.join(this.platformData.projectRoot, "mobileprovision"), uuid).wait(); - const teamidPath = path.join(this.platformData.projectRoot, "teamid"); - if (this.$fs.exists(teamidPath).wait()) { - this.$fs.deleteFile(teamidPath).wait(); + private getDevelopmentTeam(): IFuture { + return (() => { + let teamId: string; + let teams = this.getDevelopmentTeams(); + this.$logger.warn("Xcode 8 requires a team id to be specified when building for device."); + this.$logger.warn("You can specify the team id by setting the DEVELOPMENT_TEAM setting in build.xcconfig file located in App_Resources folder of your app, or by using the --teamId option when calling run, debug or livesync commnads."); + if (teams.length === 1) { + teamId = teams[0].id; + this.$logger.warn("Found and using the following development team installed on your system: " + teams[0].name + " (" + teams[0].id + ")"); + } else if (teams.length > 0) { + let choices: string[] = []; + for (let team of teams) { + choices.push(team.name + " (" + team.id + ")"); } - break; - default: - break; - } + let choice = this.$prompter.promptForChoice('Found multiple development teams, select one:', choices).wait(); + teamId = teams[choices.indexOf(choice)].id; + } + return teamId; + }).future()(); } - private persistDevelopmentTeam(teamId: string) { - let choicesPersist = [ - "Yes, set the DEVELOPMENT_TEAM setting in build.xcconfig file.", - "Yes, persist the team id in platforms folder.", - "No, don't persist this setting." - ]; - let choicePersist = this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist).wait(); - switch (choicesPersist.indexOf(choicePersist)) { - case 0: - let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); - this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n").wait(); - break; - case 1: - this.$fs.writeFile(path.join(this.platformData.projectRoot, "teamid"), teamId).wait(); - const mobileprovisionPath = path.join(this.platformData.projectRoot, "mobileprovision"); - if (this.$fs.exists(mobileprovisionPath).wait()) { - this.$fs.deleteFile(mobileprovisionPath).wait(); - } - break; - default: - break; - } + private persistProvisioningProfiles(uuid: string): IFuture { + return (() => { + let choicesPersist = [ + "Yes, set the PROVISIONING_PROFILE[sdk=iphoneos*] setting in build.xcconfig file.", + "Yes, persist the mobileprovision uuid in platforms folder.", + "No, don't persist this setting." + ]; + let choicePersist = this.$prompter.promptForChoice("Do you want to make mobileprovision: " + uuid + " a persistent choice for your app?", choicesPersist).wait(); + switch (choicesPersist.indexOf(choicePersist)) { + case 0: + let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); + this.$fs.appendFile(xcconfigFile, "\nPROVISIONING_PROFILE[sdk=iphoneos*] = " + uuid + "\n").wait(); + break; + case 1: + this.$fs.writeFile(path.join(this.platformData.projectRoot, "mobileprovision"), uuid).wait(); + const teamidPath = path.join(this.platformData.projectRoot, "teamid"); + if (this.$fs.exists(teamidPath).wait()) { + this.$fs.deleteFile(teamidPath).wait(); + } + break; + default: + break; + } + }).future()(); } - private readBuildConfigFromPlatforms(): IiOSBuildConfig { - let mobileprovisionPath = path.join(this.platformData.projectRoot, "mobileprovision"); - if (this.$fs.exists(mobileprovisionPath).wait()) { - return { mobileProvisionIdentifier: this.$fs.readText(mobileprovisionPath).wait() }; - } - let teamidPath = path.join(this.platformData.projectRoot, "teamid"); - if (this.$fs.exists(teamidPath).wait()) { - return { teamIdentifier: this.$fs.readText(teamidPath).wait() }; - } - return {}; + private persistDevelopmentTeam(teamId: string): IFuture { + return (() => { + let choicesPersist = [ + "Yes, set the DEVELOPMENT_TEAM setting in build.xcconfig file.", + "Yes, persist the team id in platforms folder.", + "No, don't persist this setting." + ]; + let choicePersist = this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist).wait(); + switch (choicesPersist.indexOf(choicePersist)) { + case 0: + let xcconfigFile = path.join(this.$projectData.appResourcesDirectoryPath, this.platformData.normalizedPlatformName, "build.xcconfig"); + this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n").wait(); + break; + case 1: + this.$fs.writeFile(path.join(this.platformData.projectRoot, "teamid"), teamId).wait(); + const mobileprovisionPath = path.join(this.platformData.projectRoot, "mobileprovision"); + if (this.$fs.exists(mobileprovisionPath).wait()) { + this.$fs.deleteFile(mobileprovisionPath).wait(); + } + break; + default: + break; + } + }).future()(); + } + + private readBuildConfigFromPlatforms(): IFuture { + return (() => { + let mobileprovisionPath = path.join(this.platformData.projectRoot, "mobileprovision"); + if (this.$fs.exists(mobileprovisionPath).wait()) { + return { mobileProvisionIdentifier: this.$fs.readText(mobileprovisionPath).wait() }; + } + let teamidPath = path.join(this.platformData.projectRoot, "teamid"); + if (this.$fs.exists(teamidPath).wait()) { + return { teamIdentifier: this.$fs.readText(teamidPath).wait() }; + } + return {}; + }).future()(); } } diff --git a/package.json b/package.json index ef667d6fcc..a72751b950 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "glob": "^7.0.3", "iconv-lite": "0.4.11", "inquirer": "0.9.0", - "ios-mobileprovision-finder": "1.0.4", + "ios-mobileprovision-finder": "1.0.8", "ios-sim-portable": "~1.6.0", "lockfile": "1.0.1", "lodash": "4.13.1",