Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Xcode 7 Support #44

Merged
merged 26 commits into from
Jun 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2c0cd7f
adding new object, DeviceSpecification that is new to the API in Xcode 7
Jun 24, 2015
4546d1d
added device spec parsing
Jun 24, 2015
773a569
added missing files to ios
Jun 24, 2015
788a131
added throwing versions of map and filter
Jun 24, 2015
efa657e
Merge branch 'swift-2' into hd/tested_devices_xcode_7
Jun 24, 2015
59d0358
add new files to the watch framework target as well
Jun 24, 2015
fbd39de
added basic objects for the DeviceSpecification object: Filter and Pl…
Jun 24, 2015
b173a1d
codesign not
Jun 24, 2015
9b869da
Revert "codesign not"
Jun 24, 2015
d899407
parsing more things, trying to get a better understanding...
Jun 24, 2015
8a39af4
Merge branch 'swift-2' into hd/tested_devices_xcode_7
Jun 25, 2015
7f96a43
I think I cracked how to verify the server fingerprint and make the n…
Jun 25, 2015
ca3e2b0
- added blueprint credentials validation
Jun 26, 2015
8cf61bd
adopting new approach to bot creation, now with automatic blueprint v…
Jun 26, 2015
e8ebffd
whoops, debugging hack sneaked in
Jun 26, 2015
111d44f
- keep the original JSON of parsed objects
Jun 26, 2015
e230ecf
better default nil approach
Jun 27, 2015
10f2992
throws -> rethrows
Jun 27, 2015
270bec4
bot creation tested and works on Xcode 7! yayz.
Jun 27, 2015
23e2f74
not again, damn it
Jun 27, 2015
de6438a
pruning test data
Jun 27, 2015
239c6b2
project
Jun 27, 2015
ad1e5e2
added Carthfile and our first dependency - DVR. let's see how it goes.
Jun 27, 2015
f33492a
got DVR working! including nice plain text JSON saving to casettes! n…
Jun 28, 2015
128df49
- live tests of bot creation
Jun 28, 2015
96b33bf
creating bots works, i repeat, creating bots works on all 3 platforms…
Jun 28, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Checkouts

# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
Expand Down
1 change: 1 addition & 0 deletions Cartfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github "czechboy0/DVR" "2742bb80be229da51b1c923c3d3e6eaadc129b8e"
1 change: 1 addition & 0 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github "czechboy0/DVR" "2742bb80be229da51b1c923c3d3e6eaadc129b8e"
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ We're providing a Plaground in which you can easily interact with `XcodeServerSD
| _List devices connected to server_ | :white_check_mark: | :white_check_mark: |
| _List hosted repositories on server_ | :white_check_mark: | :no_entry: |
| _Create a new hosted repository_ | :white_check_mark: | :no_entry: |
| Get supported platforms | :no_entry: | :white_check_mark: |
| Get SCM branches from Blueprint | :no_entry: | :white_check_mark: |
| Verify user can manage server | :no_entry: | :white_check_mark: |

Opertions listed in table above in _italics_ are those provided by  in Xcode. Rest of operations are just a product of reverse engineering.

