pilot 0.1.7 → 0.2.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/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
|