From b0f19738277b001f7a53e76e17f2094401e09930 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Wed, 1 Jul 2015 00:03:03 +0100 Subject: [PATCH 1/5] starting to add the parsing of device type from a scheme to infer the right device type --- BuildaUtils/XcodeDeviceParser.swift | 36 ++++++++++++++++++++++++++++ Buildasaur.xcodeproj/project.pbxproj | 4 ++++ 2 files changed, 40 insertions(+) create mode 100644 BuildaUtils/XcodeDeviceParser.swift diff --git a/BuildaUtils/XcodeDeviceParser.swift b/BuildaUtils/XcodeDeviceParser.swift new file mode 100644 index 0000000..64bea13 --- /dev/null +++ b/BuildaUtils/XcodeDeviceParser.swift @@ -0,0 +1,36 @@ +// +// XcodeDeviceParser.swift +// Buildasaur +// +// Created by Honza Dvorsky on 30/06/2015. +// Copyright © 2015 Honza Dvorsky. All rights reserved. +// + +import Foundation + +public class XcodeDeviceParser { + + public enum DeviceType: String { + case iPhoneOS = "iphoneos" + case macOSX = "macosx" + case watchOS = "???" //TODO:find out what the code is for watch apps + } + + class func parseDeviceTypeFromProjectUrlAndScheme(projectUrl: NSURL, scheme: String) throws -> DeviceType { + let url = NSURL(string: "/Users/honzadvorsky/Documents/Buildasaur/")! + let scheme = "Buildasaur" + try! self.parseTargetTypeFromSchemeAndProjectAtUrl(scheme, projectFolderUrl: url) + } + + public class func parseTargetTypeFromSchemeAndProjectAtUrl(schemeName: String, projectFolderUrl: NSURL) throws -> String { + + let script = "cd \"\(projectFolderUrl)\"; xcodebuild -scheme \(schemeName) -showBuildSettings 2>/dev/null | egrep '^\\s*PLATFORM_NAME' | cut -d = -f 2 | uniq | xargs echo" + let res = Script.runTemporaryScript(script) + if res.terminationStatus == 0 { + let deviceType = res.standardOutput.stripTrailingNewline() + print("\(deviceType)") + } + return "" + } + +} \ No newline at end of file diff --git a/Buildasaur.xcodeproj/project.pbxproj b/Buildasaur.xcodeproj/project.pbxproj index 0a1586c..db5b42b 100644 --- a/Buildasaur.xcodeproj/project.pbxproj +++ b/Buildasaur.xcodeproj/project.pbxproj @@ -81,6 +81,7 @@ 3AB4898E1B0929C9005C87BE /* MockHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB4898D1B0929C9005C87BE /* MockHelpers.swift */; }; 3AB489901B0929F8005C87BE /* sampleFinishedIntegration.json in Resources */ = {isa = PBXBuildFile; fileRef = 3AB4898F1B0929F8005C87BE /* sampleFinishedIntegration.json */; }; 3AD338B01AAE31D500ECD0F2 /* BuildTemplateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD338AF1AAE31D500ECD0F2 /* BuildTemplateViewController.swift */; }; + 3AD4D9E21B4356BE0054B315 /* XcodeDeviceParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4D9E11B4356BE0054B315 /* XcodeDeviceParser.swift */; }; 3AF090B81B1134AA0058567F /* BranchWatchingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF090B71B1134AA0058567F /* BranchWatchingViewController.swift */; }; 3AF1B1221AAC621800917EF3 /* UIUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF1B1211AAC621800917EF3 /* UIUtils.swift */; }; 3AF1B1241AAC7CA500917EF3 /* StatusSyncerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF1B1231AAC7CA500917EF3 /* StatusSyncerViewController.swift */; }; @@ -248,6 +249,7 @@ 3AB4898D1B0929C9005C87BE /* MockHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockHelpers.swift; sourceTree = ""; }; 3AB4898F1B0929F8005C87BE /* sampleFinishedIntegration.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = sampleFinishedIntegration.json; sourceTree = ""; }; 3AD338AF1AAE31D500ECD0F2 /* BuildTemplateViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuildTemplateViewController.swift; sourceTree = ""; }; + 3AD4D9E11B4356BE0054B315 /* XcodeDeviceParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeDeviceParser.swift; sourceTree = ""; }; 3AF090B71B1134AA0058567F /* BranchWatchingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BranchWatchingViewController.swift; sourceTree = ""; }; 3AF1B1211AAC621800917EF3 /* UIUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIUtils.swift; sourceTree = ""; }; 3AF1B1231AAC7CA500917EF3 /* StatusSyncerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusSyncerViewController.swift; sourceTree = ""; }; @@ -556,6 +558,7 @@ 3AB3FDC81B05616A00021197 /* TimeUtils.swift */, 3AF1B1211AAC621800917EF3 /* UIUtils.swift */, 3A4770A31A745FFA0016E170 /* XcodeProjectParser.swift */, + 3AD4D9E11B4356BE0054B315 /* XcodeDeviceParser.swift */, 3AAF6E761A3CE4CC00C657FB /* Supporting Files */, ); path = BuildaUtils; @@ -1200,6 +1203,7 @@ files = ( 3A3BDC1D1AF6C51900D2CD99 /* Extensions.swift in Sources */, 3A808A1D1ADB063F0073145D /* Persistence.swift in Sources */, + 3AD4D9E21B4356BE0054B315 /* XcodeDeviceParser.swift in Sources */, 3AB3FDC91B05616A00021197 /* TimeUtils.swift in Sources */, 3AF1B1221AAC621800917EF3 /* UIUtils.swift in Sources */, 3A4770A41A745FFA0016E170 /* XcodeProjectParser.swift in Sources */, From 5dce690cb8f82c0e9305a69f619e9be9fe8d0cd7 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Thu, 2 Jul 2015 01:11:15 +0100 Subject: [PATCH 2/5] xcode 7 workspace parsing fixes, integrating the detection of scheme target type ios/osx/watchos --- BuildaUtils/XcodeDeviceParser.swift | 24 ++++++++++++-------- BuildaUtils/XcodeProjectParser.swift | 3 ++- Buildasaur/BuildTemplateViewController.swift | 17 ++++++++++---- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/BuildaUtils/XcodeDeviceParser.swift b/BuildaUtils/XcodeDeviceParser.swift index 64bea13..a0bc185 100644 --- a/BuildaUtils/XcodeDeviceParser.swift +++ b/BuildaUtils/XcodeDeviceParser.swift @@ -7,30 +7,34 @@ // import Foundation +import XcodeServerSDK public class XcodeDeviceParser { public enum DeviceType: String { case iPhoneOS = "iphoneos" case macOSX = "macosx" - case watchOS = "???" //TODO:find out what the code is for watch apps + case watchOS = "watchos" } - class func parseDeviceTypeFromProjectUrlAndScheme(projectUrl: NSURL, scheme: String) throws -> DeviceType { - let url = NSURL(string: "/Users/honzadvorsky/Documents/Buildasaur/")! - let scheme = "Buildasaur" - try! self.parseTargetTypeFromSchemeAndProjectAtUrl(scheme, projectFolderUrl: url) + public class func parseDeviceTypeFromProjectUrlAndScheme(projectUrl: NSURL, scheme: String) throws -> DeviceType { + + let typeString = try self.parseTargetTypeFromSchemeAndProjectAtUrl(scheme, projectFolderUrl: projectUrl) + guard let deviceType = DeviceType(rawValue: typeString) else { + throw Error.withInfo("Unrecognized type: \(typeString)") + } + return deviceType } - public class func parseTargetTypeFromSchemeAndProjectAtUrl(schemeName: String, projectFolderUrl: NSURL) throws -> String { + private class func parseTargetTypeFromSchemeAndProjectAtUrl(schemeName: String, projectFolderUrl: NSURL) throws -> String { - let script = "cd \"\(projectFolderUrl)\"; xcodebuild -scheme \(schemeName) -showBuildSettings 2>/dev/null | egrep '^\\s*PLATFORM_NAME' | cut -d = -f 2 | uniq | xargs echo" + let folder = projectFolderUrl.URLByDeletingLastPathComponent?.path ?? "~" + let script = "cd \"\(folder)\"; xcodebuild -scheme \"\(schemeName)\" -showBuildSettings 2>/dev/null | egrep '^\\s*PLATFORM_NAME' | cut -d = -f 2 | uniq | xargs echo" let res = Script.runTemporaryScript(script) if res.terminationStatus == 0 { let deviceType = res.standardOutput.stripTrailingNewline() - print("\(deviceType)") + return deviceType } - return "" + throw Error.withInfo("Termination status: \(res.terminationStatus), output: \(res.standardOutput), error: \(res.standardError)") } - } \ No newline at end of file diff --git a/BuildaUtils/XcodeProjectParser.swift b/BuildaUtils/XcodeProjectParser.swift index 475c135..420ca3c 100644 --- a/BuildaUtils/XcodeProjectParser.swift +++ b/BuildaUtils/XcodeProjectParser.swift @@ -163,7 +163,8 @@ public class XcodeProjectParser { let projectRelativePaths = components.map { (line: String) -> String? in - let range1 = line.rangeOfString("group:") + //xcode 7 and 6 styles (container vs group) + let range1 = line.rangeOfString("container:") ?? line.rangeOfString("group:") let range2 = line.rangeOfString("\">", options: NSStringCompareOptions.BackwardsSearch) if let range1 = range1, let range2 = range2 { let start = range1.endIndex diff --git a/Buildasaur/BuildTemplateViewController.swift b/Buildasaur/BuildTemplateViewController.swift index cc38034..cba2875 100644 --- a/Buildasaur/BuildTemplateViewController.swift +++ b/Buildasaur/BuildTemplateViewController.swift @@ -113,9 +113,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.testDestinationComboBox.removeAllItems() self.testDestinationComboBox.addItemsWithObjectValues(self.allDestinations().map({ (item) -> String in /*hack*/ return "" })) //TODO: migrate here as well - let destination = BotConfiguration.TestingDestinationIdentifier.Mac //TODO: self.buildTemplate.deviceSpecification.filters.first!... - let destinationIndex = self.allDestinations().indexOfFirstObjectPassingTest({ $0 == destination })! - self.testDestinationComboBox.selectItemAtIndex(destinationIndex) +// let destination = BotConfiguration.TestingDestinationIdentifier.Mac //TODO: self.buildTemplate.deviceSpecification.filters.first!... +// let destinationIndex = self.allDestinations().indexOfFirstObjectPassingTest({ $0 == destination })! +// self.testDestinationComboBox.selectItemAtIndex(destinationIndex) self.testDestinationComboBox.delegate = self @@ -328,7 +328,16 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa if schemes.indexOf(selectedScheme) != nil { //found it, good, use it self.buildTemplate.scheme = selectedScheme - return true + + //also refresh devices for testing based on the scheme type + do { + let deviceType = try XcodeDeviceParser.parseDeviceTypeFromProjectUrlAndScheme(self.project.url, scheme: selectedScheme) + print("\(deviceType)") + //TODO: here update the devices and only filter this type + } catch { + print("\(error)") + return false + } } } From aa76daa20541e9ea342f4ff990f26e8db0dbdce5 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Thu, 2 Jul 2015 18:40:41 +0100 Subject: [PATCH 3/5] wip on fixing device choosing in build template --- BuildaUtils/XcodeDeviceParser.swift | 11 +++ Buildasaur/Base.lproj/Main.storyboard | 8 +-- Buildasaur/BuildTemplate.swift | 37 ++++++++-- Buildasaur/BuildTemplateViewController.swift | 73 +++++++++++--------- Buildasaur/SyncPairExtensions.swift | 2 +- Buildasaur/XcodeServerSyncerUtils.swift | 13 +++- 6 files changed, 98 insertions(+), 46 deletions(-) diff --git a/BuildaUtils/XcodeDeviceParser.swift b/BuildaUtils/XcodeDeviceParser.swift index a0bc185..28eddec 100644 --- a/BuildaUtils/XcodeDeviceParser.swift +++ b/BuildaUtils/XcodeDeviceParser.swift @@ -15,6 +15,17 @@ public class XcodeDeviceParser { case iPhoneOS = "iphoneos" case macOSX = "macosx" case watchOS = "watchos" + + public func toPlatformType() -> DevicePlatform.PlatformType { + switch self { + case .iPhoneOS: + return .iOS + case .macOSX: + return .OSX + case .watchOS: + return .watchOS + } + } } public class func parseDeviceTypeFromProjectUrlAndScheme(projectUrl: NSURL, scheme: String) throws -> DeviceType { diff --git a/Buildasaur/Base.lproj/Main.storyboard b/Buildasaur/Base.lproj/Main.storyboard index 7510308..3b3be9e 100644 --- a/Buildasaur/Base.lproj/Main.storyboard +++ b/Buildasaur/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -1373,7 +1373,7 @@ - + @@ -1530,7 +1530,7 @@ - + @@ -2157,7 +2157,7 @@ - + diff --git a/Buildasaur/BuildTemplate.swift b/Buildasaur/BuildTemplate.swift index 002efa4..1b3d803 100644 --- a/Buildasaur/BuildTemplate.swift +++ b/Buildasaur/BuildTemplate.swift @@ -17,7 +17,8 @@ private let kKeySchedule = "schedule" private let kKeyCleaningPolicy = "cleaning_policy" private let kKeyTriggers = "triggers" private let kKeyTestingDevices = "testing_devices" -private let kKeyDestinationType = "destination_type" +private let kKeyDeviceFilter = "device_filter" +private let kKeyPlatformType = "platform_type" private let kKeyShouldAnalyze = "should_analyze" private let kKeyShouldTest = "should_test" private let kKeyShouldArchive = "should_archive" @@ -33,8 +34,10 @@ class BuildTemplate: JSONSerializable { var shouldAnalyze: Bool? var shouldTest: Bool? var shouldArchive: Bool? - var deviceSpecification: DeviceSpecification - + var testingDeviceIds: [String] + var deviceFilter: DeviceFilter.FilterType + var platformType: DevicePlatform.PlatformType? + func validate() -> Bool { if self.uniqueId.isEmpty { return false } @@ -54,7 +57,9 @@ class BuildTemplate: JSONSerializable { self.shouldAnalyze = false self.shouldTest = false self.shouldArchive = false - self.deviceSpecification = DeviceSpecification(testingDeviceIDs: []) + self.testingDeviceIds = [] + self.deviceFilter = .AllAvailableDevicesAndSimulators + self.platformType = nil } required init?(json: NSDictionary) { @@ -84,8 +89,24 @@ class BuildTemplate: JSONSerializable { self.shouldTest = json.optionalBoolForKey(kKeyShouldTest) self.shouldArchive = json.optionalBoolForKey(kKeyShouldArchive) - let testingDevices = json.optionalArrayForKey(kKeyTestingDevices) as? [String] ?? [] - self.deviceSpecification = DeviceSpecification(testingDeviceIDs: testingDevices) + self.testingDeviceIds = json.optionalArrayForKey(kKeyTestingDevices) as? [String] ?? [] + + if + let deviceFilterInt = json.optionalIntForKey(kKeyDeviceFilter), + let deviceFilter = DeviceFilter.FilterType(rawValue: deviceFilterInt) + { + self.deviceFilter = deviceFilter + } else { + self.deviceFilter = .AllAvailableDevicesAndSimulators + } + + if + let platformTypeString = json.optionalStringForKey(kKeyPlatformType), + let platformType = DevicePlatform.PlatformType(rawValue: platformTypeString) { + self.platformType = platformType + } else { + self.platformType = nil + } if !self.validate() { return nil @@ -97,7 +118,8 @@ class BuildTemplate: JSONSerializable { dict[kKeyUniqueId] = self.uniqueId dict[kKeyTriggers] = self.triggers.map({ $0.dictionarify() }) - dict[kKeyTestingDevices] = self.deviceSpecification.deviceIdentifiers + dict[kKeyDeviceFilter] = self.deviceFilter.rawValue + dict[kKeyTestingDevices] = self.testingDeviceIds ?? [] dict[kKeyCleaningPolicy] = self.cleaningPolicy.rawValue dict.optionallyAddValueForKey(self.name, key: kKeyName) dict.optionallyAddValueForKey(self.scheme, key: kKeyScheme) @@ -105,6 +127,7 @@ class BuildTemplate: JSONSerializable { dict.optionallyAddValueForKey(self.shouldAnalyze, key: kKeyShouldAnalyze) dict.optionallyAddValueForKey(self.shouldTest, key: kKeyShouldTest) dict.optionallyAddValueForKey(self.shouldArchive, key: kKeyShouldArchive) + dict.optionallyAddValueForKey(self.platformType?.rawValue, key: kKeyPlatformType) return dict } diff --git a/Buildasaur/BuildTemplateViewController.swift b/Buildasaur/BuildTemplateViewController.swift index cba2875..c490e4c 100644 --- a/Buildasaur/BuildTemplateViewController.swift +++ b/Buildasaur/BuildTemplateViewController.swift @@ -29,7 +29,7 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa @IBOutlet weak var scheduleComboBox: NSComboBox! @IBOutlet weak var cleaninPolicyComboBox: NSComboBox! - @IBOutlet weak var testDestinationComboBox: NSComboBox! + @IBOutlet weak var testDeviceFilterComboBox: NSComboBox! @IBOutlet weak var testDevicesTableView: NSTableView! @IBOutlet weak var testDevicesActivityIndicator: NSProgressIndicator! @@ -54,16 +54,10 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa ] } - //TODO: migrate this to the new DeviceSpecification logic! - func allDestinations() -> [BotConfiguration.TestingDestinationIdentifier] { - return [ -// BotConfiguration.TestingDestinationIdentifier.iOS_SelectedDevicesAndSimulators, -// BotConfiguration.TestingDestinationIdentifier.iOS_AllDevices, -// BotConfiguration.TestingDestinationIdentifier.iOS_AllSimulators, -// BotConfiguration.TestingDestinationIdentifier.iOS_AllDevicesAndSimulators, -// BotConfiguration.TestingDestinationIdentifier.Mac, -// BotConfiguration.TestingDestinationIdentifier.AllCompatible - ] + func allFilters() -> [DeviceFilter.FilterType] { + let currentPlatformType = self.buildTemplate.platformType ?? .Unknown + let allFilters = DeviceFilter.FilterType.availableFiltersForPlatform(currentPlatformType) + return allFilters } override func viewDidLoad() { @@ -110,18 +104,26 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.cleaninPolicyComboBox.delegate = self - self.testDestinationComboBox.removeAllItems() - self.testDestinationComboBox.addItemsWithObjectValues(self.allDestinations().map({ (item) -> String in /*hack*/ return "" })) - //TODO: migrate here as well -// let destination = BotConfiguration.TestingDestinationIdentifier.Mac //TODO: self.buildTemplate.deviceSpecification.filters.first!... -// let destinationIndex = self.allDestinations().indexOfFirstObjectPassingTest({ $0 == destination })! -// self.testDestinationComboBox.selectItemAtIndex(destinationIndex) - - self.testDestinationComboBox.delegate = self + self.refreshDataInDeviceFilterComboBox() self.triggersTableView.reloadData() } + func refreshDataInDeviceFilterComboBox() { + + self.testDeviceFilterComboBox.removeAllItems() + + let allFilterNames = self.allFilters().map({ (item) -> String in return item.toString() }) + self.testDeviceFilterComboBox.addItemsWithObjectValues(allFilterNames) + + let filter = self.buildTemplate.deviceFilter ?? .AllAvailableDevicesAndSimulators + if let destinationIndex = self.allFilters().indexOfFirstObjectPassingTest({ $0 == filter }) { + self.testDeviceFilterComboBox.selectItemAtIndex(destinationIndex) + } + + self.testDeviceFilterComboBox.delegate = self + } + func fetchDevices(completion: () -> ()) { self.testDevicesActivityIndicator.startAnimation(nil) @@ -239,10 +241,12 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.triggersTableView.reloadData() //enable devices table view only if selected devices is chosen -// let selectable = self.buildTemplate.destinationType == BotConfiguration.TestingDestinationIdentifier.iOS_SelectedDevicesAndSimulators -// self.testDevicesTableView.enabled = selectable + let filter = self.buildTemplate.deviceFilter ?? .AllAvailableDevicesAndSimulators + let selectable = filter == .SelectedDevicesAndSimulators + self.testDevicesTableView.enabled = selectable - //disable/enable based on some checkboxes + //also change the device filter picker based on the platform + self.refreshDataInDeviceFilterComboBox() } func pullStagesFromUI() -> Bool { @@ -262,9 +266,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa let stages = self.pullStagesFromUI() let schedule = self.pullScheduleFromUI(interactive) let cleaning = self.pullCleaningPolicyFromUI(interactive) - let destination = self.pullDestinationFromUI(interactive) + let filter = self.pullFilterFromUI(interactive) - return scheme && name && stages && schedule && cleaning && destination + return scheme && name && stages && schedule && cleaning && filter } return false } @@ -331,9 +335,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa //also refresh devices for testing based on the scheme type do { - let deviceType = try XcodeDeviceParser.parseDeviceTypeFromProjectUrlAndScheme(self.project.url, scheme: selectedScheme) - print("\(deviceType)") - //TODO: here update the devices and only filter this type + let platformType = try XcodeDeviceParser.parseDeviceTypeFromProjectUrlAndScheme(self.project.url, scheme: selectedScheme).toPlatformType() + self.buildTemplate.platformType = platformType + self.reloadUI() } catch { print("\(error)") return false @@ -347,12 +351,12 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa return false } - func pullDestinationFromUI(interactive: Bool) -> Bool { + func pullFilterFromUI(interactive: Bool) -> Bool { - let index = self.testDestinationComboBox.indexOfSelectedItem + let index = self.testDeviceFilterComboBox.indexOfSelectedItem if index > -1 { -// let destination = self.allDestinations()[index] -// self.buildTemplate.destinationType = destination + let filter = self.allFilters()[index] + self.buildTemplate.deviceFilter = filter return true } if interactive { @@ -365,9 +369,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa if let comboBox = notification.object as? NSComboBox { - self.pullDataFromUI(false) +// self.pullDataFromUI(false) - if comboBox == self.testDestinationComboBox { + if comboBox == self.testDeviceFilterComboBox { self.reloadUI() @@ -375,6 +379,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.fetchDevices({ () -> () in // }) + } else if comboBox == self.schemesComboBox { + + self.pullSchemeFromUI(true) } } } diff --git a/Buildasaur/SyncPairExtensions.swift b/Buildasaur/SyncPairExtensions.swift index a218cb2..7bbbeb6 100644 --- a/Buildasaur/SyncPairExtensions.swift +++ b/Buildasaur/SyncPairExtensions.swift @@ -84,7 +84,7 @@ extension SyncPair { let query = [ "last": "20" ] - syncer.xcodeServer.getIntegrations(bot.id, query: query, completion: { (integrations, error) -> () in + syncer.xcodeServer.getBotIntegrations(bot.id, query: query, completion: { (integrations, error) -> () in if let error = error { let e = Error.withInfo("Bot \(bot.name) failed return integrations", internalError: error) diff --git a/Buildasaur/XcodeServerSyncerUtils.swift b/Buildasaur/XcodeServerSyncerUtils.swift index 443a9d3..482350d 100644 --- a/Buildasaur/XcodeServerSyncerUtils.swift +++ b/Buildasaur/XcodeServerSyncerUtils.swift @@ -25,7 +25,18 @@ class XcodeServerSyncerUtils { let analyze = template.shouldAnalyze ?? false let test = template.shouldTest ?? false let archive = template.shouldArchive ?? false - let deviceSpecification = template.deviceSpecification + + //TODO: create a device spec from testing devices and filter type (and scheme target type?) + let testingDeviceIds = template.testingDeviceIds + let filterType = template.deviceFilter + let platformType = template.platformType ?? .iOS //default to iOS for no reason + let architectureType = DeviceFilter.ArchitectureType.architectureFromPlatformType(platformType) + + let devicePlatform = DevicePlatform(type: platformType) + let deviceFilter = DeviceFilter(platform: devicePlatform, filterType: filterType, architectureType: architectureType) + + let deviceSpecification = DeviceSpecification(filters: [deviceFilter], deviceIdentifiers: testingDeviceIds) + let blueprint = project.createSourceControlBlueprint(branch) //create bot config From 252f5b47a30659a04f664104f2f805d3c35684f4 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Fri, 3 Jul 2015 00:13:23 +0200 Subject: [PATCH 4/5] hacking towards working with xcode 7. tested and works for OS X apps now. --- Buildasaur/BuildTemplateViewController.swift | 6 +++--- Buildasaur/NetworkUtils.swift | 13 +++++++------ Podfile.lock | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Buildasaur/BuildTemplateViewController.swift b/Buildasaur/BuildTemplateViewController.swift index c490e4c..7b85d7a 100644 --- a/Buildasaur/BuildTemplateViewController.swift +++ b/Buildasaur/BuildTemplateViewController.swift @@ -338,6 +338,7 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa let platformType = try XcodeDeviceParser.parseDeviceTypeFromProjectUrlAndScheme(self.project.url, scheme: selectedScheme).toPlatformType() self.buildTemplate.platformType = platformType self.reloadUI() + return true } catch { print("\(error)") return false @@ -359,7 +360,7 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.buildTemplate.deviceFilter = filter return true } - if interactive { + if interactive && self.testDeviceFilterComboBox.numberOfItems > 0 { UIUtils.showAlertWithText("Please select a destination to build with") } return false @@ -369,10 +370,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa if let comboBox = notification.object as? NSComboBox { -// self.pullDataFromUI(false) - if comboBox == self.testDeviceFilterComboBox { + self.pullFilterFromUI(true) self.reloadUI() //filter changed, refetch diff --git a/Buildasaur/NetworkUtils.swift b/Buildasaur/NetworkUtils.swift index 01f5842..d306d03 100644 --- a/Buildasaur/NetworkUtils.swift +++ b/Buildasaur/NetworkUtils.swift @@ -43,13 +43,14 @@ class NetworkUtils { completion(success: false, error: Error.withInfo("Missing write permission for repo")) } else { //now test ssh keys - self.checkValidityOfSSHKeys(credentialValidationBlueprint, completion: { (success, error) -> () in - - Log.verbose("Finished blueprint validation with success: \(success), error: \(error)") - + //TODO: do SSH Key validation properly in the new UI once we have Xcode Server credentials. +// self.checkValidityOfSSHKeys(credentialValidationBlueprint, completion: { (success, error) -> () in + +// Log.verbose("Finished blueprint validation with success: \(success), error: \(error)") + //now complete - completion(success: success, error: error) - }) + completion(success: true, error: nil) +// }) } } else { completion(success: false, error: Error.withInfo("Couldn't find repo permissions in GitHub response")) diff --git a/Podfile.lock b/Podfile.lock index ea8a4e4..3e4bb04 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - XcodeServerSDK (0.1-beta1) + - XcodeServerSDK (0.1-beta3) DEPENDENCIES: - XcodeServerSDK (from `git@github.com:czechboy0/XcodeServerSDK.git`, branch `swift-2`) @@ -11,10 +11,10 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: XcodeServerSDK: - :commit: 22f0f31943b3fd7a1e632e007c1382761a8732c7 + :commit: 35f1f67b4c1e0ee34b75377c7e16504c3acf74ea :git: git@github.com:czechboy0/XcodeServerSDK.git SPEC CHECKSUMS: - XcodeServerSDK: 0c70a5edfbb6c1e64e248f6e11fe8cb87faf148d + XcodeServerSDK: e409d4841fd0fde113355cc7532d0e159b13ccf1 COCOAPODS: 0.37.2 From b037a1b7cc4c988aa5bb94f202da71d0eaf0d6d0 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Fri, 3 Jul 2015 01:15:58 +0200 Subject: [PATCH 5/5] got the devices working... ok xcode 7 alpha ready. --- Buildasaur/BuildTemplateViewController.swift | 176 +++++++++++-------- Podfile.lock | 2 +- 2 files changed, 101 insertions(+), 77 deletions(-) diff --git a/Buildasaur/BuildTemplateViewController.swift b/Buildasaur/BuildTemplateViewController.swift index 7b85d7a..60c7f94 100644 --- a/Buildasaur/BuildTemplateViewController.swift +++ b/Buildasaur/BuildTemplateViewController.swift @@ -11,7 +11,7 @@ import AppKit import BuildaUtils import XcodeServerSDK -class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTableViewDataSource, NSTableViewDelegate, SetupViewControllerDelegate { +class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTableViewDataSource, NSTableViewDelegate, SetupViewControllerDelegate, NSComboBoxDataSource { var storageManager: StorageManager! var project: LocalSource! @@ -68,6 +68,10 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.xcodeServer = xcodeServer } + self.testDeviceFilterComboBox.delegate = self + self.testDeviceFilterComboBox.usesDataSource = true + self.testDeviceFilterComboBox.dataSource = self + let schemes = self.project.schemeNames() self.schemesComboBox.removeAllItems() self.schemesComboBox.addItemsWithObjectValues(schemes) @@ -107,21 +111,21 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.refreshDataInDeviceFilterComboBox() self.triggersTableView.reloadData() + self.testDeviceFilterComboBox.reloadData() } func refreshDataInDeviceFilterComboBox() { - self.testDeviceFilterComboBox.removeAllItems() + self.testDeviceFilterComboBox.reloadData() - let allFilterNames = self.allFilters().map({ (item) -> String in return item.toString() }) - self.testDeviceFilterComboBox.addItemsWithObjectValues(allFilterNames) + let filters = self.allFilters() let filter = self.buildTemplate.deviceFilter ?? .AllAvailableDevicesAndSimulators - if let destinationIndex = self.allFilters().indexOfFirstObjectPassingTest({ $0 == filter }) { + if let destinationIndex = filters.indexOfFirstObjectPassingTest({ $0 == filter }) { self.testDeviceFilterComboBox.selectItemAtIndex(destinationIndex) } - self.testDeviceFilterComboBox.delegate = self + return } func fetchDevices(completion: () -> ()) { @@ -155,58 +159,56 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa func processReceivedDevices(devices: [Device]) -> [Device] { - //TODO: migrate this over - //pull filter from testing destination -// var filter = BotConfiguration.TestingDestinationIdentifier.AllCompatible -// let index = self.testDestinationComboBox.indexOfSelectedItem -// if index > -1 { -// filter = self.allDestinations()[index] -// } -// -// let allowedDeviceTypes = Set(filter.allowedDeviceTypes()) -// -// //filter first -// let filtered = devices.filter { (device: Device) -> Bool in -// if let type = BotConfiguration.DeviceType(rawValue: device.deviceType) { -// return allowedDeviceTypes.contains(type) -// } -// return false -// } -// -// let sortDevices = { -// (a: Device, b: Device) -> (equal: Bool, shouldGoBefore: Bool) in -// -// if a.simulator == b.simulator { -// return (equal: true, shouldGoBefore: true) -// } -// return (equal: false, shouldGoBefore: !a.simulator) -// } -// -// let sortConnected = { -// (a: Device, b: Device) -> (equal: Bool, shouldGoBefore: Bool) in -// -// if a.connected == b.connected { -// return (equal: true, shouldGoBefore: false) -// } -// return (equal: false, shouldGoBefore: a.connected) -// } -// -// //then sort, devices first and if match, connected first -// let sortedDevices = sorted(filtered, { (a, b) -> Bool in -// -// let (equalDevices, goBeforeDevices) = sortDevices(a, b) -// if !equalDevices { -// return goBeforeDevices -// } -// -// let (equalConnected, goBeforeConnected) = sortConnected(a, b) -// if !equalConnected { -// return goBeforeConnected -// } -// return true -// }) - - return [] + //pull filter from platform type + guard let platform = self.buildTemplate.platformType else { + return [] + } + + let allowedPlatforms: Set + switch platform { + case .iOS, .iOS_Simulator: + allowedPlatforms = Set([.iOS, .iOS_Simulator]) + default: + allowedPlatforms = Set([platform]) + } + + //filter first + let filtered = devices.filter { allowedPlatforms.contains($0.platform) } + + let sortDevices = { + (a: Device, b: Device) -> (equal: Bool, shouldGoBefore: Bool) in + + if a.simulator == b.simulator { + return (equal: true, shouldGoBefore: true) + } + return (equal: false, shouldGoBefore: !a.simulator) + } + + let sortConnected = { + (a: Device, b: Device) -> (equal: Bool, shouldGoBefore: Bool) in + + if a.connected == b.connected { + return (equal: true, shouldGoBefore: false) + } + return (equal: false, shouldGoBefore: a.connected) + } + + //then sort, devices first and if match, connected first + let sortedDevices = filtered.sort { (a, b) -> Bool in + + let (equalDevices, goBeforeDevices) = sortDevices(a, b) + if !equalDevices { + return goBeforeDevices + } + + let (equalConnected, goBeforeConnected) = sortConnected(a, b) + if !equalConnected { + return goBeforeConnected + } + return true + } + + return sortedDevices } override func prepareForSegue(segue: NSStoryboardSegue, sender: AnyObject?) { @@ -338,6 +340,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa let platformType = try XcodeDeviceParser.parseDeviceTypeFromProjectUrlAndScheme(self.project.url, scheme: selectedScheme).toPlatformType() self.buildTemplate.platformType = platformType self.reloadUI() + self.fetchDevices({ () -> () in + // + }) return true } catch { print("\(error)") @@ -361,7 +366,7 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa return true } if interactive && self.testDeviceFilterComboBox.numberOfItems > 0 { - UIUtils.showAlertWithText("Please select a destination to build with") + UIUtils.showAlertWithText("Please select a device filter to test on") } return false } @@ -381,6 +386,9 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa }) } else if comboBox == self.schemesComboBox { + if self.testDeviceFilterComboBox.numberOfItems > 0 { + self.testDeviceFilterComboBox.selectItemAtIndex(0) + } self.pullSchemeFromUI(true) } } @@ -407,6 +415,23 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa }) } + //MARK: filter combo box + func numberOfItemsInComboBox(aComboBox: NSComboBox) -> Int { + if (aComboBox == self.testDeviceFilterComboBox) { + return self.allFilters().count + } + return 0 + } + + func comboBox(aComboBox: NSComboBox, objectValueForItemAtIndex index: Int) -> AnyObject { + if (aComboBox == self.testDeviceFilterComboBox) { + if index >= 0 { + return self.allFilters()[index].toString() + } + } + return "" + } + //MARK: triggers table view func numberOfRowsInTableView(tableView: NSTableView) -> Int { @@ -438,11 +463,10 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa let string = "\(simString)\(device.name) (\(device.osVersion)) \(connString)" return string case "enabled": - break -// let devices = self.buildTemplate.testingDeviceIds ?? [] -// let index = devices.indexOfFirstObjectPassingTest({ $0 == device.id }) -// let enabled = index > -1 -// return enabled + let devices = self.buildTemplate.testingDeviceIds ?? [] + let index = devices.indexOfFirstObjectPassingTest({ $0 == device.id }) + let enabled = index > -1 + return enabled default: return nil } @@ -498,19 +522,19 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa //toggle selection in model and reload data //get device at index first -// let device = self.allAvailableTestingDevices[self.testDevicesTableView.selectedRow] + let device = self.allAvailableTestingDevices[self.testDevicesTableView.selectedRow] //see if we are checking or unchecking -// let foundIndex = self.buildTemplate.testingDeviceIds.indexOfFirstObjectPassingTest({ $0 == device.id }) -// -// if let foundIndex = foundIndex { -// //found, remove it -// self.buildTemplate.testingDeviceIds.removeAtIndex(foundIndex) -// } else { -// //not found, add it -// self.buildTemplate.testingDeviceIds.append(device.id) -// } -// -// self.testDevicesTableView.reloadData() + let foundIndex = self.buildTemplate.testingDeviceIds.indexOfFirstObjectPassingTest({ $0 == device.id }) + + if let foundIndex = foundIndex { + //found, remove it + self.buildTemplate.testingDeviceIds.removeAtIndex(foundIndex) + } else { + //not found, add it + self.buildTemplate.testingDeviceIds.append(device.id) + } + + self.testDevicesTableView.reloadData() } } diff --git a/Podfile.lock b/Podfile.lock index 3e4bb04..40f2e7b 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -11,7 +11,7 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: XcodeServerSDK: - :commit: 35f1f67b4c1e0ee34b75377c7e16504c3acf74ea + :commit: df387df50bcca48537833d37deb364d28be823c0 :git: git@github.com:czechboy0/XcodeServerSDK.git SPEC CHECKSUMS: