spaceship 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +16 -15
- data/lib/spaceship.rb +2 -1
- data/lib/spaceship/base.rb +0 -1
- data/lib/spaceship/client.rb +71 -69
- data/lib/spaceship/helper/net_http_generic_request.rb +1 -1
- data/lib/spaceship/launcher.rb +19 -14
- data/lib/spaceship/portal/app.rb +23 -9
- data/lib/spaceship/portal/app_group.rb +77 -0
- data/lib/spaceship/portal/app_service.rb +222 -0
- data/lib/spaceship/portal/certificate.rb +2 -2
- data/lib/spaceship/portal/device.rb +7 -7
- data/lib/spaceship/portal/portal.rb +3 -1
- data/lib/spaceship/portal/portal_base.rb +1 -1
- data/lib/spaceship/portal/portal_client.rb +64 -10
- data/lib/spaceship/portal/provisioning_profile.rb +28 -54
- data/lib/spaceship/portal/spaceship.rb +27 -9
- data/lib/spaceship/portal/ui/select_team.rb +6 -8
- data/lib/spaceship/tunes/app_screenshot.rb +1 -1
- data/lib/spaceship/tunes/app_status.rb +5 -6
- data/lib/spaceship/tunes/app_submission.rb +24 -23
- data/lib/spaceship/tunes/app_version.rb +27 -34
- data/lib/spaceship/tunes/application.rb +24 -25
- data/lib/spaceship/tunes/build.rb +6 -7
- data/lib/spaceship/tunes/build_train.rb +2 -2
- data/lib/spaceship/tunes/language_converter.rb +14 -13
- data/lib/spaceship/tunes/language_item.rb +1 -1
- data/lib/spaceship/tunes/processing_build.rb +1 -1
- data/lib/spaceship/tunes/spaceship.rb +5 -5
- data/lib/spaceship/tunes/tester.rb +14 -15
- data/lib/spaceship/tunes/tunes_client.rb +61 -61
- data/lib/spaceship/ui.rb +1 -2
- data/lib/spaceship/version.rb +2 -2
- metadata +18 -2
@@ -0,0 +1,77 @@
|
|
1
|
+
module Spaceship
|
2
|
+
module Portal
|
3
|
+
# Represents an app group of the Apple Dev Portal
|
4
|
+
class AppGroup < PortalBase
|
5
|
+
# @return (String) The identifier assigned to this group
|
6
|
+
# @example
|
7
|
+
# "group.com.example.application"
|
8
|
+
attr_accessor :group_id
|
9
|
+
|
10
|
+
# @return (String) The prefix assigned to this group
|
11
|
+
# @example
|
12
|
+
# "9J57U9392R"
|
13
|
+
attr_accessor :prefix
|
14
|
+
|
15
|
+
# @return (String) The name of this group
|
16
|
+
# @example
|
17
|
+
# "App Group"
|
18
|
+
attr_accessor :name
|
19
|
+
|
20
|
+
# @return (String) Status of the group
|
21
|
+
# @example
|
22
|
+
# "current"
|
23
|
+
attr_accessor :status
|
24
|
+
|
25
|
+
# @return (String) The identifier of this app group, provided by the Dev Portal
|
26
|
+
# @example
|
27
|
+
# "2MAY7NPHAA"
|
28
|
+
attr_accessor :app_group_id
|
29
|
+
|
30
|
+
attr_mapping(
|
31
|
+
'applicationGroup' => :app_group_id,
|
32
|
+
'name' => :name,
|
33
|
+
'prefix' => :prefix,
|
34
|
+
'identifier' => :group_id,
|
35
|
+
'status' => :status
|
36
|
+
)
|
37
|
+
|
38
|
+
class << self
|
39
|
+
# Create a new object based on a hash.
|
40
|
+
# This is used to create a new object based on the server response.
|
41
|
+
def factory(attrs)
|
42
|
+
self.new(attrs)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return (Array) Returns all app groups available for this account
|
46
|
+
def all
|
47
|
+
client.app_groups.map { |group| self.factory(group) }
|
48
|
+
end
|
49
|
+
|
50
|
+
# Creates a new App Group on the Apple Dev Portal
|
51
|
+
#
|
52
|
+
# @param group_id [String] the identifier to assign to this group
|
53
|
+
# @param name [String] the name of the group
|
54
|
+
# @return (AppGroup) The group you just created
|
55
|
+
def create!(group_id: nil, name: nil)
|
56
|
+
new_group = client.create_app_group!(name, group_id)
|
57
|
+
self.new(new_group)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Find a specific App Group group_id
|
61
|
+
# @return (AppGroup) The app group you're looking for. This is nil if the app group can't be found.
|
62
|
+
def find(group_id)
|
63
|
+
all.find do |group|
|
64
|
+
group.group_id == group_id
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Delete this app group
|
70
|
+
# @return (AppGroup) The app group you just deletd
|
71
|
+
def delete!
|
72
|
+
client.delete_app_group!(app_group_id)
|
73
|
+
self
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
module Spaceship
|
2
|
+
module Portal
|
3
|
+
# Represents a single application service (its state to be more precise) on the Apple Dev Portal
|
4
|
+
class AppService
|
5
|
+
# @return (String) The identifier used by the Dev Portal to represent this service
|
6
|
+
# @example
|
7
|
+
# "homeKit"
|
8
|
+
attr_accessor :service_id
|
9
|
+
|
10
|
+
# @return (Object) The current value for this service
|
11
|
+
# @example
|
12
|
+
# false
|
13
|
+
attr_accessor :value
|
14
|
+
|
15
|
+
# @return (String) The service URI for this service
|
16
|
+
# @example
|
17
|
+
# "account/ios/identifiers/updateService.action"
|
18
|
+
attr_accessor :service_uri
|
19
|
+
|
20
|
+
def initialize(service_id, value)
|
21
|
+
@service_id = service_id
|
22
|
+
@value = value
|
23
|
+
|
24
|
+
if @service_id == "push"
|
25
|
+
# Push notifications have a special URI
|
26
|
+
@service_uri = "account/ios/identifiers/updatePushService.action"
|
27
|
+
else
|
28
|
+
# Default service URI
|
29
|
+
@service_uri = "account/ios/identifiers/updateService.action"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def app_group
|
35
|
+
self::AppGroup
|
36
|
+
end
|
37
|
+
|
38
|
+
def associated_domains
|
39
|
+
self::AssociatedDomains
|
40
|
+
end
|
41
|
+
|
42
|
+
def data_protection
|
43
|
+
self::DataProtection
|
44
|
+
end
|
45
|
+
|
46
|
+
def health_kit
|
47
|
+
self::HealthKit
|
48
|
+
end
|
49
|
+
|
50
|
+
def home_kit
|
51
|
+
self::HomeKit
|
52
|
+
end
|
53
|
+
|
54
|
+
def wireless_accessory
|
55
|
+
self::WirelessAccessory
|
56
|
+
end
|
57
|
+
|
58
|
+
def icloud
|
59
|
+
self::Cloud
|
60
|
+
end
|
61
|
+
|
62
|
+
def cloud_kit
|
63
|
+
self::CloudKit
|
64
|
+
end
|
65
|
+
|
66
|
+
def inter_app_audio
|
67
|
+
self::InterAppAudio
|
68
|
+
end
|
69
|
+
|
70
|
+
def passbook
|
71
|
+
self::Passbook
|
72
|
+
end
|
73
|
+
|
74
|
+
def push_notification
|
75
|
+
self::PushNotification
|
76
|
+
end
|
77
|
+
|
78
|
+
def vpn_configuration
|
79
|
+
self::VPNConfiguration
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def ==(other)
|
84
|
+
self.class == other.class &&
|
85
|
+
self.service_id == other.service_id &&
|
86
|
+
self.value == other.value &&
|
87
|
+
self.service_uri == other.service_uri
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Modules for "constants"
|
92
|
+
#
|
93
|
+
module AppGroup
|
94
|
+
def self.off
|
95
|
+
AppService.new("APG3427HIY", false)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.on
|
99
|
+
AppService.new("APG3427HIY", true)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module AssociatedDomains
|
104
|
+
def self.off
|
105
|
+
AppService.new("SKC3T5S89Y", false)
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.on
|
109
|
+
AppService.new("SKC3T5S89Y", true)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
module DataProtection
|
114
|
+
def self.off
|
115
|
+
AppService.new("dataProtection", "")
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.complete
|
119
|
+
AppService.new("dataProtection", "complete")
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.unless_open
|
123
|
+
AppService.new("dataProtection", "unlessopen")
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.until_first_auth
|
127
|
+
AppService.new("dataProtection", "untilfirstauth")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
module HealthKit
|
132
|
+
def self.off
|
133
|
+
AppService.new("HK421J6T7P", false)
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.on
|
137
|
+
AppService.new("HK421J6T7P", true)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
module HomeKit
|
142
|
+
def self.off
|
143
|
+
AppService.new("homeKit", false)
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.on
|
147
|
+
AppService.new("homeKit", true)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
module WirelessAccessory
|
152
|
+
def self.off
|
153
|
+
AppService.new("WC421J6T7P", false)
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.on
|
157
|
+
AppService.new("WC421J6T7P", true)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
module Cloud
|
162
|
+
def self.off
|
163
|
+
AppService.new("iCloud", false)
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.on
|
167
|
+
AppService.new("iCloud", true)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
module CloudKit
|
172
|
+
def self.xcode5_compatible
|
173
|
+
AppService.new("cloudKitVersion", 1)
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.cloud_kit
|
177
|
+
AppService.new("cloudKitVersion", 2)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
module InterAppAudio
|
182
|
+
def self.off
|
183
|
+
AppService.new("IAD53UNK2F", false)
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.on
|
187
|
+
AppService.new("IAD53UNK2F", true)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
module Passbook
|
192
|
+
def self.off
|
193
|
+
AppService.new("pass", false)
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.on
|
197
|
+
AppService.new("pass", true)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
module PushNotification
|
202
|
+
def self.off
|
203
|
+
AppService.new("push", false)
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.on
|
207
|
+
AppService.new("push", true)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
module VPNConfiguration
|
212
|
+
def self.off
|
213
|
+
AppService.new("V66P55NK2I", false)
|
214
|
+
end
|
215
|
+
|
216
|
+
def self.on
|
217
|
+
AppService.new("V66P55NK2I", true)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -237,7 +237,7 @@ module Spaceship
|
|
237
237
|
end
|
238
238
|
|
239
239
|
# ensure csr is a OpenSSL::X509::Request
|
240
|
-
csr = OpenSSL::X509::Request.new(csr) if csr.
|
240
|
+
csr = OpenSSL::X509::Request.new(csr) if csr.kind_of?(String)
|
241
241
|
|
242
242
|
# if this succeeds, we need to save the .cer and the private key in keychain access or wherever they go in linux
|
243
243
|
response = client.create_certificate!(type, csr.to_pem, app_id)
|
@@ -266,7 +266,7 @@ module Spaceship
|
|
266
266
|
|
267
267
|
# @return (Bool): Is this certificate a push profile for apps?
|
268
268
|
def is_push?
|
269
|
-
self.kind_of?PushCertificate
|
269
|
+
self.kind_of? PushCertificate
|
270
270
|
end
|
271
271
|
end
|
272
272
|
end
|
@@ -3,27 +3,27 @@ module Spaceship
|
|
3
3
|
# Represents a device from the Apple Developer Portal
|
4
4
|
class Device < PortalBase
|
5
5
|
# @return (String) The ID given from the developer portal. You'll probably not need it.
|
6
|
-
# @example
|
6
|
+
# @example
|
7
7
|
# "XJXGVS46MW"
|
8
8
|
attr_accessor :id
|
9
9
|
|
10
10
|
# @return (String) The name of the device
|
11
|
-
# @example
|
11
|
+
# @example
|
12
12
|
# "Felix Krause's iPhone 6"
|
13
13
|
attr_accessor :name
|
14
14
|
|
15
15
|
# @return (String) The UDID of the device
|
16
|
-
# @example
|
16
|
+
# @example
|
17
17
|
# "4c24a7ee5caaa4847f49aaab2d87483053f53b65"
|
18
18
|
attr_accessor :udid
|
19
19
|
|
20
20
|
# @return (String) The platform of the device. This is probably always "ios"
|
21
|
-
# @example
|
21
|
+
# @example
|
22
22
|
# "ios"
|
23
23
|
attr_accessor :platform
|
24
24
|
|
25
25
|
# @return (String) Status of the device. Probably always "c"
|
26
|
-
# @example
|
26
|
+
# @example
|
27
27
|
# "c"
|
28
28
|
attr_accessor :status
|
29
29
|
|
@@ -47,7 +47,7 @@ module Spaceship
|
|
47
47
|
client.devices.map { |device| self.factory(device) }
|
48
48
|
end
|
49
49
|
|
50
|
-
# @return (Device) Find a device based on the ID of the device. *Attention*:
|
50
|
+
# @return (Device) Find a device based on the ID of the device. *Attention*:
|
51
51
|
# This is *not* the UDID. nil if no device was found.
|
52
52
|
def find(device_id)
|
53
53
|
all.find do |device|
|
@@ -72,7 +72,7 @@ module Spaceship
|
|
72
72
|
# Register a new device to this account
|
73
73
|
# @param name (String) (required): The name of the new device
|
74
74
|
# @param udid (String) (required): The UDID of the new device
|
75
|
-
# @example
|
75
|
+
# @example
|
76
76
|
# Spaceship.device.create!(name: "Felix Krause's iPhone 6", udid: "4c24a7ee5caaa4847f49aaab2d87483053f53b65")
|
77
77
|
# @return (Device): The newly created device
|
78
78
|
def create!(name: nil, udid: nil)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'spaceship/portal/portal_base'
|
2
2
|
require 'spaceship/portal/app'
|
3
|
+
require 'spaceship/portal/app_group'
|
4
|
+
require 'spaceship/portal/app_service'
|
3
5
|
require 'spaceship/portal/certificate'
|
4
6
|
require 'spaceship/portal/device'
|
5
7
|
require 'spaceship/portal/provisioning_profile'
|
6
|
-
require 'spaceship/portal/portal_client'
|
8
|
+
require 'spaceship/portal/portal_client'
|
@@ -13,7 +13,7 @@ module Spaceship
|
|
13
13
|
def api_key
|
14
14
|
cache_path = "/tmp/spaceship_api_key.txt"
|
15
15
|
begin
|
16
|
-
cached = File.read(cache_path)
|
16
|
+
cached = File.read(cache_path)
|
17
17
|
rescue Errno::ENOENT
|
18
18
|
end
|
19
19
|
return cached if cached
|
@@ -87,7 +87,6 @@ module Spaceship
|
|
87
87
|
@in_house = (team_information['type'] == 'In-House')
|
88
88
|
end
|
89
89
|
|
90
|
-
|
91
90
|
#####################################################
|
92
91
|
# @!group Apps
|
93
92
|
#####################################################
|
@@ -112,6 +111,28 @@ module Spaceship
|
|
112
111
|
parse_response(r, 'appId')
|
113
112
|
end
|
114
113
|
|
114
|
+
def update_service_for_app(app, service)
|
115
|
+
request(:post, service.service_uri, {
|
116
|
+
teamId: team_id,
|
117
|
+
displayId: app.app_id,
|
118
|
+
featureType: service.service_id,
|
119
|
+
featureValue: service.value
|
120
|
+
})
|
121
|
+
|
122
|
+
details_for_app(app)
|
123
|
+
end
|
124
|
+
|
125
|
+
def associate_groups_with_app(app, groups)
|
126
|
+
r = request(:post, 'account/ios/identifiers/assignApplicationGroupToAppId.action', {
|
127
|
+
teamId: team_id,
|
128
|
+
appIdId: app.app_id,
|
129
|
+
displayId: app.app_id,
|
130
|
+
applicationGroups: groups.map { |g| g.app_group_id }
|
131
|
+
})
|
132
|
+
|
133
|
+
details_for_app(app)
|
134
|
+
end
|
135
|
+
|
115
136
|
def create_app!(type, name, bundle_id)
|
116
137
|
ident_params = case type.to_sym
|
117
138
|
when :explicit
|
@@ -150,6 +171,39 @@ module Spaceship
|
|
150
171
|
parse_response(r)
|
151
172
|
end
|
152
173
|
|
174
|
+
#####################################################
|
175
|
+
# @!group App Groups
|
176
|
+
#####################################################
|
177
|
+
|
178
|
+
def app_groups
|
179
|
+
paging do |page_number|
|
180
|
+
r = request(:post, 'account/ios/identifiers/listApplicationGroups.action', {
|
181
|
+
teamId: team_id,
|
182
|
+
pageNumber: page_number,
|
183
|
+
pageSize: page_size,
|
184
|
+
sort: 'name=asc'
|
185
|
+
})
|
186
|
+
parse_response(r, 'applicationGroupList')
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def create_app_group!(name, group_id)
|
191
|
+
r = request(:post, 'account/ios/identifiers/addApplicationGroup.action', {
|
192
|
+
name: name,
|
193
|
+
identifier: group_id,
|
194
|
+
teamId: team_id
|
195
|
+
})
|
196
|
+
parse_response(r, 'applicationGroup')
|
197
|
+
end
|
198
|
+
|
199
|
+
def delete_app_group!(app_group_id)
|
200
|
+
r = request(:post, 'account/ios/identifiers/deleteApplicationGroup.action', {
|
201
|
+
teamId: team_id,
|
202
|
+
applicationGroup: app_group_id
|
203
|
+
})
|
204
|
+
parse_response(r)
|
205
|
+
end
|
206
|
+
|
153
207
|
#####################################################
|
154
208
|
# @!group Devices
|
155
209
|
#####################################################
|
@@ -167,7 +221,7 @@ module Spaceship
|
|
167
221
|
end
|
168
222
|
|
169
223
|
def create_device!(device_name, device_id)
|
170
|
-
|
224
|
+
req = request(:post) do |r|
|
171
225
|
r.url "https://developerservices2.apple.com/services/#{PROTOCOL_VERSION}/ios/addDevice.action"
|
172
226
|
r.params = {
|
173
227
|
teamId: team_id,
|
@@ -176,7 +230,7 @@ module Spaceship
|
|
176
230
|
}
|
177
231
|
end
|
178
232
|
|
179
|
-
parse_response(
|
233
|
+
parse_response(req, 'device')
|
180
234
|
end
|
181
235
|
|
182
236
|
#####################################################
|
@@ -201,7 +255,7 @@ module Spaceship
|
|
201
255
|
teamId: team_id,
|
202
256
|
type: type,
|
203
257
|
csrContent: csr,
|
204
|
-
appIdId: app_id
|
258
|
+
appIdId: app_id # optional
|
205
259
|
})
|
206
260
|
parse_response(r, 'certRequest')
|
207
261
|
end
|
@@ -231,16 +285,16 @@ module Spaceship
|
|
231
285
|
#####################################################
|
232
286
|
|
233
287
|
def provisioning_profiles
|
234
|
-
|
288
|
+
req = request(:post) do |r|
|
235
289
|
r.url "https://developerservices2.apple.com/services/#{PROTOCOL_VERSION}/ios/listProvisioningProfiles.action"
|
236
290
|
r.params = {
|
237
291
|
teamId: team_id,
|
238
292
|
includeInactiveProfiles: true,
|
239
|
-
onlyCountLists: true
|
293
|
+
onlyCountLists: true
|
240
294
|
}
|
241
295
|
end
|
242
296
|
|
243
|
-
parse_response(
|
297
|
+
parse_response(req, 'provisioningProfiles')
|
244
298
|
end
|
245
299
|
|
246
300
|
def create_provisioning_profile!(name, distribution_method, app_id, certificate_ids, device_ids)
|
@@ -278,11 +332,11 @@ module Spaceship
|
|
278
332
|
provisioningProfileName: name,
|
279
333
|
appIdId: app_id,
|
280
334
|
distributionType: distribution_method,
|
281
|
-
certificateIds: certificate_ids.
|
335
|
+
certificateIds: certificate_ids.join(','),
|
282
336
|
deviceIds: device_ids
|
283
337
|
})
|
284
338
|
|
285
339
|
parse_response(r, 'provisioningProfile')
|
286
340
|
end
|
287
341
|
end
|
288
|
-
end
|
342
|
+
end
|