fastlane 2.29.0.beta.20170428010037 → 2.29.0.beta.20170429010036
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/deliver/lib/deliver/options.rb +2 -2
- data/fastlane/lib/fastlane/actions/crashlytics.rb +1 -1
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane_core/lib/fastlane_core/build_watcher.rb +39 -21
- data/fastlane_core/lib/fastlane_core/helper.rb +0 -5
- data/pilot/lib/pilot/options.rb +1 -1
- data/pilot/lib/pilot/tester_manager.rb +2 -36
- data/spaceship/lib/spaceship/test_flight/base.rb +12 -0
- data/spaceship/lib/spaceship/test_flight/build.rb +10 -6
- data/spaceship/lib/spaceship/test_flight/client.rb +93 -41
- data/spaceship/lib/spaceship/test_flight/group.rb +36 -5
- data/spaceship/lib/spaceship/test_flight/test_info.rb +4 -0
- metadata +27 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3651fba720d62f1e3f1c4ac3a153045521c06eb
|
4
|
+
data.tar.gz: 7d86e4038f6bd0f7adb34ed11f3937eb06306e69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0be189bdc70ba539c76274d43ee7289baa549acaa17cd9706eb9c425284d4fe541c895c2ff4e363f3b85e47d18471422a378a5dbb61620488cb1fa9875ac8d54
|
7
|
+
data.tar.gz: 8f9cef4e329780ed40035fcd2420e9b77e7a4548a1393efa1076ebac0d66ac6681c8f2ed85d3ea0cab1e85ea92ddd8dc4cadb49558fd7c0c2ebb0c3ed3d3a354
|
@@ -37,7 +37,7 @@ module Deliver
|
|
37
37
|
optional: true,
|
38
38
|
env_name: "DELIVER_IPA_PATH",
|
39
39
|
description: "Path to your ipa file",
|
40
|
-
default_value: Dir["*.ipa"].
|
40
|
+
default_value: Dir["*.ipa"].sort_by { |x| File.mtime(x) }.last,
|
41
41
|
verify_block: proc do |value|
|
42
42
|
UI.user_error!("Could not find ipa file at path '#{File.expand_path(value)}'") unless File.exist?(value)
|
43
43
|
UI.user_error!("'#{value}' doesn't seem to be an ipa file") unless value.end_with?(".ipa")
|
@@ -51,7 +51,7 @@ module Deliver
|
|
51
51
|
optional: true,
|
52
52
|
env_name: "DELIVER_PKG_PATH",
|
53
53
|
description: "Path to your pkg file",
|
54
|
-
default_value: Dir["*.pkg"].
|
54
|
+
default_value: Dir["*.pkg"].sort_by { |x| File.mtime(x) }.last,
|
55
55
|
verify_block: proc do |value|
|
56
56
|
UI.user_error!("Could not find pkg file at path '#{File.expand_path(value)}'") unless File.exist?(value)
|
57
57
|
UI.user_error!("'#{value}' doesn't seem to be a pkg file") unless value.end_with?(".pkg")
|
@@ -65,7 +65,7 @@ module Fastlane
|
|
65
65
|
platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
|
66
66
|
|
67
67
|
if platform == :ios or platform.nil?
|
68
|
-
ipa_path_default = Dir["*.ipa"].last
|
68
|
+
ipa_path_default = Dir["*.ipa"].sort_by { |x| File.mtime(x) }.last
|
69
69
|
end
|
70
70
|
|
71
71
|
if platform == :android
|
@@ -1,36 +1,54 @@
|
|
1
1
|
module FastlaneCore
|
2
2
|
class BuildWatcher
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
class << self
|
4
|
+
# @return The build we waited for. This method will always return a build
|
5
|
+
def wait_for_build_processing_to_be_complete(app_id: nil, platform: nil)
|
6
|
+
# First, find the train and build version we want to watch for
|
7
|
+
watched_build = watching_build(app_id: app_id, platform: platform)
|
8
|
+
UI.crash!("Could not find a build for app: #{app_id} on platform: #{platform}") if watched_build.nil?
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
+
loop do
|
11
|
+
matched_build = matching_build(watched_build: watched_build, app_id: app_id, platform: platform)
|
10
12
|
|
11
|
-
|
12
|
-
UI.message("Waiting for iTunes Connect to finish processing the new build (#{watching_build.train_version} - #{watching_build.build_version})")
|
13
|
+
report_status(build: matched_build)
|
13
14
|
|
15
|
+
if matched_build && matched_build.processed?
|
16
|
+
return matched_build
|
17
|
+
end
|
18
|
+
|
19
|
+
sleep 10
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def watching_build(app_id: nil, platform: nil)
|
26
|
+
processing_builds = Spaceship::TestFlight::Build.all_processing_builds(app_id: app_id, platform: platform)
|
27
|
+
|
28
|
+
watched_build = processing_builds.sort_by(&:upload_date).last
|
29
|
+
watched_build || Spaceship::TestFlight::Build.latest(app_id: app_id, platform: platform)
|
30
|
+
end
|
31
|
+
|
32
|
+
def matching_build(watched_build: nil, app_id: nil, platform: nil)
|
33
|
+
matched_builds = Spaceship::TestFlight::Build.builds_for_train(app_id: app_id, platform: platform, train_version: watched_build.train_version)
|
34
|
+
matched_builds.find { |build| build.build_version == watched_build.build_version }
|
35
|
+
end
|
36
|
+
|
37
|
+
def report_status(build: nil)
|
14
38
|
# Due to iTunes Connect, builds disappear from the build list alltogether
|
15
39
|
# after they finished processing. Before returning this build, we have to
|
16
40
|
# wait for the build to appear in the build list again
|
17
41
|
# As this method is very often used to wait for a build, and then do something
|
18
42
|
# with it, we have to be sure that the build actually is ready
|
19
|
-
|
20
|
-
matching_builds = Spaceship::TestFlight::Build.builds_for_train(app_id: app_id, platform: platform, train_version: watching_build.train_version)
|
21
|
-
matching_build = matching_builds.find { |build| build.build_version == watching_build.build_version }
|
22
|
-
|
23
|
-
if matching_build.nil?
|
43
|
+
if build.nil?
|
24
44
|
UI.message("Build doesn't show up in the build list any more, waiting for it to appear again")
|
25
|
-
elsif
|
26
|
-
UI.success("Build #{
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
45
|
+
elsif build.active?
|
46
|
+
UI.success("Build #{build.train_version} - #{build.build_version} is already being tested")
|
47
|
+
elsif build.ready_to_submit? || build.export_compliance_missing?
|
48
|
+
UI.success("Successfully finished processing the build #{build.train_version} - #{build.build_version}")
|
49
|
+
else
|
50
|
+
UI.message("Waiting for iTunes Connect to finish processing the new build (#{build.train_version} - #{build.build_version})")
|
31
51
|
end
|
32
|
-
|
33
|
-
sleep 10
|
34
52
|
end
|
35
53
|
end
|
36
54
|
end
|
@@ -118,11 +118,6 @@ module FastlaneCore
|
|
118
118
|
FastlaneCore::Env.truthy?("TERM_PROGRAM_VERSION")
|
119
119
|
end
|
120
120
|
|
121
|
-
# Does the user use iTerm?
|
122
|
-
def self.iterm?
|
123
|
-
FastlaneCore::Env.truthy?("ITERM_SESSION_ID")
|
124
|
-
end
|
125
|
-
|
126
121
|
# Logs base directory
|
127
122
|
def self.buildlog_path
|
128
123
|
return ENV["FL_BUILDLOG_PATH"] || "~/Library/Logs"
|
data/pilot/lib/pilot/options.rb
CHANGED
@@ -32,7 +32,7 @@ module Pilot
|
|
32
32
|
optional: true,
|
33
33
|
env_name: "PILOT_IPA",
|
34
34
|
description: "Path to the ipa file to upload",
|
35
|
-
default_value: Dir["*.ipa"].
|
35
|
+
default_value: Dir["*.ipa"].sort_by { |x| File.mtime(x) }.last,
|
36
36
|
verify_block: proc do |value|
|
37
37
|
UI.user_error!("Could not find ipa file at path '#{value}'") unless File.exist? value
|
38
38
|
UI.user_error!("'#{value}' doesn't seem to be an ipa file") unless value.end_with? ".ipa"
|
@@ -13,7 +13,7 @@ module Pilot
|
|
13
13
|
tester = find_or_create_tester(email: config[:email], first_name: config[:first_name], last_name: config[:last_name])
|
14
14
|
|
15
15
|
begin
|
16
|
-
groups = add_tester_to_groups!(tester: tester, app: app, groups: config[:groups])
|
16
|
+
groups = Spaceship::TestFlight::Group.add_tester_to_groups!(tester: tester, app: app, groups: config[:groups])
|
17
17
|
if tester.kind_of?(Spaceship::Tunes::Tester::Internal)
|
18
18
|
UI.success("Successfully added tester to app #{app.name}")
|
19
19
|
else
|
@@ -59,7 +59,7 @@ module Pilot
|
|
59
59
|
test_flight_tester.remove_from_app!(app_id: app.apple_id)
|
60
60
|
UI.success("Successfully removed tester, #{test_flight_tester.email}, from app: #{app.name}")
|
61
61
|
else
|
62
|
-
groups = remove_tester_from_groups!(tester: tester, app: app, groups: config[:groups])
|
62
|
+
groups = Spaceship::TestFlight::Group.remove_tester_from_groups!(tester: tester, app: app, groups: config[:groups])
|
63
63
|
group_names = groups.map(&:name).join(", ")
|
64
64
|
UI.success("Successfully removed tester #{tester.email} from app #{app.name} in group(s) #{group_names}")
|
65
65
|
end
|
@@ -109,40 +109,6 @@ module Pilot
|
|
109
109
|
raise ex
|
110
110
|
end
|
111
111
|
|
112
|
-
def perform_for_groups_in_app(app: nil, groups: nil, &block)
|
113
|
-
if groups.nil?
|
114
|
-
default_external_group = app.default_external_group
|
115
|
-
if default_external_group.nil?
|
116
|
-
UI.user_error!("The app #{app.name} does not have a default external group. Please make sure to pass group names to the `:groups` option.")
|
117
|
-
end
|
118
|
-
test_flight_groups = [default_external_group]
|
119
|
-
else
|
120
|
-
test_flight_groups = Spaceship::TestFlight::Group.filter_groups(app_id: app.apple_id) do |group|
|
121
|
-
groups.include?(group.name)
|
122
|
-
end
|
123
|
-
|
124
|
-
UI.user_error!("There are no groups available matching the names passed to the `:groups` option.") if test_flight_groups.empty?
|
125
|
-
end
|
126
|
-
|
127
|
-
test_flight_groups.each(&block)
|
128
|
-
end
|
129
|
-
|
130
|
-
def add_tester_to_groups!(tester: nil, app: nil, groups: nil)
|
131
|
-
if tester.kind_of?(Spaceship::Tunes::Tester::Internal)
|
132
|
-
Spaceship::TestFlight::Group.internal_group(app_id: app.apple_id).add_tester!(tester)
|
133
|
-
else
|
134
|
-
perform_for_groups_in_app(app: app, groups: groups) { |group| group.add_tester!(tester) }
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def remove_tester_from_groups!(tester: nil, app: nil, groups: nil)
|
139
|
-
if tester.kind_of?(Spaceship::Tunes::Tester::Internal)
|
140
|
-
Spaceship::TestFlight::Group.internal_group(app_id: app.apple_id).remove_tester!(tester)
|
141
|
-
else
|
142
|
-
perform_for_groups_in_app(app: app, groups: groups) { |group| group.remove_tester!(tester) }
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
112
|
def list_testers_by_app(app_filter)
|
147
113
|
app = Spaceship::Application.find(app_filter)
|
148
114
|
UI.user_error!("Couldn't find app with '#{app_filter}'") unless app
|
@@ -4,6 +4,18 @@ module Spaceship::TestFlight
|
|
4
4
|
@client ||= Client.client_with_authorization_from(Spaceship::Tunes.client)
|
5
5
|
end
|
6
6
|
|
7
|
+
##
|
8
|
+
# Have subclasses inherit the client from their superclass
|
9
|
+
#
|
10
|
+
# Essentially, we are making a class-inheritable-accessor as described here:
|
11
|
+
# https://apidock.com/rails/v4.2.7/Class/class_attribute
|
12
|
+
def self.inherited(subclass)
|
13
|
+
this_class = self
|
14
|
+
subclass.define_singleton_method(:client) do
|
15
|
+
this_class.client
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
7
19
|
def to_json
|
8
20
|
raw_data.to_json
|
9
21
|
end
|
@@ -72,12 +72,12 @@ module Spaceship::TestFlight
|
|
72
72
|
export_compliance_missing: 'testflight.build.state.export.compliance.missing'
|
73
73
|
}
|
74
74
|
|
75
|
-
# Find a Build by `build_id`.
|
75
|
+
# Find a Build by `build_id`.
|
76
76
|
#
|
77
77
|
# @return (Spaceship::TestFlight::Build)
|
78
78
|
def self.find(app_id: nil, build_id: nil)
|
79
79
|
attrs = client.get_build(app_id: app_id, build_id: build_id)
|
80
|
-
self.new(attrs)
|
80
|
+
self.new(attrs)
|
81
81
|
end
|
82
82
|
|
83
83
|
def self.all(app_id: nil, platform: nil)
|
@@ -105,7 +105,7 @@ module Spaceship::TestFlight
|
|
105
105
|
#
|
106
106
|
# Note: this will overwrite any non-saved changes to the object
|
107
107
|
#
|
108
|
-
# @return (
|
108
|
+
# @return (Spaceship::Base::DataHash) the raw_data of the build.
|
109
109
|
def reload
|
110
110
|
self.raw_data = self.class.find(app_id: app_id, build_id: id).raw_data
|
111
111
|
end
|
@@ -130,6 +130,10 @@ module Spaceship::TestFlight
|
|
130
130
|
external_state == BUILD_STATES[:export_compliance_missing]
|
131
131
|
end
|
132
132
|
|
133
|
+
def self.processed?
|
134
|
+
active? || ready_to_submit? || export_compliance_missing?
|
135
|
+
end
|
136
|
+
|
133
137
|
# Getting builds from BuildTrains only gets a partial Build object
|
134
138
|
# We are then requesting the full build from iTC when we need to access
|
135
139
|
# any of the variables below, because they are not inlcuded in the partial Build objects
|
@@ -164,9 +168,9 @@ module Spaceship::TestFlight
|
|
164
168
|
end
|
165
169
|
|
166
170
|
def update_build_information!(description: nil, feedback_email: nil, whats_new: nil)
|
167
|
-
test_info.description = description
|
168
|
-
test_info.feedback_email = feedback_email
|
169
|
-
test_info.whats_new = whats_new
|
171
|
+
test_info.description = description if description
|
172
|
+
test_info.feedback_email = feedback_email if feedback_email
|
173
|
+
test_info.whats_new = whats_new if whats_new
|
170
174
|
save!
|
171
175
|
end
|
172
176
|
|
@@ -1,20 +1,34 @@
|
|
1
1
|
module Spaceship::TestFlight
|
2
2
|
class Client < Spaceship::Client
|
3
|
+
##
|
4
|
+
# Spaceship HTTP client for the testflight API.
|
5
|
+
#
|
6
|
+
# This client is solely responsible for the making HTTP requests and
|
7
|
+
# parsing their responses. Parameters should be either named parameters, or
|
8
|
+
# for large request data bodies, pass in anything that can resond to
|
9
|
+
# `to_json`.
|
10
|
+
#
|
11
|
+
# Each request method should validate the required parameters. A required parameter is one that would result in 400-range response if it is not supplied.
|
12
|
+
# Each request method should make only one request. For more high-level logic, put code in the data models.
|
13
|
+
|
3
14
|
def self.hostname
|
4
15
|
'https://itunesconnect.apple.com/testflight/v2/'
|
5
16
|
end
|
6
17
|
|
18
|
+
##
|
19
|
+
# @!group Build trains API
|
20
|
+
##
|
21
|
+
|
7
22
|
# Returns an array of all available build trains (not the builds they include)
|
8
|
-
def get_build_trains(app_id: nil, platform:
|
23
|
+
def get_build_trains(app_id: nil, platform: "ios")
|
9
24
|
assert_required_params(__method__, binding)
|
10
|
-
|
25
|
+
|
11
26
|
response = request(:get, "providers/#{team_id}/apps/#{app_id}/platforms/#{platform}/trains")
|
12
27
|
handle_response(response)
|
13
28
|
end
|
14
29
|
|
15
|
-
def get_builds_for_train(app_id: nil, platform:
|
30
|
+
def get_builds_for_train(app_id: nil, platform: "ios", train_version: nil)
|
16
31
|
assert_required_params(__method__, binding)
|
17
|
-
platform ||= "ios"
|
18
32
|
|
19
33
|
response = request(:get, "providers/#{team_id}/apps/#{app_id}/platforms/#{platform}/trains/#{train_version}/builds")
|
20
34
|
handle_response(response)
|
@@ -34,8 +48,72 @@ module Spaceship::TestFlight
|
|
34
48
|
handle_response(response)
|
35
49
|
end
|
36
50
|
|
51
|
+
##
|
52
|
+
# @!group Builds API
|
53
|
+
##
|
54
|
+
|
55
|
+
def get_build(app_id: nil, build_id: nil)
|
56
|
+
assert_required_params(__method__, binding)
|
57
|
+
|
58
|
+
response = request(:get, "providers/#{team_id}/apps/#{app_id}/builds/#{build_id}")
|
59
|
+
handle_response(response)
|
60
|
+
end
|
61
|
+
|
62
|
+
def put_build(app_id: nil, build_id: nil, build: nil)
|
63
|
+
assert_required_params(__method__, binding)
|
64
|
+
|
65
|
+
response = request(:put) do |req|
|
66
|
+
req.url "providers/#{team_id}/apps/#{app_id}/builds/#{build_id}"
|
67
|
+
req.body = build.to_json
|
68
|
+
req.headers['Content-Type'] = 'application/json'
|
69
|
+
end
|
70
|
+
handle_response(response)
|
71
|
+
end
|
72
|
+
|
73
|
+
def post_for_testflight_review(app_id: nil, build_id: nil, build: nil)
|
74
|
+
assert_required_params(__method__, binding)
|
75
|
+
|
76
|
+
response = request(:post) do |req|
|
77
|
+
req.url "providers/#{team_id}/apps/#{app_id}/builds/#{build_id}/review"
|
78
|
+
req.body = build.to_json
|
79
|
+
req.headers['Content-Type'] = 'application/json'
|
80
|
+
end
|
81
|
+
handle_response(response)
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# @!group Groups API
|
86
|
+
##
|
87
|
+
|
88
|
+
def get_groups(app_id: nil)
|
89
|
+
assert_required_params(__method__, binding)
|
90
|
+
|
91
|
+
response = request(:get, "/testflight/v2/providers/#{team_id}/apps/#{app_id}/groups")
|
92
|
+
handle_response(response)
|
93
|
+
end
|
94
|
+
|
95
|
+
def add_group_to_build(app_id: nil, group_id: nil, build_id: nil)
|
96
|
+
assert_required_params(__method__, binding)
|
97
|
+
|
98
|
+
body = {
|
99
|
+
'groupId' => group_id,
|
100
|
+
'buildId' => build_id
|
101
|
+
}
|
102
|
+
response = request(:put) do |req|
|
103
|
+
req.url "providers/#{team_id}/apps/#{app_id}/groups/#{group_id}/builds/#{build_id}"
|
104
|
+
req.body = body.to_json
|
105
|
+
req.headers['Content-Type'] = 'application/json'
|
106
|
+
end
|
107
|
+
handle_response(response)
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# @!group Testers API
|
112
|
+
##
|
113
|
+
|
37
114
|
def post_tester(app_id: nil, tester: nil)
|
38
115
|
assert_required_params(__method__, binding)
|
116
|
+
|
39
117
|
url = "providers/#{team_id}/apps/#{app_id}/testers"
|
40
118
|
response = request(:post) do |req|
|
41
119
|
req.url url
|
@@ -51,6 +129,7 @@ module Spaceship::TestFlight
|
|
51
129
|
|
52
130
|
def put_tester_to_group(app_id: nil, tester_id: nil, group_id: nil)
|
53
131
|
assert_required_params(__method__, binding)
|
132
|
+
|
54
133
|
# Then we can add the tester to the group that allows the app to test
|
55
134
|
# This is easy enough, we already have all this data. We don't need any response from the previous request
|
56
135
|
url = "providers/#{team_id}/apps/#{app_id}/groups/#{group_id}/testers/#{tester_id}"
|
@@ -67,6 +146,7 @@ module Spaceship::TestFlight
|
|
67
146
|
|
68
147
|
def delete_tester_from_group(group_id: nil, tester_id: nil, app_id: nil)
|
69
148
|
assert_required_params(__method__, binding)
|
149
|
+
|
70
150
|
url = "providers/#{team_id}/apps/#{app_id}/groups/#{group_id}/testers/#{tester_id}"
|
71
151
|
response = request(:delete) do |req|
|
72
152
|
req.url url
|
@@ -75,53 +155,25 @@ module Spaceship::TestFlight
|
|
75
155
|
handle_response(response)
|
76
156
|
end
|
77
157
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
handle_response(response)
|
82
|
-
end
|
158
|
+
##
|
159
|
+
# @!group TestInfo
|
160
|
+
##
|
83
161
|
|
84
|
-
def
|
162
|
+
def put_testinfo(app_id: nil, testinfo: nil)
|
85
163
|
assert_required_params(__method__, binding)
|
86
|
-
response = request(:put) do |req|
|
87
|
-
req.url "providers/#{team_id}/apps/#{app_id}/builds/#{build_id}"
|
88
|
-
req.body = build.to_json
|
89
|
-
req.headers['Content-Type'] = 'application/json'
|
90
|
-
end
|
91
|
-
handle_response(response)
|
92
|
-
end
|
93
164
|
|
94
|
-
def post_for_testflight_review(app_id: nil, build_id: nil, build: nil)
|
95
|
-
assert_required_params(__method__, binding)
|
96
|
-
response = request(:post) do |req|
|
97
|
-
req.url "providers/#{team_id}/apps/#{app_id}/builds/#{build_id}/review"
|
98
|
-
req.body = build.to_json
|
99
|
-
req.headers['Content-Type'] = 'application/json'
|
100
|
-
end
|
101
|
-
handle_response(response)
|
102
|
-
end
|
103
|
-
|
104
|
-
def get_groups(app_id: nil)
|
105
|
-
assert_required_params(__method__, binding)
|
106
|
-
response = request(:get, "/testflight/v2/providers/#{team_id}/apps/#{app_id}/groups")
|
107
|
-
handle_response(response)
|
108
|
-
end
|
109
|
-
|
110
|
-
def add_group_to_build(app_id: nil, group_id: nil, build_id: nil)
|
111
|
-
body = {
|
112
|
-
'groupId' => group_id,
|
113
|
-
'buildId' => build_id
|
114
|
-
}
|
115
165
|
response = request(:put) do |req|
|
116
|
-
req.url "providers/#{team_id}/apps/#{app_id}/
|
117
|
-
req.body =
|
166
|
+
req.url "providers/#{team_id}/apps/#{app_id}/testInfo"
|
167
|
+
req.body = testinfo.to_json
|
118
168
|
req.headers['Content-Type'] = 'application/json'
|
119
169
|
end
|
120
170
|
handle_response(response)
|
121
171
|
end
|
122
172
|
|
173
|
+
protected
|
174
|
+
|
123
175
|
def handle_response(response)
|
124
|
-
if (200
|
176
|
+
if (200...300).cover?(response.status) && (response.body.nil? || response.body.empty?)
|
125
177
|
return
|
126
178
|
end
|
127
179
|
|
@@ -11,16 +11,13 @@ module Spaceship::TestFlight
|
|
11
11
|
'id' => :id,
|
12
12
|
'name' => :name,
|
13
13
|
'isInternalGroup' => :is_internal_group,
|
14
|
+
'appAdamId' => :app_id,
|
14
15
|
'isDefaultExternalGroup' => :is_default_external_group
|
15
16
|
})
|
16
17
|
|
17
18
|
def self.all(app_id: nil)
|
18
19
|
groups = client.get_groups(app_id: app_id)
|
19
|
-
groups.map
|
20
|
-
current_element = self.new(g)
|
21
|
-
current_element.app_id = app_id
|
22
|
-
current_element
|
23
|
-
end
|
20
|
+
groups.map { |g| self.new(g) }
|
24
21
|
end
|
25
22
|
|
26
23
|
def self.find(app_id: nil, group_name: nil)
|
@@ -59,6 +56,22 @@ module Spaceship::TestFlight
|
|
59
56
|
client.delete_tester_from_group(group_id: self.id, tester_id: tester.tester_id, app_id: self.app_id)
|
60
57
|
end
|
61
58
|
|
59
|
+
def self.add_tester_to_groups!(tester: nil, app: nil, groups: nil)
|
60
|
+
if tester.kind_of?(Spaceship::Tunes::Tester::Internal)
|
61
|
+
self.internal_group(app_id: app.apple_id).add_tester!(tester)
|
62
|
+
else
|
63
|
+
self.perform_for_groups_in_app(app: app, groups: groups) { |group| group.add_tester!(tester) }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.remove_tester_from_groups!(tester: nil, app: nil, groups: nil)
|
68
|
+
if tester.kind_of?(Spaceship::Tunes::Tester::Internal)
|
69
|
+
self.internal_group(app_id: app.apple_id).remove_tester!(tester)
|
70
|
+
else
|
71
|
+
self.perform_for_groups_in_app(app: app, groups: groups) { |group| group.remove_tester!(tester) }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
62
75
|
def default_external_group?
|
63
76
|
is_default_external_group
|
64
77
|
end
|
@@ -66,5 +79,23 @@ module Spaceship::TestFlight
|
|
66
79
|
def internal_group?
|
67
80
|
is_internal_group
|
68
81
|
end
|
82
|
+
|
83
|
+
def self.perform_for_groups_in_app(app: nil, groups: nil, &block)
|
84
|
+
if groups.nil?
|
85
|
+
default_external_group = app.default_external_group
|
86
|
+
if default_external_group.nil?
|
87
|
+
UI.user_error!("The app #{app.name} does not have a default external group. Please make sure to pass group names to the `:groups` option.")
|
88
|
+
end
|
89
|
+
test_flight_groups = [default_external_group]
|
90
|
+
else
|
91
|
+
test_flight_groups = self.filter_groups(app_id: app.apple_id) do |group|
|
92
|
+
groups.include?(group.name)
|
93
|
+
end
|
94
|
+
|
95
|
+
UI.user_error!("There are no groups available matching the names passed to the `:groups` option.") if test_flight_groups.empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
test_flight_groups.each(&block)
|
99
|
+
end
|
69
100
|
end
|
70
101
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.29.0.beta.
|
4
|
+
version: 2.29.0.beta.20170429010036
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felix Krause
|
@@ -15,7 +15,7 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date: 2017-04-
|
18
|
+
date: 2017-04-29 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: slack-notifier
|
@@ -743,6 +743,20 @@ dependencies:
|
|
743
743
|
- - "~>"
|
744
744
|
- !ruby/object:Gem::Version
|
745
745
|
version: 0.8.1
|
746
|
+
- !ruby/object:Gem::Dependency
|
747
|
+
name: sinatra
|
748
|
+
requirement: !ruby/object:Gem::Requirement
|
749
|
+
requirements:
|
750
|
+
- - "~>"
|
751
|
+
- !ruby/object:Gem::Version
|
752
|
+
version: 1.4.8
|
753
|
+
type: :development
|
754
|
+
prerelease: false
|
755
|
+
version_requirements: !ruby/object:Gem::Requirement
|
756
|
+
requirements:
|
757
|
+
- - "~>"
|
758
|
+
- !ruby/object:Gem::Version
|
759
|
+
version: 1.4.8
|
746
760
|
description: The easiest way to automate beta deployments and releases for your iOS
|
747
761
|
and Android apps
|
748
762
|
email:
|
@@ -1342,23 +1356,23 @@ metadata:
|
|
1342
1356
|
post_install_message:
|
1343
1357
|
rdoc_options: []
|
1344
1358
|
require_paths:
|
1345
|
-
-
|
1346
|
-
- deliver/lib
|
1347
|
-
- spaceship/lib
|
1348
|
-
- supply/lib
|
1349
|
-
- screengrab/lib
|
1350
|
-
- cert/lib
|
1351
|
-
- pilot/lib
|
1352
|
-
- sigh/lib
|
1359
|
+
- fastlane/lib
|
1353
1360
|
- scan/lib
|
1354
|
-
-
|
1361
|
+
- gym/lib
|
1362
|
+
- screengrab/lib
|
1355
1363
|
- snapshot/lib
|
1364
|
+
- supply/lib
|
1356
1365
|
- match/lib
|
1357
1366
|
- pem/lib
|
1358
|
-
-
|
1367
|
+
- spaceship/lib
|
1359
1368
|
- produce/lib
|
1360
|
-
-
|
1369
|
+
- sigh/lib
|
1361
1370
|
- fastlane_core/lib
|
1371
|
+
- frameit/lib
|
1372
|
+
- pilot/lib
|
1373
|
+
- deliver/lib
|
1374
|
+
- credentials_manager/lib
|
1375
|
+
- cert/lib
|
1362
1376
|
required_ruby_version: !ruby/object:Gem::Requirement
|
1363
1377
|
requirements:
|
1364
1378
|
- - ">="
|