fastlane 2.47.0.beta.20170712010003 → 2.47.0.beta.20170713010003
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane_core/lib/fastlane_core/build_watcher.rb +2 -2
- data/gym/lib/gym/error_handler.rb +52 -31
- data/spaceship/lib/spaceship/portal/key.rb +99 -0
- data/spaceship/lib/spaceship/portal/portal.rb +1 -0
- data/spaceship/lib/spaceship/portal/portal_client.rb +48 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87fdbf460eea76afd41b155d334da48b710b2d4f
|
4
|
+
data.tar.gz: 19ca586cb7f4f518383e8a293c3251a49b22ae49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 966fac603239f16233f92dbea02d932a4fc01191ec03d84c3d5a69434aeb8245fab59c050d81fe441e0f611154402899f142b2eab2c17487f27c37c1944783f8
|
7
|
+
data.tar.gz: a3b6baab3fd47dbb4b36594300e7446ffbc1cacbf9b575ab1feb015c6c45b2f18a98b2d57cf027a3ecda33e7f683aaa509f0211c2ab0182825f27901e886e80b
|
data/README.md
CHANGED
@@ -95,6 +95,10 @@ Get started distributing your first app with fastlane within minutes:
|
|
95
95
|
Want to learn more? Explore guides for [iOS](https://docs.fastlane.tools/getting-started/ios/setup/)
|
96
96
|
or [Android](https://docs.fastlane.tools/getting-started/android/setup/).
|
97
97
|
|
98
|
+
## System Requirements
|
99
|
+
|
100
|
+
Currently, _fastlane_ is officially supported to run on macOS. Support for other operating systems is limited and untested at this point in time. _fastlane_ uses system APIs that may not be implemented on other platforms, for example, we use the Ruby `fork` method for sub-process management, which isn't available on Windows.
|
101
|
+
|
98
102
|
## Available Commands
|
99
103
|
|
100
104
|
Typically you'll use `fastlane` by triggering individual lanes:
|
@@ -35,13 +35,13 @@ module FastlaneCore
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def report_status(build: nil)
|
38
|
-
# Due to iTunes Connect, builds disappear from the build list
|
38
|
+
# Due to iTunes Connect, builds disappear from the build list altogether
|
39
39
|
# after they finished processing. Before returning this build, we have to
|
40
40
|
# wait for the build to appear in the build list again
|
41
41
|
# As this method is very often used to wait for a build, and then do something
|
42
42
|
# with it, we have to be sure that the build actually is ready
|
43
43
|
if build.nil?
|
44
|
-
UI.message("Build doesn't show up in the build list
|
44
|
+
UI.message("Build doesn't show up in the build list anymore, waiting for it to appear again")
|
45
45
|
elsif build.active?
|
46
46
|
UI.success("Build #{build.train_version} - #{build.build_version} is already being tested")
|
47
47
|
elsif build.ready_to_submit? || build.export_compliance_missing?
|
@@ -51,9 +51,10 @@ module Gym
|
|
51
51
|
print "For more information visit this stackoverflow answer:"
|
52
52
|
print "https://stackoverflow.com/a/17031697/445598"
|
53
53
|
end
|
54
|
-
print_full_log_path
|
55
54
|
print_xcode_path_instructions
|
56
55
|
print_xcode_version
|
56
|
+
print_full_log_path
|
57
|
+
print_build_error_instructions
|
57
58
|
UI.build_failure!("Error building the application - see the log above", error_info: output)
|
58
59
|
end
|
59
60
|
|
@@ -89,6 +90,7 @@ module Gym
|
|
89
90
|
print "provisioning profile and code signing identity."
|
90
91
|
end
|
91
92
|
print_full_log_path
|
93
|
+
print_build_error_instructions
|
92
94
|
UI.build_failure!("Error packaging up the application", error_info: output)
|
93
95
|
end
|
94
96
|
|
@@ -102,18 +104,8 @@ module Gym
|
|
102
104
|
UI.build_failure!("Archive invalid")
|
103
105
|
end
|
104
106
|
|
105
|
-
def find_standard_output_path(output)
|
106
|
-
m = /Created bundle at path '(.*)'/.match(output)
|
107
|
-
return File.join(m[1], 'IDEDistribution.standard.log') unless m.nil?
|
108
|
-
end
|
109
|
-
|
110
107
|
private
|
111
108
|
|
112
|
-
def read_standard_output(output)
|
113
|
-
path = find_standard_output_path output
|
114
|
-
return File.read(path) if File.exist?(path)
|
115
|
-
end
|
116
|
-
|
117
109
|
# Just to make things easier
|
118
110
|
def print(text)
|
119
111
|
UI.error text
|
@@ -121,8 +113,21 @@ module Gym
|
|
121
113
|
|
122
114
|
def print_full_log_path
|
123
115
|
return if Gym.config[:disable_xcpretty]
|
116
|
+
|
124
117
|
log_path = Gym::BuildCommandGenerator.xcodebuild_log_path
|
125
|
-
|
118
|
+
return unless File.exist?(log_path)
|
119
|
+
|
120
|
+
# `xcodebuild` doesn't properly mark lines as failure reason or important information
|
121
|
+
# so we assume that the last few lines show the error message that's relevant
|
122
|
+
# (at least that's what was correct during testing)
|
123
|
+
log_content = File.read(log_path).split("\n")[-5..-1]
|
124
|
+
log_content.each do |row|
|
125
|
+
UI.command_output(row)
|
126
|
+
end
|
127
|
+
|
128
|
+
UI.message("")
|
129
|
+
UI.error("⬆️ Check out the few lines of raw `xcodebuild` output above for potential hints on how to solve this error")
|
130
|
+
UI.important("📋 For the complete and more detailed error log, check the full log at:")
|
126
131
|
UI.important("📋 #{log_path}")
|
127
132
|
end
|
128
133
|
|
@@ -148,25 +153,41 @@ module Gym
|
|
148
153
|
default_xcode_path = "/Applications/"
|
149
154
|
|
150
155
|
xcode_installations_in_default_path = Dir[File.join(default_xcode_path, "Xcode*.app")]
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
156
|
+
return unless xcode_installations_in_default_path.count > 1
|
157
|
+
UI.message ""
|
158
|
+
UI.important "Maybe the error shown is caused by using the wrong version of Xcode"
|
159
|
+
UI.important "Found multiple versions of Xcode in '#{default_xcode_path}'"
|
160
|
+
UI.important "Make sure you selected the right version for your project"
|
161
|
+
UI.important "This build process was executed using '#{xcode_path}'"
|
162
|
+
UI.important "If you want to update your Xcode path, either"
|
163
|
+
UI.message ""
|
164
|
+
|
165
|
+
UI.message "- Specify the Xcode version in your Fastfile"
|
166
|
+
UI.command_output "xcversion(version: \"8.1\") # Selects Xcode 8.1.0"
|
167
|
+
UI.message ""
|
168
|
+
|
169
|
+
UI.message "- Specify an absolute path to your Xcode installation in your Fastfile"
|
170
|
+
UI.command_output "xcode_select \"/Applications/Xcode8.app\""
|
171
|
+
UI.message ""
|
172
|
+
|
173
|
+
UI.message "- Manually update the path using"
|
174
|
+
UI.command_output "sudo xcode-select -s /Applications/Xcode.app"
|
175
|
+
UI.message ""
|
176
|
+
end
|
177
|
+
|
178
|
+
# Indicate that code signing errors are not caused by fastlane
|
179
|
+
# and that fastlane only runs `xcodebuild` commands
|
180
|
+
def print_build_error_instructions
|
181
|
+
UI.message("")
|
182
|
+
UI.error("Looks like fastlane ran into a build/archive error with your project")
|
183
|
+
UI.error("It's hard to tell what's causing the error, so we wrote some guides on how")
|
184
|
+
UI.error("to troubleshoot build and signing issues: https://docs.fastlane.tools/codesigning/getting-started/")
|
185
|
+
UI.error("Before submitting an issue on GitHub, please follow the guide above and make")
|
186
|
+
UI.error("sure your project is set up correctly.")
|
187
|
+
UI.error("fastlane uses `xcodebuild` commands to generate your binary, you can see the")
|
188
|
+
UI.error("the full commands printed out in yellow in the above log.")
|
189
|
+
UI.error("Make sure to inspect the output above, as usually you'll find more error information there")
|
190
|
+
UI.message("")
|
170
191
|
end
|
171
192
|
end
|
172
193
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Spaceship
|
2
|
+
module Portal
|
3
|
+
class Key < PortalBase
|
4
|
+
##
|
5
|
+
# data model for managing JWT tokens or "Keys" as the ADP refers to them
|
6
|
+
|
7
|
+
APNS_ID = 'U27F4V844T'
|
8
|
+
DEVICE_CHECK_ID = 'DQ8HTZ7739'
|
9
|
+
MUSIC_KIT_ID = '6A7HVUVQ3M'
|
10
|
+
|
11
|
+
attr_accessor :id
|
12
|
+
attr_accessor :name
|
13
|
+
|
14
|
+
attr_mapping({
|
15
|
+
'keyId' => :id,
|
16
|
+
'keyName' => :name,
|
17
|
+
'services' => :services,
|
18
|
+
'canDownload' => :can_download,
|
19
|
+
'canRevoke' => :can_revoke
|
20
|
+
})
|
21
|
+
|
22
|
+
def self.all
|
23
|
+
keys = client.list_keys
|
24
|
+
keys.map do |key|
|
25
|
+
new(key)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.find(id)
|
30
|
+
key = client.get_key(id: id)
|
31
|
+
new(key)
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Creates a new JWT / Key for making requests to services.
|
36
|
+
#
|
37
|
+
# @param name [String] the name of the key
|
38
|
+
# @param apns [Bool] whether the key should be able to make APNs requests
|
39
|
+
# @param device_check [Bool] whether the key should be able to make DeviceCheck requests
|
40
|
+
# @param music_id [String] the Music Id id (the autogenerated id, not the user specified identifier "music.com.etc...")
|
41
|
+
def self.create(name: nil, apns: nil, device_check: nil, music_id: nil)
|
42
|
+
service_config = {}
|
43
|
+
service_config[APNS_ID] = [] if apns
|
44
|
+
service_config[DEVICE_CHECK_ID] = [] if device_check
|
45
|
+
service_config[MUSIC_KIT_ID] = [music_id] if music_id
|
46
|
+
|
47
|
+
key = client.create_key!(name: name, service_configs: service_config)
|
48
|
+
new(key)
|
49
|
+
end
|
50
|
+
|
51
|
+
def revoke!
|
52
|
+
client.revoke_key!(id: id)
|
53
|
+
end
|
54
|
+
|
55
|
+
def download
|
56
|
+
client.download_key(id: id)
|
57
|
+
end
|
58
|
+
|
59
|
+
def services
|
60
|
+
raw_data['services'] || reload
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
def service_configs_for(service_id)
|
65
|
+
if (service = find_service(service_id))
|
66
|
+
service['configurations']
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def has_apns?
|
71
|
+
has_service?(APNS_ID)
|
72
|
+
end
|
73
|
+
|
74
|
+
def has_music_kit?
|
75
|
+
has_service?(MUSIC_KIT_ID)
|
76
|
+
end
|
77
|
+
|
78
|
+
def has_device_check?
|
79
|
+
has_service?(DEVICE_CHECK_ID)
|
80
|
+
end
|
81
|
+
|
82
|
+
def reload
|
83
|
+
self.raw_data = self.class.find(id).raw_data
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def find_service(service_id)
|
89
|
+
services.find do |service|
|
90
|
+
service['id'] == service_id
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def has_service?(service_id)
|
95
|
+
find_service(service_id) != nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -560,6 +560,54 @@ module Spaceship
|
|
560
560
|
parse_response(r, 'provisioningProfile')
|
561
561
|
end
|
562
562
|
|
563
|
+
#####################################################
|
564
|
+
# @!group Keys
|
565
|
+
#####################################################
|
566
|
+
|
567
|
+
def list_keys
|
568
|
+
paging do |page_number|
|
569
|
+
response = request(:post, 'account/auth/key/list', {
|
570
|
+
teamId: team_id,
|
571
|
+
pageNumber: page_number,
|
572
|
+
pageSize: page_size,
|
573
|
+
sort: 'name=asc'
|
574
|
+
})
|
575
|
+
parse_response(response, 'keys')
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
def get_key(id: nil)
|
580
|
+
response = request(:post, 'account/auth/key/get', { teamId: team_id, keyId: id })
|
581
|
+
# response contains a list of keys with 1 item
|
582
|
+
parse_response(response, 'keys').first
|
583
|
+
end
|
584
|
+
|
585
|
+
def download_key(id: nil)
|
586
|
+
response = request(:get, 'account/auth/key/download', { teamId: team_id, keyId: id })
|
587
|
+
parse_response(response)
|
588
|
+
end
|
589
|
+
|
590
|
+
def create_key!(name: nil, service_configs: nil)
|
591
|
+
params = {
|
592
|
+
name: name,
|
593
|
+
serviceConfigurations: service_configs,
|
594
|
+
teamId: team_id
|
595
|
+
}
|
596
|
+
|
597
|
+
response = request(:post, 'account/auth/key/create') do |req|
|
598
|
+
req.headers['Content-Type'] = 'application/json'
|
599
|
+
req.body = params.to_json
|
600
|
+
end
|
601
|
+
|
602
|
+
# response contains a list of keys with 1 item
|
603
|
+
parse_response(response, 'keys').first
|
604
|
+
end
|
605
|
+
|
606
|
+
def revoke_key!(id: nil)
|
607
|
+
response = request(:post, 'account/auth/key/revoke', { teamId: team_id, keyId: id })
|
608
|
+
parse_response(response)
|
609
|
+
end
|
610
|
+
|
563
611
|
private
|
564
612
|
|
565
613
|
# This is a cache of entity type (App, AppGroup, Certificate, Device) to csrf_tokens
|
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.47.0.beta.
|
4
|
+
version: 2.47.0.beta.20170713010003
|
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-07-
|
18
|
+
date: 2017-07-13 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: slack-notifier
|
@@ -1312,6 +1312,7 @@ files:
|
|
1312
1312
|
- spaceship/lib/spaceship/portal/app_service.rb
|
1313
1313
|
- spaceship/lib/spaceship/portal/certificate.rb
|
1314
1314
|
- spaceship/lib/spaceship/portal/device.rb
|
1315
|
+
- spaceship/lib/spaceship/portal/key.rb
|
1315
1316
|
- spaceship/lib/spaceship/portal/person.rb
|
1316
1317
|
- spaceship/lib/spaceship/portal/persons.rb
|
1317
1318
|
- spaceship/lib/spaceship/portal/portal.rb
|