fastlane 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30bf18c8b5fd980a862648ec6cba94f11f0b1aed
4
- data.tar.gz: 3558eaec5dcce06536ed04f2fa20a7315c2b3b4b
3
+ metadata.gz: acbb31b6b342da9f2a15a22936808c0c93d68762
4
+ data.tar.gz: 21bd81ba701a4b11a2bf71d8cc8b41a20f4be78c
5
5
  SHA512:
6
- metadata.gz: 725d84319bf1219fef0658c4f29f5004baa1fb7eb8625642855f48a3b0d607c4839e2519575a31fcc4963cca43189379e5f4ff405287e250a1d27094639dd926
7
- data.tar.gz: 1dcb5131e5708cd5c2c0841192e66b65f97768bee7e371b45aa09468d2fd38042a9d498bb8d760e39d79b642394fd953de22888e09345686be074788b8fa2784
6
+ metadata.gz: 43b2ba4ba3613e9324522c76a6a081639d4ddb46d1a00d95c01c2a809e2d84c43525d09533102e7197fd4a4dedb288f40c1a90dcc5393def55ab3a15619d1317
7
+ data.tar.gz: e372a9675ae45e33aa649f620116ee257313679d692673ecc073f88fa134fdb382a787a4e430065a3a2d05847851532e2602b22d3db587c34795703ffb62e901
@@ -2,4 +2,14 @@
2
2
  $LOAD_PATH.push File.expand_path("../../lib", __FILE__)
3
3
 
4
4
  require "fastlane/cli_tools_distributor"
5
+
6
+ if Fastlane::CLIToolsDistributor.running_version_command?
7
+ # This will print out the fastlane binary path right above the
8
+ # version number. Very often, users are not aware they have
9
+ # e.g. bundled fastlane installed
10
+ puts "fastlane installation at path:"
11
+ puts File.expand_path(__FILE__)
12
+ puts "-----------------------------"
13
+ end
14
+
5
15
  Fastlane::CLIToolsDistributor.take_off
@@ -3,19 +3,31 @@ require 'highline/import' # to hide the entered password
3
3
 
4
4
  module CredentialsManager
5
5
  class AccountManager
6
+ DEFAULT_PREFIX = "deliver"
6
7
  # @param prefix [String] Very optional, is used for the
7
8
  # iTunes Transporter which uses application specofic passwords
8
- def initialize(user: nil, password: nil, prefix: nil)
9
- @prefix = prefix || "deliver"
9
+ # @param note [String] An optional note that will be shown next
10
+ # to the password and username prompt
11
+ def initialize(user: nil, password: nil, prefix: nil, note: nil)
12
+ @prefix = prefix || DEFAULT_PREFIX
10
13
 
11
14
  @user = user
12
15
  @password = password
16
+ @note = note
17
+ end
18
+
19
+ # Is the that default prefix "deliver"
20
+ def default_prefix?
21
+ @prefix == DEFAULT_PREFIX
13
22
  end
14
23
 
15
24
  def user
16
- @user ||= ENV["FASTLANE_USER"]
17
- @user ||= ENV["DELIVER_USER"]
18
- @user ||= AppfileConfig.try_fetch_value(:apple_id)
25
+ if default_prefix?
26
+ @user ||= ENV["FASTLANE_USER"]
27
+ @user ||= ENV["DELIVER_USER"]
28
+ @user ||= AppfileConfig.try_fetch_value(:apple_id)
29
+ end
30
+
19
31
  ask_for_login if @user.to_s.length == 0
20
32
  return @user
21
33
  end
@@ -25,7 +37,10 @@ module CredentialsManager
25
37
  end
26
38
 
27
39
  def password(ask_if_missing: true)
28
- @password ||= fetch_password_from_env
40
+ if default_prefix?
41
+ @password ||= fetch_password_from_env
42
+ end
43
+
29
44
  unless @password
30
45
  item = Security::InternetPassword.find(server: server_name)
31
46
  @password ||= item.password if item
@@ -87,20 +102,28 @@ module CredentialsManager
87
102
  def ask_for_login
88
103
  puts "-------------------------------------------------------------------------------------".green
89
104
  puts "The login information you enter will be stored in your Mac OS Keychain".green
90
- puts "You can also pass the password using the `FASTLANE_PASSWORD` environment variable".green
91
- puts "More information about it on GitHub: https://github.com/fastlane/fastlane/tree/master/credentials_manager".green
105
+ if default_prefix?
106
+ # We don't want to show this message, if we ask for the application specific password
107
+ # which has a different prefix
108
+ puts "You can also pass the password using the `FASTLANE_PASSWORD` environment variable".green
109
+ puts "More information about it on GitHub: https://github.com/fastlane/fastlane/tree/master/credentials_manager".green
110
+ end
92
111
  puts "-------------------------------------------------------------------------------------".green
