pilot 0.1.7 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pilot/build_manager.rb +54 -51
- data/lib/pilot/commands_generator.rb +17 -13
- data/lib/pilot/manager.rb +5 -6
- data/lib/pilot/options.rb +10 -20
- data/lib/pilot/package_builder.rb +11 -10
- data/lib/pilot/tester_exporter.rb +5 -5
- data/lib/pilot/tester_importer.rb +2 -3
- data/lib/pilot/tester_manager.rb +47 -50
- data/lib/pilot/tester_util.rb +23 -0
- data/lib/pilot/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2daff1b9410811bcefce3463946c8d5fd431f25
|
4
|
+
data.tar.gz: 2e7ed79218abbb987b039872a30e81df48f5c23b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4289b34303f3c9fe3fb00b297b7963a27023bb1266a7fd6fd1a71d18a4acf79617faf8f6f376fbc67264ab0eb3dad882743d628ef794ba175496add1d773f355
|
7
|
+
data.tar.gz: 05acaec2f491065cb17f3a78b7678e3c76569b09a7355c85e3641701c2b85790d38fa59f04340cc7d1b61a2f02ff78e4d486bc964bea22841827e6e438d38b48
|
data/lib/pilot/build_manager.rb
CHANGED
@@ -5,7 +5,7 @@ module Pilot
|
|
5
5
|
|
6
6
|
Helper.log.info "Ready to upload new build to TestFlight (App: #{app.apple_id})...".green
|
7
7
|
|
8
|
-
package_path = PackageBuilder.new.generate(apple_id: app.apple_id,
|
8
|
+
package_path = PackageBuilder.new.generate(apple_id: app.apple_id,
|
9
9
|
ipa_path: config[:ipa],
|
10
10
|
package_path: "/tmp")
|
11
11
|
|
@@ -32,8 +32,10 @@ module Pilot
|
|
32
32
|
config[:app_identifier] = ask("App Identifier: ")
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
builds = app.all_processing_builds + app.builds
|
36
|
+
# sort by upload_date
|
37
|
+
builds.sort! {|a, b| a.upload_date <=> b.upload_date }
|
38
|
+
rows = builds.collect { |build| describe_build(build) }
|
37
39
|
|
38
40
|
puts Terminal::Table.new(
|
39
41
|
title: "#{app.name} Builds".green,
|
@@ -43,60 +45,61 @@ module Pilot
|
|
43
45
|
end
|
44
46
|
|
45
47
|
private
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
|
49
|
+
def describe_build(build)
|
50
|
+
row = [build.train_version,
|
51
|
+
build.build_version,
|
52
|
+
build.testing_status,
|
53
|
+
build.install_count,
|
54
|
+
build.session_count]
|
55
|
+
|
56
|
+
return row
|
57
|
+
end
|
58
|
+
|
59
|
+
# This method will takes care of checking for the processing builds every few seconds
|
60
|
+
# @return [Integer] The upload date
|
61
|
+
def wait_for_processing_build
|
62
|
+
# the upload date of the new buid
|
63
|
+
# we use it to identify the build
|
64
|
+
upload_date = nil
|
65
|
+
loop do
|
66
|
+
Helper.log.info "Waiting for iTunes Connect to process the new build"
|
67
|
+
sleep 5
|
68
|
+
builds = app.all_processing_builds
|
69
|
+
break if builds.count == 0
|
70
|
+
upload_date = builds.last.upload_date
|
54
71
|
end
|
55
72
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
if upload_date
|
74
|
+
Helper.log.info "Build successfully processed by iTunes Connect".green
|
75
|
+
return upload_date
|
76
|
+
else
|
77
|
+
raise "Error: Seems like iTunes Connect didn't properly pre-process the binary".red
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def distribute_build(upload_date)
|
82
|
+
Helper.log.info "Distributing new build to testers"
|
83
|
+
|
84
|
+
# We try this multiple times, as it sometimes takes some time
|
85
|
+
# to process the binary
|
86
|
+
10.times do
|
87
|
+
current_build = app.builds.find do |build|
|
88
|
+
build.upload_date == upload_date
|
68
89
|
end
|
69
90
|
|
70
|
-
if
|
71
|
-
|
72
|
-
return
|
91
|
+
if current_build
|
92
|
+
current_build.build_train.update_testing_status!(true)
|
93
|
+
return true
|
73
94
|
else
|
74
|
-
|
95
|
+
Helper.log.info "Binary is not yet available online..."
|
96
|
+
sleep 5
|
75
97
|
end
|
76
98
|
end
|
77
99
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# to process the binary
|
83
|
-
10.times do
|
84
|
-
current_build = app.builds.find do |build|
|
85
|
-
build.upload_date == upload_date
|
86
|
-
end
|
87
|
-
|
88
|
-
if current_build
|
89
|
-
current_build.build_train.update_testing_status!(true)
|
90
|
-
return true
|
91
|
-
else
|
92
|
-
Helper.log.info "Binary is not yet available online..."
|
93
|
-
sleep 5
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
Helper.log.error "Build is not visible on iTunes Connect any more - couldn't distribute to testers.".red
|
98
|
-
Helper.log.error "You can run `pilot --skip_submission` to only upload the binary without distributing.".red
|
99
|
-
raise "Error distributing the binary"
|
100
|
-
end
|
100
|
+
Helper.log.error "Build is not visible on iTunes Connect any more - couldn't distribute to testers.".red
|
101
|
+
Helper.log.error "You can run `pilot --skip_submission` to only upload the binary without distributing.".red
|
102
|
+
raise "Error distributing the binary"
|
103
|
+
end
|
101
104
|
end
|
102
|
-
end
|
105
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# rubocop:disable Metrics/MethodLength
|
2
|
+
# rubocop:disable Metrics/AbcSize
|
1
3
|
require "commander"
|
2
4
|
require "pilot/options"
|
3
5
|
require "fastlane_core"
|
@@ -23,8 +25,8 @@ module Pilot
|
|
23
25
|
o
|
24
26
|
end
|
25
27
|
|
26
|
-
def handle_email(config,
|
27
|
-
config[:email] ||=
|
28
|
+
def handle_email(config, args)
|
29
|
+
config[:email] ||= args.first
|
28
30
|
config[:email] ||= ask("Email address of the tester: ".yellow)
|
29
31
|
end
|
30
32
|
|
@@ -41,7 +43,7 @@ module Pilot
|
|
41
43
|
command :upload do |c|
|
42
44
|
c.syntax = "pilot upload"
|
43
45
|
c.description = "Uploads a new binary to Apple TestFlight"
|
44
|
-
c.action do |
|
46
|
+
c.action do |args, options|
|
45
47
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
46
48
|
Pilot::BuildManager.new.upload(config)
|
47
49
|
end
|
@@ -50,7 +52,7 @@ module Pilot
|
|
50
52
|
command :builds do |c|
|
51
53
|
c.syntax = "pilot builds"
|
52
54
|
c.description = "Lists all builds for given application"
|
53
|
-
c.action do |
|
55
|
+
c.action do |args, options|
|
54
56
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
55
57
|
Pilot::BuildManager.new.list(config)
|
56
58
|
end
|
@@ -59,9 +61,9 @@ module Pilot
|
|
59
61
|
command :add do |c|
|
60
62
|
c.syntax = "pilot add"
|
61
63
|
c.description = "Adds a new external tester to a specific app (if given). This will also add an existing tester to an app."
|
62
|
-
c.action do |
|
64
|
+
c.action do |args, options|
|
63
65
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
64
|
-
handle_email(config,
|
66
|
+
handle_email(config, args)
|
65
67
|
Pilot::TesterManager.new.add_tester(config)
|
66
68
|
end
|
67
69
|
end
|
@@ -69,7 +71,7 @@ module Pilot
|
|
69
71
|
command :list do |c|
|
70
72
|
c.syntax = "pilot list"
|
71
73
|
c.description = "Lists all registered testers, both internal and external"
|
72
|
-
c.action do |
|
74
|
+
c.action do |args, options|
|
73
75
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
74
76
|
Pilot::TesterManager.new.list_testers(config)
|
75
77
|
end
|
@@ -78,9 +80,9 @@ module Pilot
|
|
78
80
|
command :find do |c|
|
79
81
|
c.syntax = "pilot find"
|
80
82
|
c.description = "Find a tester (internal or external) by their email address"
|
81
|
-
c.action do |
|
83
|
+
c.action do |args, options|
|
82
84
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
83
|
-
handle_email(config,
|
85
|
+
handle_email(config, args)
|
84
86
|
Pilot::TesterManager.new.find_tester(config)
|
85
87
|
end
|
86
88
|
end
|
@@ -88,9 +90,9 @@ module Pilot
|
|
88
90
|
command :remove do |c|
|
89
91
|
c.syntax = "pilot remove"
|
90
92
|
c.description = "Remove an external tester by their email address"
|
91
|
-
c.action do |
|
93
|
+
c.action do |args, options|
|
92
94
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
93
|
-
handle_email(config,
|
95
|
+
handle_email(config, args)
|
94
96
|
Pilot::TesterManager.new.remove_tester(config)
|
95
97
|
end
|
96
98
|
end
|
@@ -98,7 +100,7 @@ module Pilot
|
|
98
100
|
command :export do |c|
|
99
101
|
c.syntax = "pilot export"
|
100
102
|
c.description = "Exports all external testers to a CSV file"
|
101
|
-
c.action do |
|
103
|
+
c.action do |args, options|
|
102
104
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
103
105
|
Pilot::TesterExporter.new.export_testers(config)
|
104
106
|
end
|
@@ -107,7 +109,7 @@ module Pilot
|
|
107
109
|
command :import do |c|
|
108
110
|
c.syntax = "pilot import"
|
109
111
|
c.description = "Create external testers from a CSV file"
|
110
|
-
c.action do |
|
112
|
+
c.action do |args, options|
|
111
113
|
config = FastlaneCore::Configuration.create(Pilot::Options.available_options, convert_options(options))
|
112
114
|
Pilot::TesterImporter.new.import_testers(config)
|
113
115
|
end
|
@@ -119,3 +121,5 @@ module Pilot
|
|
119
121
|
end
|
120
122
|
end
|
121
123
|
end
|
124
|
+
# rubocop:enable Metrics/MethodLength
|
125
|
+
# rubocop:enable Metrics/AbcSize
|
data/lib/pilot/manager.rb
CHANGED
@@ -20,16 +20,15 @@ module Pilot
|
|
20
20
|
def app
|
21
21
|
@apple_id ||= fetch_app_id
|
22
22
|
|
23
|
-
|
23
|
+
@app ||= Spaceship::Application.find(@apple_id)
|
24
|
+
unless @app
|
24
25
|
raise "Could not find app with #{(config[:apple_id] || config[:app_identifier])}"
|
25
26
|
end
|
26
27
|
return @app
|
27
28
|
end
|
28
29
|
|
29
|
-
# Access the current configuration
|
30
|
-
|
31
|
-
@config
|
32
|
-
end
|
30
|
+
# Access the current configuration
|
31
|
+
attr_reader :config
|
33
32
|
|
34
33
|
# Config Related
|
35
34
|
################
|
@@ -56,4 +55,4 @@ module Pilot
|
|
56
55
|
return result
|
57
56
|
end
|
58
57
|
end
|
59
|
-
end
|
58
|
+
end
|
data/lib/pilot/options.rb
CHANGED
@@ -4,7 +4,7 @@ require "credentials_manager"
|
|
4
4
|
module Pilot
|
5
5
|
class Options
|
6
6
|
def self.available_options
|
7
|
-
|
7
|
+
@options ||= [
|
8
8
|
FastlaneCore::ConfigItem.new(key: :username,
|
9
9
|
short_option: "-u",
|
10
10
|
env_name: "PILOT_USERNAME",
|
@@ -16,8 +16,8 @@ module Pilot
|
|
16
16
|
description: "Path to the ipa file to upload",
|
17
17
|
default_value: Dir["*.ipa"].first,
|
18
18
|
verify_block: proc do |value|
|
19
|
-
|
20
|
-
|
19
|
+
raise "Could not find ipa file at path '#{value}'" unless File.exist? value
|
20
|
+
raise "'#{value}' doesn't seem to be an ipa file" unless value.end_with? ".ipa"
|
21
21
|
end),
|
22
22
|
FastlaneCore::ConfigItem.new(key: :skip_submission,
|
23
23
|
short_option: "-s",
|
@@ -30,47 +30,37 @@ module Pilot
|
|
30
30
|
env_name: "PILOT_APP_IDENTIFIER",
|
31
31
|
description: "The bundle identifier of the app to upload or manage testers (optional)",
|
32
32
|
optional: true,
|
33
|
-
default_value: ENV["TESTFLIGHT_APP_IDENTITIFER"] || CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier),
|
34
|
-
verify_block: proc do |_value|
|
35
|
-
end),
|
33
|
+
default_value: ENV["TESTFLIGHT_APP_IDENTITIFER"] || CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)),
|
36
34
|
FastlaneCore::ConfigItem.new(key: :apple_id,
|
37
35
|
short_option: "-p",
|
38
36
|
env_name: "PILOT_APPLE_ID",
|
39
37
|
description: "The unique App ID provided by iTunes Connect",
|
40
38
|
optional: true,
|
41
|
-
default_value: ENV["TESTFLIGHT_APPLE_ID"],
|
42
|
-
verify_block: proc do |_value|
|
43
|
-
end),
|
39
|
+
default_value: ENV["TESTFLIGHT_APPLE_ID"]),
|
44
40
|
FastlaneCore::ConfigItem.new(key: :first_name,
|
45
41
|
short_option: "-f",
|
46
42
|
env_name: "PILOT_TESTER_FIRST_NAME",
|
47
43
|
description: "The tester's first name",
|
48
|
-
optional: true,
|
49
|
-
verify_block: proc do |_value|
|
50
|
-
end),
|
44
|
+
optional: true),
|
51
45
|
FastlaneCore::ConfigItem.new(key: :last_name,
|
52
46
|
short_option: "-l",
|
53
47
|
env_name: "PILOT_TESTER_LAST_NAME",
|
54
48
|
description: "The tester's last name",
|
55
|
-
optional: true,
|
56
|
-
verify_block: proc do |_value|
|
57
|
-
end),
|
49
|
+
optional: true),
|
58
50
|
FastlaneCore::ConfigItem.new(key: :email,
|
59
51
|
short_option: "-e",
|
60
52
|
env_name: "PILOT_TESTER_EMAIL",
|
61
53
|
description: "The tester's email",
|
62
54
|
optional: true,
|
63
|
-
verify_block: proc do |
|
64
|
-
|
55
|
+
verify_block: proc do |value|
|
56
|
+
raise "Please pass a valid email address" unless value.include? "@"
|
65
57
|
end),
|
66
58
|
FastlaneCore::ConfigItem.new(key: :testers_file_path,
|
67
59
|
short_option: "-c",
|
68
60
|
env_name: "PILOT_TESTERS_FILE",
|
69
61
|
description: "Path to a CSV file of testers",
|
70
62
|
default_value: "./testers.csv",
|
71
|
-
optional: true
|
72
|
-
verify_block: proc do |_value|
|
73
|
-
end)
|
63
|
+
optional: true)
|
74
64
|
|
75
65
|
]
|
76
66
|
end
|
@@ -8,7 +8,7 @@ module Pilot
|
|
8
8
|
|
9
9
|
def generate(apple_id: nil, ipa_path: nil, package_path: nil)
|
10
10
|
self.package_path = File.join(package_path, "#{apple_id}.itmsp")
|
11
|
-
FileUtils.rm_rf self.package_path
|
11
|
+
FileUtils.rm_rf self.package_path if File.directory?(self.package_path)
|
12
12
|
FileUtils.mkdir_p self.package_path
|
13
13
|
|
14
14
|
lib_path = Helper.gem_path("pilot")
|
@@ -22,8 +22,8 @@ module Pilot
|
|
22
22
|
}
|
23
23
|
|
24
24
|
xml_path = File.join(lib_path, "lib/assets/XMLTemplate.xml.erb")
|
25
|
-
xml = ERB.new(File.read(xml_path)).result(binding) # http://www.rrn.dk/rubys-erb-templating-system
|
26
|
-
|
25
|
+
xml = ERB.new(File.read(xml_path)).result(binding) # http://www.rrn.dk/rubys-erb-templating-system
|
26
|
+
|
27
27
|
File.write(File.join(self.package_path, METADATA_FILE_NAME), xml)
|
28
28
|
Helper.log.info "Wrote XML data to '#{self.package_path}'".green if $verbose
|
29
29
|
|
@@ -31,12 +31,13 @@ module Pilot
|
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
34
|
-
def copy_ipa(ipa_path)
|
35
|
-
ipa_file_name = Digest::MD5.hexdigest(ipa_path)
|
36
|
-
resulting_path = File.join(self.package_path, "#{ipa_file_name}.ipa")
|
37
|
-
FileUtils.cp(ipa_path, resulting_path)
|
38
34
|
|
39
|
-
|
40
|
-
|
35
|
+
def copy_ipa(ipa_path)
|
36
|
+
ipa_file_name = Digest::MD5.hexdigest(ipa_path)
|
37
|
+
resulting_path = File.join(self.package_path, "#{ipa_file_name}.ipa")
|
38
|
+
FileUtils.cp(ipa_path, resulting_path)
|
39
|
+
|
40
|
+
return resulting_path
|
41
|
+
end
|
41
42
|
end
|
42
|
-
end
|
43
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require "fastlane_core"
|
2
|
+
require "pilot/tester_util"
|
2
3
|
|
3
4
|
module Pilot
|
4
5
|
class TesterExporter < Manager
|
5
6
|
def export_testers(options)
|
6
|
-
|
7
7
|
raise "Export file path is required".red unless options[:testers_file_path]
|
8
8
|
|
9
9
|
start(options)
|
@@ -14,11 +14,9 @@ module Pilot
|
|
14
14
|
file = config[:testers_file_path]
|
15
15
|
|
16
16
|
CSV.open(file, "w") do |csv|
|
17
|
-
|
18
17
|
csv << ['First', 'Last', 'Email', 'Devices', 'Groups', 'Installed Version', 'Install Date']
|
19
18
|
|
20
19
|
testers.each do |tester|
|
21
|
-
|
22
20
|
groups = tester.raw_data.get("groups")
|
23
21
|
|
24
22
|
group_names = ""
|
@@ -27,12 +25,14 @@ module Pilot
|
|
27
25
|
group_names = names.join(';')
|
28
26
|
end
|
29
27
|
|
30
|
-
|
28
|
+
install_version = tester.full_version || ""
|
29
|
+
pretty_date = tester.pretty_install_date || ""
|
30
|
+
|
31
|
+
csv << [tester.first_name, tester.last_name, tester.email, tester.devices.count, group_names, install_version, pretty_date]
|
31
32
|
end
|
32
33
|
|
33
34
|
Helper.log.info "Successfully exported CSV to #{file}".green
|
34
35
|
end
|
35
|
-
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -20,7 +20,7 @@ module Pilot
|
|
20
20
|
next
|
21
21
|
end
|
22
22
|
|
23
|
-
first_name, last_name, email = row
|
23
|
+
first_name, last_name, email = row
|
24
24
|
|
25
25
|
unless email
|
26
26
|
Helper.log.error "No email found in row: #{row}".red
|
@@ -35,10 +35,9 @@ module Pilot
|
|
35
35
|
begin
|
36
36
|
tester_manager.add_tester(config)
|
37
37
|
imported_tester_count += 1
|
38
|
-
rescue
|
38
|
+
rescue
|
39
39
|
# do nothing, move on to the next row
|
40
40
|
end
|
41
|
-
|
42
41
|
end
|
43
42
|
|
44
43
|
Helper.log.info "Successfully imported #{imported_tester_count} testers from #{file}".green
|
data/lib/pilot/tester_manager.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "fastlane_core"
|
2
|
+
require "pilot/tester_util"
|
2
3
|
|
3
4
|
module Pilot
|
4
5
|
class TesterManager < Manager
|
@@ -17,7 +18,7 @@ module Pilot
|
|
17
18
|
last_name: config[:last_name])
|
18
19
|
Helper.log.info "Successfully invited tester: #{tester.email}".green
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
app_filter = (config[:apple_id] || config[:app_identifier])
|
22
23
|
if app_filter
|
23
24
|
begin
|
@@ -43,14 +44,14 @@ module Pilot
|
|
43
44
|
tester ||= Spaceship::Tunes::Tester::External.find(config[:email])
|
44
45
|
|
45
46
|
raise "Tester #{config[:email]} not found".red unless tester
|
46
|
-
|
47
|
+
|
47
48
|
describe_tester(tester)
|
48
49
|
return tester
|
49
50
|
end
|
50
51
|
|
51
52
|
def remove_tester(options)
|
52
53
|
start(options)
|
53
|
-
|
54
|
+
|
54
55
|
tester = Spaceship::Tunes::Tester::External.find(config[:email])
|
55
56
|
tester ||= Spaceship::Tunes::Tester::Internal.find(config[:email])
|
56
57
|
|
@@ -73,64 +74,60 @@ module Pilot
|
|
73
74
|
|
74
75
|
private
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
puts Terminal::Table.new(
|
83
|
-
title: title.green,
|
84
|
-
headings: ["First", "Last", "Email", "Devices"],
|
85
|
-
rows: rows
|
86
|
-
)
|
77
|
+
def list(all_testers, title)
|
78
|
+
rows = []
|
79
|
+
all_testers.each do |tester|
|
80
|
+
rows << [tester.first_name, tester.last_name, tester.email, tester.devices.count]
|
87
81
|
end
|
88
82
|
|
89
|
-
|
90
|
-
|
91
|
-
|
83
|
+
puts Terminal::Table.new(
|
84
|
+
title: title.green,
|
85
|
+
headings: ["First", "Last", "Email", "Devices"],
|
86
|
+
rows: rows
|
87
|
+
)
|
88
|
+
end
|
92
89
|
|
93
|
-
|
90
|
+
# Print out all the details of a specific tester
|
91
|
+
def describe_tester(tester)
|
92
|
+
return unless tester
|
94
93
|
|
95
|
-
|
96
|
-
rows << ["Last name", tester.last_name]
|
97
|
-
rows << ["Email", tester.email]
|
94
|
+
rows = []
|
98
95
|
|
99
|
-
|
96
|
+
rows << ["First name", tester.first_name]
|
97
|
+
rows << ["Last name", tester.last_name]
|
98
|
+
rows << ["Email", tester.email]
|
100
99
|
|
101
|
-
|
102
|
-
group_names = groups.map { |group| group["name"]["value"] }
|
103
|
-
rows << ["Groups", group_names.join(', ')]
|
104
|
-
end
|
100
|
+
groups = tester.raw_data.get("groups")
|
105
101
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
102
|
+
if groups && groups.length > 0
|
103
|
+
group_names = groups.map { |group| group["name"]["value"] }
|
104
|
+
rows << ["Groups", group_names.join(', ')]
|
105
|
+
end
|
110
106
|
|
111
|
-
|
112
|
-
|
113
|
-
|
107
|
+
if tester.latest_install_date
|
108
|
+
rows << ["Latest Version", tester.full_version]
|
109
|
+
rows << ["Latest Install Date", tester.pretty_install_date]
|
110
|
+
end
|
114
111
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
112
|
+
if tester.devices.length == 0
|
113
|
+
rows << ["Devices", "No devices"]
|
114
|
+
else
|
115
|
+
rows << ["#{tester.devices.count} Devices", ""]
|
116
|
+
tester.devices.each do |device|
|
117
|
+
current = "\u2022 #{device['model']}, iOS #{device['osVersion']}"
|
118
|
+
|
119
|
+
if rows.last[1].length == 0
|
120
|
+
rows.last[1] = current
|
121
|
+
else
|
122
|
+
rows << ["", current]
|
127
123
|
end
|
128
124
|
end
|
129
|
-
|
130
|
-
puts Terminal::Table.new(
|
131
|
-
title: tester.email.green,
|
132
|
-
rows: rows
|
133
|
-
)
|
134
125
|
end
|
126
|
+
|
127
|
+
puts Terminal::Table.new(
|
128
|
+
title: tester.email.green,
|
129
|
+
rows: rows
|
130
|
+
)
|
131
|
+
end
|
135
132
|
end
|
136
133
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spaceship/base"
|
2
|
+
require "spaceship/tunes/tunes_base"
|
3
|
+
require "spaceship/tunes/tester"
|
4
|
+
|
5
|
+
module Spaceship
|
6
|
+
module Tunes
|
7
|
+
# monkey patched
|
8
|
+
# move this to spaceship
|
9
|
+
class Tester < TunesBase
|
10
|
+
def full_version
|
11
|
+
return nil unless latest_install_date
|
12
|
+
latest_installed_version = latest_installed_version_number
|
13
|
+
latest_installed_short_version = latest_installed_build_number
|
14
|
+
"#{latest_installed_version} (#{latest_installed_short_version})"
|
15
|
+
end
|
16
|
+
|
17
|
+
def pretty_install_date
|
18
|
+
return nil unless latest_install_date
|
19
|
+
Time.at((latest_install_date / 1000)).strftime("%m/%d/%y %H:%M")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/pilot/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pilot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felix Krause
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fastlane_core
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.16.
|
19
|
+
version: 0.16.1
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 1.0.0
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.16.
|
29
|
+
version: 0.16.1
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.0.0
|
@@ -191,6 +191,7 @@ files:
|
|
191
191
|
- lib/pilot/tester_exporter.rb
|
192
192
|
- lib/pilot/tester_importer.rb
|
193
193
|
- lib/pilot/tester_manager.rb
|
194
|
+
- lib/pilot/tester_util.rb
|
194
195
|
- lib/pilot/version.rb
|
195
196
|
homepage: https://fastlane.tools
|
196
197
|
licenses:
|
@@ -212,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
212
213
|
version: '0'
|
213
214
|
requirements: []
|
214
215
|
rubyforge_project:
|
215
|
-
rubygems_version: 2.4.
|
216
|
+
rubygems_version: 2.4.5
|
216
217
|
signing_key:
|
217
218
|
specification_version: 4
|
218
219
|
summary: The best way to manage your TestFlight testers and builds from your terminal
|