Expand All @@ -110,6 +113,9 @@ Using hardware buttons to start integrations? Why not! The sky is the limit.
# License
[MIT](https://github.com/czechboy0/XcodeServerSDK/blob/master/LICENSE)

# Building & Testing
We use [Carthage](https://github.com/Carthage/Carthage) to pull in some dependencies for tests. If you clone this repo and want to run tests, first you have to run `carthage update --no-build` to download the necessary dependencies.

# Contributing
Create an issue or (preferably) send a pull request.

Expand Down
266 changes: 214 additions & 52 deletions XcodeServerSDK.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions XcodeServerSDK/Server Entities/Bot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ public class Bot : XcodeServerEntity {

public let name: String
public let configuration: BotConfiguration
public let integrationsCount: Int!
public let integrationsCount: Int

public required init(json: NSDictionary) {

self.name = json.stringForKey("name")
self.configuration = BotConfiguration(json: json.dictionaryForKey("configuration"))
self.integrationsCount = json.intForKey("integration_counter")
self.integrationsCount = json.optionalIntForKey("integration_counter") ?? 0

super.init(json: json)
}
Expand All @@ -30,7 +30,7 @@ public class Bot : XcodeServerEntity {

self.name = name
self.configuration = configuration
self.integrationsCount = nil
self.integrationsCount = 0

super.init()
}
Expand Down
76 changes: 27 additions & 49 deletions XcodeServerSDK/Server Entities/BotConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,46 +69,8 @@ public class BotConfiguration : XcodeServerEntity {
- AllCompatible: All Compatible (default) - for build only
*/
public enum TestingDestinationIdentifier : Int {
case iOS_AllDevicesAndSimulators = 0
case iOS_AllDevices = 1
case iOS_AllSimulators = 2
case iOS_SelectedDevicesAndSimulators = 3
case iOSAndWatch = 0
case Mac = 7
case AllCompatible = 8

public func toString() -> String {
switch self {
case .iOS_AllDevicesAndSimulators:
return "iOS: All Devices and Simulators"
case .iOS_AllDevices:
return "iOS: All Devices"
case .iOS_AllSimulators:
return "iOS: All Simulators"
case .iOS_SelectedDevicesAndSimulators:
return "iOS: Selected Devices and Simulators"
case .Mac:
return "Mac"
case .AllCompatible:
return "All Compatible (Mac + iOS)"
}
}

public func allowedDeviceTypes() -> [DeviceType] {
switch self {
case .iOS_AllDevicesAndSimulators:
return [.iPhone, .Simulator]
case .iOS_AllDevices:
return [.iPhone]
case .iOS_AllSimulators:
return [.Simulator]
case .iOS_SelectedDevicesAndSimulators:
return [.iPhone, .Simulator]
case .Mac:
return [.Mac]
case .AllCompatible:
return [.iPhone, .Simulator, .Mac]
}
}
}

public let builtFromClean: CleaningPolicy!
Expand All @@ -118,8 +80,17 @@ public class BotConfiguration : XcodeServerEntity {
public let schemeName: String
public let schedule: BotSchedule
public let triggers: [Trigger]
public let testingDestinationType: TestingDestinationIdentifier?
public let testingDeviceIDs: [String]
public var testingDestinationType: TestingDestinationIdentifier {
get {
if let firstFilter = self.deviceSpecification.filters.first {
if case .OSX = firstFilter.platform.type {
return .Mac
}
}
return .iOSAndWatch
}
}
public let deviceSpecification: DeviceSpecification
public let sourceControlBlueprint: SourceControlBlueprint

public required init(json: NSDictionary) {
Expand All @@ -131,10 +102,19 @@ public class BotConfiguration : XcodeServerEntity {
self.schemeName = json.stringForKey("schemeName")
self.schedule = BotSchedule(json: json)
self.triggers = XcodeServerArray(json.arrayForKey("triggers"))
self.testingDestinationType = TestingDestinationIdentifier(rawValue: json.intForKey("testingDestinationType"))
self.testingDeviceIDs = json.arrayForKey("testingDeviceIDs")
self.sourceControlBlueprint = SourceControlBlueprint(json: json.dictionaryForKey("sourceControlBlueprint"))

//old bots (xcode 6) only have testingDeviceIds, try to parse those into the new format of DeviceSpecification (xcode 7)
if let deviceSpecJSON = json.optionalDictionaryForKey("deviceSpecification") {
self.deviceSpecification = DeviceSpecification(json: deviceSpecJSON)
} else {
if let testingDeviceIds = json.optionalArrayForKey("testingDeviceIDs") as? [String] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.deviceSpecification = (json.optionalArrayForKey("testingDeviceIDs") as? [String]).map { 
    DeviceSpecification(json: $0) 
} ?? DeviceSpecification(testingDeviceIDs: [])

or do you rather have it verbose with if/else notation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, in this case I prefer the longer, but simpler to understand solution. I actually prefer that most times, because the compiler reorders/optimizes the hell out of it anyway, so we can at least write readable code 😊 But thanks for the suggestion, that's a good way to write it really concisely.

self.deviceSpecification = DeviceSpecification(testingDeviceIDs: testingDeviceIds)
} else {
self.deviceSpecification = DeviceSpecification(testingDeviceIDs: [])
}
}

super.init(json: json)
}

Expand All @@ -146,8 +126,7 @@ public class BotConfiguration : XcodeServerEntity {
schemeName: String,
schedule: BotSchedule,
triggers: [Trigger],
testingDeviceIDs: [String],
testingDestinationType: TestingDestinationIdentifier,
deviceSpecification: DeviceSpecification,
sourceControlBlueprint: SourceControlBlueprint) {

self.builtFromClean = builtFromClean
Expand All @@ -157,9 +136,8 @@ public class BotConfiguration : XcodeServerEntity {
self.schemeName = schemeName
self.schedule = schedule
self.triggers = triggers
self.testingDeviceIDs = testingDeviceIDs
self.deviceSpecification = deviceSpecification
self.sourceControlBlueprint = sourceControlBlueprint
self.testingDestinationType = testingDestinationType

super.init()
}
Expand All @@ -177,9 +155,9 @@ public class BotConfiguration : XcodeServerEntity {
dictionary["triggers"] = self.triggers.map { $0.dictionarify() }
dictionary["performsAnalyzeAction"] = self.analyze
dictionary["schemeName"] = self.schemeName
dictionary["testingDeviceIDs"] = self.testingDeviceIDs
dictionary["deviceSpecification"] = self.deviceSpecification.dictionarify()
dictionary["performsArchiveAction"] = self.archive
dictionary["testingDestinationType"] = self.testingDestinationType?.rawValue //TODO: figure out if we need this
dictionary["testingDestinationType"] = self.testingDestinationType.rawValue //TODO: figure out if we still need this in Xcode 7

let botScheduleDict = self.schedule.dictionarify() //needs to be merged into the main bot config dict
dictionary.addEntriesFromDictionary(botScheduleDict as [NSObject : AnyObject])
Expand Down
192 changes: 192 additions & 0 deletions XcodeServerSDK/Server Entities/DeviceSpecification.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
//
// DeviceSpecification.swift
// XcodeServerSDK
//
// Created by Honza Dvorsky on 24/06/2015.
// Copyright © 2015 Honza Dvorsky. All rights reserved.
//

import Foundation

public class DevicePlatform : XcodeServerEntity {

let displayName: String
let version: String

public enum PlatformType: String {
case Unknown = "unknown"
case iOS = "com.apple.platform.iphoneos"
case OSX = "com.apple.platform.macosx"
case watchOS = "com.apple.platform.watchos"
}

public enum SimulatorType: String {
case iPhone = "com.apple.platform.iphonesimulator"
case Watch = "com.apple.platform.watchsimulator"
}

let type: PlatformType
let simulatorType: SimulatorType?

public required init(json: NSDictionary) {

self.displayName = json.stringForKey("displayName")
self.version = json.stringForKey("version")
self.type = PlatformType(rawValue: json.optionalStringForKey("identifier") ?? "") ?? .Unknown
self.simulatorType = SimulatorType(rawValue: json.optionalStringForKey("simulatorIdentifier") ?? "")

super.init(json: json)
}

//for just informing the intention - iOS or WatchOS or OS X - and we'll fetch the real ones and replace this placeholder with a fetched one.
public init(type: PlatformType) {
self.type = type
self.displayName = ""
self.version = ""
self.simulatorType = nil

super.init()
}

public class func OSX() -> DevicePlatform {
return DevicePlatform(type: DevicePlatform.PlatformType.OSX)
}

public class func iOS() -> DevicePlatform {
return DevicePlatform(type: DevicePlatform.PlatformType.iOS)
}

public class func watchOS() -> DevicePlatform {
return DevicePlatform(type: DevicePlatform.PlatformType.watchOS)
}

public override func dictionarify() -> NSDictionary {

//in this case we want everything the way we parsed it.
if let original = self.originalJSON {
return original
}

let dictionary = NSMutableDictionary()

dictionary["displayName"] = self.displayName
dictionary["version"] = self.version
dictionary["identifier"] = self.type.rawValue
dictionary.optionallyAddValueForKey(self.simulatorType?.rawValue, key: "simulatorIdentifier")

return dictionary
}
}

public class DeviceFilter : XcodeServerEntity {

var platform: DevicePlatform

public enum FilterType: Int {
case AllAvailableDevicesAndSimulators = 0
case AllDevices = 1
case AllSimulators = 2
case SelectedDevicesAndSimulators = 3
}

let filterType: FilterType

public enum ArchitectureType: Int {
case Unknown = -1
case iOS_Like = 0 //also watchOS
case OSX_Like = 1
}

let architectureType: ArchitectureType //TODO: ditto, find out more.

public required init(json: NSDictionary) {

self.platform = DevicePlatform(json: json.dictionaryForKey("platform"))
self.filterType = FilterType(rawValue: json.intForKey("filterType")) ?? .AllAvailableDevicesAndSimulators
self.architectureType = ArchitectureType(rawValue: json.optionalIntForKey("architectureType") ?? -1) ?? .Unknown

super.init(json: json)
}

public init(platform: DevicePlatform, filterType: FilterType, architectureType: ArchitectureType) {
self.platform = platform
self.filterType = filterType
self.architectureType = architectureType

super.init()
}

public override func dictionarify() -> NSDictionary {

return [
"filterType": self.filterType.rawValue,
"architectureType": self.architectureType.rawValue,
"platform": self.platform.dictionarify()
]
}
}

public class DeviceSpecification : XcodeServerEntity {

public let deviceIdentifiers: [String]
public let filters: [DeviceFilter]

public required init(json: NSDictionary) {

self.deviceIdentifiers = json.arrayForKey("deviceIdentifiers")
self.filters = XcodeServerArray(json.arrayForKey("filters"))

super.init(json: json)
}

public init(filters: [DeviceFilter], deviceIdentifiers: [String]) {
self.deviceIdentifiers = deviceIdentifiers
self.filters = filters

super.init()
}

/**
Initializes a new DeviceSpecification object with only a list of tested device ids.
This is a convenience initializer for compatibility with old Xcode 6 bots that are still hanging around on old servers.
*/
public init(testingDeviceIDs: [String]) {

self.deviceIdentifiers = testingDeviceIDs
self.filters = []

super.init()
}

public override func dictionarify() -> NSDictionary {

return [
"deviceIdentifiers": self.deviceIdentifiers,
"filters": self.filters.map({ $0.dictionarify() })
]
}

// MARK: Convenience methods

public class func OSX() -> DeviceSpecification {
let platform = DevicePlatform.OSX()
let filter = DeviceFilter(platform: platform, filterType: .AllAvailableDevicesAndSimulators, architectureType: .OSX_Like)
let spec = DeviceSpecification(filters: [filter], deviceIdentifiers: [])
return spec
}

public class func iOS(filterType: DeviceFilter.FilterType, deviceIdentifiers: [String]) -> DeviceSpecification {
let platform = DevicePlatform.iOS()
let filter = DeviceFilter(platform: platform, filterType: filterType, architectureType: .iOS_Like)
let spec = DeviceSpecification(filters: [filter], deviceIdentifiers: deviceIdentifiers)
return spec
}

public class func watchOS() -> DeviceSpecification {
let platform = DevicePlatform.watchOS()
let filter = DeviceFilter(platform: platform, filterType: .AllAvailableDevicesAndSimulators, architectureType: .iOS_Like)
let spec = DeviceSpecification(filters: [filter], deviceIdentifiers: [])
return spec
}
}

Loading