93
112
 
94
113
  if @user.to_s.length == 0
95
114
  raise "Missing username, and running in non-interactive shell" if $stdout.isatty == false
96
- @user = ask("Username: ") while @user.to_s.length == 0
115
+ prompt_text = "Username"
116
+ prompt_text += " (#{@note})" if @note
117
+ prompt_text += ": "
118
+ @user = ask(prompt_text) while @user.to_s.length == 0
97
119
  # we return here, as only the username was asked for now, we'll get called for the pw again anyway
98
120
  return
99
121
  end
100
122
 
101
123
  while @password.to_s.length == 0
102
124
  raise "Missing password for user #{@user}, and running in non-interactive shell" if $stdout.isatty == false
103
- @password = ask("Password (for #{@user}): ") { |q| q.echo = "*" }
125
+ note = @note + " " if @note
126
+ @password = ask("Password (#{note}for #{@user}): ") { |q| q.echo = "*" }
104
127
  end
105
128
 
106
129
  return true if ENV["FASTLANE_DONT_STORE_PASSWORD"]
@@ -27,6 +27,7 @@ module Deliver
27
27
  FastlaneCore::ConfigItem.new(key: :edit_live,
28
28
  short_option: "-o",
29
29
  optional: true,
30
+ default_value: false,
30
31
  env_name: "DELIVER_EDIT_LIVE",
31
32
  description: "Modify live metadata, this option disables ipa upload and screenshot upload",
32
33
  is_string: false),
@@ -37,6 +37,15 @@ module Deliver
37
37
  v = app.live_version(platform: options[:platform])
38
38
  localised_options = LOCALISED_LIVE_VALUES
39
39
  non_localised_options = NON_LOCALISED_LIVE_VALUES
40
+
41
+ if v.nil?
42
+ UI.message("Couldn't find live version, editing the current version on iTunes Connect instead")
43
+ v = app.edit_version(platform: options[:platform])
44
+ # we don't want to update the localised_options and non_localised_options
45
+ # as we also check for `options[:edit_live]` at other areas in the code
46
+ # by not touching those 2 variables, deliver is more consistent with what the option says
47
+ # in the documentation
48
+ end
40
49
  else
41
50
  v = app.edit_version(platform: options[:platform])
42
51
  localised_options = (LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES)
@@ -28,7 +28,7 @@ module Fastlane
28
28
  FastlaneCore::UpdateChecker.start_looking_for_update('fastlane')
29
29
  Fastlane.load_actions
30
30
  # do not use "include" as it may be some where in the commandline where "env" is required, therefore explicit index->0
31
- unless ARGV[0] == "env"
31
+ unless ARGV[0] == "env" || CLIToolsDistributor.running_version_command?
32
32
  # *after* loading the plugins
33
33
  Fastlane.plugin_manager.load_plugins
34
34
  Fastlane::PluginUpdateManager.start_looking_for_updates
@@ -1,4 +1,4 @@
1
1
  module Fastlane
2
- VERSION = '2.4.0'.freeze
2
+ VERSION = '2.5.0'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  end
@@ -71,14 +71,8 @@ module FastlaneCore
71
71
 
72
72
  device_uuids = []
73
73
  result = Plist.parse_xml(usb_devices_output)
74
- result[0]['_items'].each do |host_controller| # loop just incase the host system has more then 1 controller
75
- host_controller['_items'].each do |usb_device|
76
- is_supported_device = device_types.any? { |device_type| usb_device['_name'] == device_type }
77
- if is_supported_device && usb_device['serial_num'].length == 40
78
- device_uuids.push(usb_device['serial_num'])
79
- end
80
- end
81
- end
74
+
75
+ discover_devices(result[0], device_types, device_uuids) if result[0]
82
76
 
83
77
  if device_uuids.count > 0 # instruments takes a little while to return so skip it if we have no devices
84
78
  instruments_devices_output = ''
@@ -100,6 +94,21 @@ module FastlaneCore
100
94
  return devices
101
95
  end
102
96
 
97
+ # Recursively handle all USB items, discovering devices that match the
98
+ # desired types.
99
+ def discover_devices(usb_item, device_types, discovered_device_udids)
100
+ (usb_item['_items'] || []).each do |child_item|
101
+ discover_devices(child_item, device_types, discovered_device_udids)
102
+ end
103
+
104
+ is_supported_device = device_types.any? { |device_type| usb_item['_name'] == device_type }
105
+ has_serial_number = (usb_item['serial_num'] || '').length == 40
106
+
107
+ if is_supported_device && has_serial_number
108
+ discovered_device_udids << usb_item['serial_num']
109
+ end
110
+ end
111
+
103
112
  # The code below works from Xcode 7 on
104
113
  # def all
105
114
  # UI.verbose("Fetching available devices")
