fastlane 2.125.0.beta.20190531200016 → 2.125.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +70 -70
- data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane_core/lib/fastlane_core/build_watcher.rb +31 -15
- data/pilot/lib/pilot/.build_manager.rb.swp +0 -0
- data/pilot/lib/pilot/.manager.rb.swp +0 -0
- data/pilot/lib/pilot/build_manager.rb +133 -101
- data/pilot/lib/pilot/manager.rb +9 -9
- data/pilot/lib/pilot/tester_exporter.rb +27 -11
- data/pilot/lib/pilot/tester_manager.rb +48 -98
- data/spaceship/lib/spaceship/connect_api.rb +18 -0
- data/spaceship/lib/spaceship/connect_api/.DS_Store +0 -0
- data/spaceship/lib/spaceship/connect_api/client.rb +297 -156
- data/spaceship/lib/spaceship/connect_api/models/.app.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/models/.build.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/models/.model.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/models/app.rb +97 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_app_localization.rb +28 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_app_review_detail.rb +32 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_app_review_submission.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_build_localization.rb +20 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_build_metric.rb +24 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +41 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +56 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_tester_metric.rb +43 -0
- data/spaceship/lib/spaceship/connect_api/models/build.rb +144 -0
- data/spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb +56 -0
- data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +36 -0
- data/spaceship/lib/spaceship/connect_api/models/model.rb +165 -0
- data/spaceship/lib/spaceship/connect_api/models/pre_release_version.rb +20 -0
- data/spaceship/lib/spaceship/connect_api/models/user.rb +50 -0
- data/spaceship/lib/spaceship/connect_api/response.rb +70 -0
- data/spaceship/lib/spaceship/connect_api/token.rb +44 -0
- data/spaceship/lib/spaceship/test_flight/build_trains.rb +1 -1
- metadata +73 -33
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative './model'
|
2
|
+
module Spaceship
|
3
|
+
module ConnectAPI
|
4
|
+
class BuildBetaDetail
|
5
|
+
include Spaceship::ConnectAPI::Model
|
6
|
+
|
7
|
+
attr_accessor :auto_notify_enabled
|
8
|
+
attr_accessor :did_notify
|
9
|
+
attr_accessor :internal_build_state
|
10
|
+
attr_accessor :external_build_state
|
11
|
+
|
12
|
+
module InternalState
|
13
|
+
PROCESSING_EXCEPTION = "PROCESSING_EXCEPTION"
|
14
|
+
MISSING_EXPORT_COMPLIANCE = "MISSING_EXPORT_COMPLIANCE"
|
15
|
+
READY_FOR_BETA_TESTING = "READY_FOR_BETA_TESTING"
|
16
|
+
IN_BETA_TESTING = "IN_BETA_TESTING"
|
17
|
+
EXPIRED = "EXPIRED"
|
18
|
+
IN_EXPORT_COMPLIANCE_REVIEW = "IN_EXPORT_COMPLIANCE_REVIEW"
|
19
|
+
end
|
20
|
+
|
21
|
+
module ExternalState
|
22
|
+
PROCESSING = "PROCESSING"
|
23
|
+
PROCESSING_EXCEPTION = "PROCESSING_EXCEPTION"
|
24
|
+
MISSING_EXPORT_COMPLIANCE = "MISSING_EXPORT_COMPLIANCE"
|
25
|
+
READY_FOR_BETA_TESTING = "READY_FOR_BETA_TESTING"
|
26
|
+
IN_BETA_TESTING = "IN_BETA_TESTING"
|
27
|
+
EXPIRED = "EXPIRED"
|
28
|
+
READY_FOR_BETA_SUBMISSION = "READY_FOR_BETA_SUBMISSION"
|
29
|
+
IN_EXPORT_COMPLIANCE_REVIEW = "IN_EXPORT_COMPLIANCE_REVIEW"
|
30
|
+
WAITING_FOR_BETA_REVIEW = "WAITING_FOR_BETA_REVIEW"
|
31
|
+
IN_BETA_REVIEW = "IN_BETA_REVIEW"
|
32
|
+
BETA_REJECTED = "BETA_REJECTED"
|
33
|
+
BETA_APPROVED = "BETA_APPROVED"
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_mapping({
|
37
|
+
"autoNotifyEnabled" => "auto_notify_enabled",
|
38
|
+
"didNotify" => "did_notify",
|
39
|
+
"internalBuildState" => "internal_build_state",
|
40
|
+
"externalBuildState" => "external_build_state"
|
41
|
+
})
|
42
|
+
|
43
|
+
def self.type
|
44
|
+
return "buildBetaDetails"
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Helpers
|
49
|
+
#
|
50
|
+
|
51
|
+
def ready_for_beta_submission?
|
52
|
+
return external_build_state == ExternalState::READY_FOR_BETA_SUBMISSION
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative './model'
|
2
|
+
module Spaceship
|
3
|
+
module ConnectAPI
|
4
|
+
class BuildDelivery
|
5
|
+
include Spaceship::ConnectAPI::Model
|
6
|
+
|
7
|
+
attr_accessor :cf_build_version
|
8
|
+
attr_accessor :cf_build_short_version_string
|
9
|
+
attr_accessor :platform
|
10
|
+
attr_accessor :uploaded_date
|
11
|
+
|
12
|
+
attr_mapping({
|
13
|
+
"cfBundleVersion" => "cf_build_version",
|
14
|
+
"cfBundleShortVersionString" => "cf_build_short_version_string",
|
15
|
+
"platform" => "platform",
|
16
|
+
"uploadedDate" => "uploaded_date"
|
17
|
+
})
|
18
|
+
|
19
|
+
def self.type
|
20
|
+
return "buildDeliveries"
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# API
|
25
|
+
#
|
26
|
+
|
27
|
+
def self.all(app_id: nil, version: nil, build_number: nil)
|
28
|
+
resps = client.get_build_deliveries(
|
29
|
+
filter: { app: app_id, cfBundleShortVersionString: version, cfBundleVersion: build_number },
|
30
|
+
limit: 1
|
31
|
+
).all_pages
|
32
|
+
return resps.map(&:to_models).flatten
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require_relative '../base'
|
2
|
+
|
3
|
+
module Spaceship
|
4
|
+
module ConnectAPI
|
5
|
+
module Model
|
6
|
+
def self.included(base)
|
7
|
+
Spaceship::ConnectAPI::Models.types ||= []
|
8
|
+
Spaceship::ConnectAPI::Models.types << base
|
9
|
+
base.extend(Spaceship::ConnectAPI::Model)
|
10
|
+
base.extend(Spaceship::ConnectAPI::Model::ClassMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def client
|
15
|
+
return Spaceship::ConnectAPI::Base.client
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_accessor :id
|
20
|
+
|
21
|
+
def initialize(id, attributes)
|
22
|
+
self.id = id
|
23
|
+
update_attributes(attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_attributes(attributes)
|
27
|
+
attributes.each do |key, value|
|
28
|
+
method = "#{key}=".to_sym
|
29
|
+
self.send(method, value) if self.respond_to?(method)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def client
|
34
|
+
return Spaceship::ConnectAPI::Base.client
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
# { "minOsVersion" => "min_os_version" }
|
40
|
+
#
|
41
|
+
# Creates attr_write and attr_reader for :min_os_version
|
42
|
+
# Creates alias for :minOsVersion to :min_os_version
|
43
|
+
#
|
44
|
+
def attr_mapping(attr_map)
|
45
|
+
attr_map.each do |key, value|
|
46
|
+
# Actual
|
47
|
+
reader = value.to_sym
|
48
|
+
writer = "#{value}=".to_sym
|
49
|
+
|
50
|
+
has_reader = instance_methods.include?(reader)
|
51
|
+
has_writer = instance_methods.include?(writer)
|
52
|
+
|
53
|
+
send(:attr_reader, value) unless has_reader
|
54
|
+
send(:attr_writer, value) unless has_writer
|
55
|
+
|
56
|
+
# Alias
|
57
|
+
key_reader = key.to_sym
|
58
|
+
key_writer = "#{key}=".to_sym
|
59
|
+
|
60
|
+
# Alias the API response name to attribute name
|
61
|
+
alias_method(key_reader, reader)
|
62
|
+
alias_method(key_writer, writer)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module Models
|
68
|
+
class << self
|
69
|
+
attr_accessor :types
|
70
|
+
attr_accessor :types_cache
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.parse(json)
|
74
|
+
data = json["data"]
|
75
|
+
raise "No data" unless data
|
76
|
+
|
77
|
+
included = json["included"] || []
|
78
|
+
|
79
|
+
if data.kind_of?(Hash)
|
80
|
+
inflate_model(data, included)
|
81
|
+
elsif data.kind_of?(Array)
|
82
|
+
return data.map do |model_data|
|
83
|
+
inflate_model(model_data, included)
|
84
|
+
end
|
85
|
+
else
|
86
|
+
raise "'data' is neither a hash nor an array"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.find_class(model_data)
|
91
|
+
# Initialize cache
|
92
|
+
@types_cache ||= {}
|
93
|
+
|
94
|
+
# Find class in cache
|
95
|
+
type_string = model_data["type"]
|
96
|
+
type_class = @types_cache[type_string]
|
97
|
+
return type_class if type_class
|
98
|
+
|
99
|
+
# Find class in array
|
100
|
+
type_class = @types.find do |type|
|
101
|
+
type.type == type_string
|
102
|
+
end
|
103
|
+
|
104
|
+
# Cache and return class
|
105
|
+
@types_cache[type_string] = type_class
|
106
|
+
return type_class
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.inflate_model(model_data, included)
|
110
|
+
# Find class
|
111
|
+
type_class = find_class(model_data)
|
112
|
+
raise "No type class found for #{model_data['type']}" unless type_class
|
113
|
+
|
114
|
+
# Get id and attributes needed for inflating
|
115
|
+
id = model_data["id"]
|
116
|
+
attributes = model_data["attributes"]
|
117
|
+
|
118
|
+
# Instantiate object and inflate relationships
|
119
|
+
relationships = model_data["relationships"] || []
|
120
|
+
type_instance = type_class.new(id, attributes)
|
121
|
+
type_instance = inflate_model_relationships(type_instance, relationships, included)
|
122
|
+
|
123
|
+
return type_instance
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.inflate_model_relationships(type_instance, relationships, included)
|
127
|
+
# Relationship attributes to set
|
128
|
+
attributes = {}
|
129
|
+
|
130
|
+
# 1. Iterate over relationships
|
131
|
+
# 2. Find id and type
|
132
|
+
# 3. Find matching id and type in included
|
133
|
+
# 4. Inflate matching data and set in attributes
|
134
|
+
relationships.each do |key, value|
|
135
|
+
# Validate data exists
|
136
|
+
value_data_or_datas = value["data"]
|
137
|
+
next unless value_data_or_datas
|
138
|
+
|
139
|
+
# Map an included data object
|
140
|
+
map_data = lambda do |value_data|
|
141
|
+
id = value_data["id"]
|
142
|
+
type = value_data["type"]
|
143
|
+
|
144
|
+
relationship_data = included.find do |included_data|
|
145
|
+
id == included_data["id"] && type == included_data["type"]
|
146
|
+
end
|
147
|
+
|
148
|
+
inflate_model(relationship_data, included)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Map a hash or an array of data
|
152
|
+
if value_data_or_datas.kind_of?(Hash)
|
153
|
+
attributes[key] = map_data.call(value_data_or_datas)
|
154
|
+
elsif value_data_or_datas.kind_of?(Array)
|
155
|
+
attributes[key] = value_data_or_datas.map(&map_data)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
type_instance.update_attributes(attributes)
|
160
|
+
|
161
|
+
return type_instance
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative './model'
|
2
|
+
module Spaceship
|
3
|
+
module ConnectAPI
|
4
|
+
class PreReleaseVersion
|
5
|
+
include Spaceship::ConnectAPI::Model
|
6
|
+
|
7
|
+
attr_accessor :version
|
8
|
+
attr_accessor :platform
|
9
|
+
|
10
|
+
attr_mapping({
|
11
|
+
"version" => "version",
|
12
|
+
"platform" => "platform"
|
13
|
+
})
|
14
|
+
|
15
|
+
def self.type
|
16
|
+
return "preReleaseVersions"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative './model'
|
2
|
+
module Spaceship
|
3
|
+
module ConnectAPI
|
4
|
+
class User
|
5
|
+
include Spaceship::ConnectAPI::Model
|
6
|
+
|
7
|
+
attr_accessor :username
|
8
|
+
attr_accessor :first_name
|
9
|
+
attr_accessor :last_name
|
10
|
+
attr_accessor :email
|
11
|
+
attr_accessor :preferred_currency_territory
|
12
|
+
attr_accessor :agreed_to_terms
|
13
|
+
attr_accessor :roles
|
14
|
+
attr_accessor :all_apps_visible
|
15
|
+
attr_accessor :provisioning_allowed
|
16
|
+
attr_accessor :email_vetting_required
|
17
|
+
attr_accessor :notifications
|
18
|
+
|
19
|
+
attr_mapping({
|
20
|
+
"username" => "username",
|
21
|
+
"firstName" => "first_name",
|
22
|
+
"lastName" => "last_name",
|
23
|
+
"email" => "email",
|
24
|
+
"preferredCurrencyTerritory" => "preferred_currency_territory",
|
25
|
+
"agreedToTerms" => "agreed_to_terms",
|
26
|
+
"roles" => "roles",
|
27
|
+
"allAppsVisible" => "all_apps_visible",
|
28
|
+
"provisioningAllowed" => "provisioning_allowed",
|
29
|
+
"emailVettingRequired" => "email_vetting_required",
|
30
|
+
"notifications" => "notifications"
|
31
|
+
})
|
32
|
+
|
33
|
+
def self.type
|
34
|
+
return "users"
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# API
|
39
|
+
#
|
40
|
+
|
41
|
+
def self.all(filter: {}, includes: nil, limit: nil, sort: nil)
|
42
|
+
return client.get_users(filter: filter, includes: includes)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.find(email: nil, includes: nil)
|
46
|
+
return all(filter: { email: email }, includes: includes)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative './base'
|
2
|
+
require_relative './models/model'
|
3
|
+
|
4
|
+
module Spaceship
|
5
|
+
module ConnectAPI
|
6
|
+
class Response
|
7
|
+
include Enumerable
|
8
|
+
attr_reader :body
|
9
|
+
attr_reader :status
|
10
|
+
|
11
|
+
def initialize(body: nil, status: nil)
|
12
|
+
@body = body
|
13
|
+
@status = status
|
14
|
+
end
|
15
|
+
|
16
|
+
def client
|
17
|
+
return Spaceship::ConnectAPI::Base.client
|
18
|
+
end
|
19
|
+
|
20
|
+
def next_url
|
21
|
+
return nil if body.nil?
|
22
|
+
links = body["links"] || {}
|
23
|
+
return links["next"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def next_page
|
27
|
+
url = next_url
|
28
|
+
return nil if url.nil?
|
29
|
+
return client.get(url)
|
30
|
+
end
|
31
|
+
|
32
|
+
def next_pages(count: 1)
|
33
|
+
if !count.nil? && count < 0
|
34
|
+
count = 0
|
35
|
+
end
|
36
|
+
|
37
|
+
responses = [self]
|
38
|
+
counter = 0
|
39
|
+
|
40
|
+
resp = self
|
41
|
+
loop do
|
42
|
+
resp = resp.next_page
|
43
|
+
break if resp.nil?
|
44
|
+
responses << resp
|
45
|
+
counter += 1
|
46
|
+
|
47
|
+
break if !count.nil? && counter >= count
|
48
|
+
end
|
49
|
+
|
50
|
+
return responses
|
51
|
+
end
|
52
|
+
|
53
|
+
def all_pages
|
54
|
+
return next_pages(count: nil)
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_models
|
58
|
+
return [] if body.nil?
|
59
|
+
model_or_models = Spaceship::ConnectAPI::Models.parse(body)
|
60
|
+
return [model_or_models].flatten
|
61
|
+
end
|
62
|
+
|
63
|
+
def each(&block)
|
64
|
+
to_models.each do |model|
|
65
|
+
yield(model)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'jwt'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
# extract pem from .p8
|
5
|
+
# openssl pkcs8 -topk8 -outform PEM -in AuthKey.p8 -out key.pem -nocrypt
|
6
|
+
|
7
|
+
# compute public key
|
8
|
+
# openssl ec -in key.pem -pubout -out public_key.pem -aes256
|
9
|
+
|
10
|
+
module Spaceship
|
11
|
+
module ConnectAPI
|
12
|
+
class Token
|
13
|
+
# maximum expiration supported by AppStore (20 minutes)
|
14
|
+
MAX_TOKEN_DURATION = 1200
|
15
|
+
|
16
|
+
attr_reader :key_id
|
17
|
+
attr_reader :issuer_id
|
18
|
+
attr_reader :text
|
19
|
+
|
20
|
+
def initialize(key_id: nil, issuer_id: nil, key: nil)
|
21
|
+
@expiration = Time.now + MAX_TOKEN_DURATION
|
22
|
+
@key_id = key_id
|
23
|
+
@key = key
|
24
|
+
@issuer_id = issuer_id
|
25
|
+
|
26
|
+
header = {
|
27
|
+
kid: key_id
|
28
|
+
}
|
29
|
+
|
30
|
+
payload = {
|
31
|
+
iss: issuer_id,
|
32
|
+
exp: @expiration.to_i,
|
33
|
+
aud: 'appstoreconnect-v1'
|
34
|
+
}
|
35
|
+
|
36
|
+
@text = JWT.encode(payload, key, 'ES256', header)
|
37
|
+
end
|
38
|
+
|
39
|
+
def expired?
|
40
|
+
@expiration < Time.now
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|