fastlane 2.4.0 → 2.5.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 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