@@ -294,20 +294,9 @@ module FastlaneCore
294
294
  use_shell_script ||= Helper.is_mac? && Helper.xcode_version.start_with?('6.')
295
295
  use_shell_script ||= Feature.enabled?('FASTLANE_ITUNES_TRANSPORTER_USE_SHELL_SCRIPT')
296
296
 
297
- # First, see if we have an application specific password
298
- data = CredentialsManager::AccountManager.new(user: user,
299
- prefix: TWO_STEP_HOST_PREFIX)
300
- @user = data.user
301
- @password ||= data.password(ask_if_missing: false)
302
-
303
- if @password.to_s.length == 0
304
- # No specific password found, just using the iTC/Dev Portal one
305
- # default to the given password here
306
- data = CredentialsManager::AccountManager.new(user: user,
307
- password: password)
308
- @user = data.user
309
- @password ||= data.password
310
- end
297
+ @user = user
298
+ @password = password || load_password_for_transporter
299
+
311
300
  @transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new
312
301
  @provider_short_name = provider_short_name
313
302
  end
@@ -383,10 +372,36 @@ module FastlaneCore
383
372
 
384
373
  private
385
374
 
375
+ TWO_FACTOR_ENV_VARIABLE = "FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"
376
+
377
+ # Returns the password to be used with the transporter
378
+ def load_password_for_transporter
379
+ # 3 different sources for the password
380
+ # 1) ENV variable for application specific password
381
+ return ENV[TWO_FACTOR_ENV_VARIABLE] if ENV[TWO_FACTOR_ENV_VARIABLE].to_s.length > 0
382
+ # 2) TWO_STEP_HOST_PREFIX from keychain
383
+ account_manager = CredentialsManager::AccountManager.new(user: @user,
384
+ prefix: TWO_STEP_HOST_PREFIX,
385
+ note: "application-specific")
386
+ password = account_manager.password(ask_if_missing: false)
387
+ return password if password.to_s.length > 0
388
+ # 3) standard iTC password
389
+ account_manager = CredentialsManager::AccountManager.new(user: @user)
390
+ return account_manager.password(ask_if_missing: true)
391
+ end
392
+
386
393
  # Tells the user how to get an application specific password
387
394
  def handle_two_step_failure(ex)
395
+ if ENV[TWO_FACTOR_ENV_VARIABLE].to_s.length > 0
396
+ # Password provided, however we already used it
397
+ UI.error("Application specific password you provided using #{TWO_FACTOR_ENV_VARIABLE}")
398
+ UI.error("is invalid, please make sure it's correct")
399
+ UI.user_error!("Invalid application specific password provided")
400
+ end
401
+
388
402
  a = CredentialsManager::AccountManager.new(user: @user,
389
- prefix: TWO_STEP_HOST_PREFIX)
403
+ prefix: TWO_STEP_HOST_PREFIX,
404
+ note: "application-specific")
390
405
  if a.password(ask_if_missing: false).to_s.length > 0
391
406
  # user already entered one.. delete the old one
392
407
  UI.error("Application specific password seems wrong")
@@ -397,7 +412,10 @@ module FastlaneCore
397
412
  UI.error("Please go to https://appleid.apple.com/account/manage")
398
413
  UI.error("and generate an application specific password for")
399
414
  UI.error("the iTunes Transporter, which is used to upload builds")
400
- @password = a.password # to ask the user for the missing value
415
+ UI.error("To set the application specific password on a CI machine using")
416
+ UI.error("an environment variable, you can set the")
417
+ UI.error("#{TWO_FACTOR_ENV_VARIABLE} variable")
418
+ @password = a.password(ask_if_missing: true) # to ask the user for the missing value
401
419
 
402
420
  return true
403
421
  end
@@ -71,6 +71,8 @@ module FastlaneCore
71
71
  end
72
72
  puts '#######################################################################'.green
73
73
  Changelog.show_changes(gem_name, current_version) unless FastlaneCore::Env.truthy?("FASTLANE_HIDE_CHANGELOG")
74
+
75
+ ensure_rubygems_source
74
76
  end
75
77
 
76
78
  # The command that the user should use to update their mac
@@ -84,6 +86,20 @@ module FastlaneCore
84
86
  end
85
87
  end
86
88
 
89
+ # Check if RubyGems is set as a gem source
90
+ # on some machines that might not be the case
91
+ # and then users can't find the update when
92
+ # running the specified command
93
+ def self.ensure_rubygems_source
94
+ return if Helper.contained_fastlane?
95
+ return if `gem sources`.include?("https://rubygems.org")
96
+ puts ""
97
+ UI.error("RubyGems is not listed as your Gem source")
98
+ UI.error("You can run `gem sources` to see all your sources")
99
+ UI.error("Please run the following command to fix this:")
100
+ UI.command("gem sources --add https://rubygems.org")
101
+ end
102
+
87
103
  # Generate the URL on the main thread (since we're switching directory)
88
104
  def self.generate_fetch_url(gem_name)
89
105
  url = UPDATE_URL + gem_name
@@ -112,7 +112,11 @@ This requires you to install `pry` using `sudo gem install pry`. `pry` is not in
112
112
 
113
113
  When your Apple account has 2 factor verification enabled, you'll automatically be asked to verify your identity using your phone. The resulting session will be stored in `~/.spaceship/[email]/cookie`. The session should be valid for about one month, however there is no way to test this without actually waiting for over a month.
114
114
 
115
- Since your CI system probably doesn't allow you to input values (like the verification code), you can use `fastlane spaceauth`:
115
+ ### Support for CI machines
116
+
117
+ #### Web sessions
118
+
119
+ To generate a web session for your CI machine, use
116
120
 
117
121
  ```sh
118
122
  fastlane spaceauth -u apple@krausefx.com
@@ -126,6 +130,16 @@ export FASTLANE_SESSION='---\n- !ruby/object:HTTP::Cookie\n name: DES5c148586df
126
130
 
127
131
  Copy everything from `---\n` to your CI server and provide it as environment variable named `FASTLANE_SESSION`.
128
132
 
133
+ #### Transporter
134
+
135
+ If you want to upload builds to TestFlight/iTunes Connect from your CI, you have to generate an application specific password:
136
+
137
+ 1. Visit [appleid.apple.com/account/manage](https://appleid.apple.com/account/manage)
138
+ 1. Generate a new application specific password
139
+ 1. Provide the application specific password using an environment variable `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD`.
140
+
141
+ Alternatively you can enter the password when you're asked the first time _fastlane_ uploads a build.
142
+
129
143
  ### _spaceship_ in use
130
144
 
131
145
  All [fastlane tools](https://fastlane.tools) that communicate with Apple's web services in some way, use _spaceship_ to do so.
@@ -211,6 +211,21 @@ module Supply
211
211
  return result_upload.version_code
212
212
  end
213
213
 
214
+ def upload_mapping(path_to_mapping, apk_version_code)
215
+ ensure_active_edit!
216
+
217
+ call_google_api do
218
+ android_publisher.upload_edit_deobfuscationfile(
219
+ current_package_name,
220
+ current_edit.id,
221
+ apk_version_code,
222
+ "proguard",
223
+ upload_source: path_to_mapping,
224
+ content_type: "application/octet-stream"
225
+ )
226
+ end
227
+ end
228
+
214
229
  # Updates the track for the provided version code(s)
215
230
  def update_track(track, rollout, apk_version_code)
216
231
  ensure_active_edit!
@@ -127,7 +127,29 @@ module Supply
127
127
  optional: true,
128
128
  description: "Indicate that changes will only be validated with Google Play rather than actually published",
129
129
  is_string: false,
130
- default_value: false)
130
+ default_value: false),
131
+ FastlaneCore::ConfigItem.new(key: :mapping,
132
+ env_name: "SUPPLY_MAPPING",
133
+ description: "Path to the mapping file to upload",
134
+ short_option: "-d",
135
+ conflicting_options: [:mapping_paths],
136
+ optional: true,
137
+ verify_block: proc do |value|
138
+ UI.user_error! "Could not find mapping file at path '#{value}'" unless File.exist?(value)
139
+ end),
140
+ FastlaneCore::ConfigItem.new(key: :mapping_paths,
141
+ env_name: "SUPPLY_MAPPING_PATHS",
142
+ conflicting_options: [:mapping],
143
+ optional: true,
144
+ type: Array,
145
+ description: "An array of paths to mapping files to upload",
146
+ short_option: "-s",
147
+ verify_block: proc do |value|
148
+ UI.user_error!("Could not evaluate array from '#{value}'") unless value.kind_of?(Array)
149
+ value.each do |path|
150
+ UI.user_error! "Could not find mapping file at path '#{path}'" unless File.exist?(path)
151
+ end
152
+ end)
131
153
 
132
154
  ]
133
155
  end
@@ -115,6 +115,13 @@ module Supply
115
115
  apk_version_codes.push(upload_binary_data(apk_path))
116
116
  end
117
117
 
118
+ mapping_paths = [Supply.config[:mapping]] unless (mapping_paths = Supply.config[:mapping_paths])
119
+ mapping_paths.zip(apk_version_codes).each do |mapping_path, version_code|
120
+ if mapping_path
121
+ client.upload_mapping(mapping_path, version_code)
122
+ end
123
+ end
124
+
118
125
  update_track(apk_version_codes)
119
126
  end
120
127
 
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.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2017-01-03 00:00:00.000000000 Z
17
+ date: 2017-01-04 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: slack-notifier