fastlane 1.92.0.beta2 → 1.92.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -2
  3. data/lib/fastlane.rb +0 -1
  4. data/lib/fastlane/action_collector.rb +2 -34
  5. data/lib/fastlane/actions/actions_helper.rb +0 -4
  6. data/lib/fastlane/actions/appium.rb +1 -1
  7. data/lib/fastlane/actions/changelog_from_git_commits.rb +4 -0
  8. data/lib/fastlane/actions/copy_artifacts.rb +26 -14
  9. data/lib/fastlane/actions/gradle.rb +1 -1
  10. data/lib/fastlane/actions/increment_build_number.rb +1 -1
  11. data/lib/fastlane/actions/increment_version_number.rb +1 -1
  12. data/lib/fastlane/actions/jira.rb +1 -1
  13. data/lib/fastlane/actions/onesignal.rb +1 -1
  14. data/lib/fastlane/actions/pod_lib_lint.rb +22 -1
  15. data/lib/fastlane/actions/push_to_git_remote.rb +1 -1
  16. data/lib/fastlane/actions/slather.rb +49 -21
  17. data/lib/fastlane/actions/upload_symbols_to_sentry.rb +1 -0
  18. data/lib/fastlane/actions/xcake.rb +35 -0
  19. data/lib/fastlane/commands_generator.rb +11 -62
  20. data/lib/fastlane/lane_manager.rb +2 -6
  21. data/lib/fastlane/one_off.rb +1 -7
  22. data/lib/fastlane/runner.rb +12 -34
  23. data/lib/fastlane/version.rb +1 -1
  24. metadata +32 -83
  25. data/lib/assets/Plugins.md.erb +0 -8
  26. data/lib/fastlane/plugins/plugin_fetcher.rb +0 -59
  27. data/lib/fastlane/plugins/plugin_generator.rb +0 -109
  28. data/lib/fastlane/plugins/plugin_generator_ui.rb +0 -19
  29. data/lib/fastlane/plugins/plugin_info.rb +0 -47
  30. data/lib/fastlane/plugins/plugin_info_collector.rb +0 -120
  31. data/lib/fastlane/plugins/plugin_manager.rb +0 -333
  32. data/lib/fastlane/plugins/plugin_search.rb +0 -46
  33. data/lib/fastlane/plugins/plugins.rb +0 -7
  34. data/lib/fastlane/plugins/templates/Gemfile.erb +0 -3
  35. data/lib/fastlane/plugins/templates/LICENSE.erb +0 -21
  36. data/lib/fastlane/plugins/templates/README.md.erb +0 -31
  37. data/lib/fastlane/plugins/templates/Rakefile.erb +0 -1
  38. data/lib/fastlane/plugins/templates/action.rb.erb +0 -35
  39. data/lib/fastlane/plugins/templates/action_spec.rb.erb +0 -9
  40. data/lib/fastlane/plugins/templates/assets/fastlane_logo.png +0 -0
  41. data/lib/fastlane/plugins/templates/assets/plugin-badge.svg +0 -1
  42. data/lib/fastlane/plugins/templates/dot_gitignore.erb +0 -8
  43. data/lib/fastlane/plugins/templates/dot_rspec.erb +0 -3
  44. data/lib/fastlane/plugins/templates/helper.rb.erb +0 -12
  45. data/lib/fastlane/plugins/templates/plugin.gemspec.erb +0 -26
  46. data/lib/fastlane/plugins/templates/plugin.rb.erb +0 -16
  47. data/lib/fastlane/plugins/templates/spec_helper.rb.erb +0 -8
  48. data/lib/fastlane/plugins/templates/version.rb.erb +0 -5
@@ -1,19 +0,0 @@
1
- module Fastlane
2
- class PluginGeneratorUI
3
- def success(text)
4
- puts text.green
5
- end
6
-
7
- def message(text)
8
- puts text
9
- end
10
-
11
- def input(text)
12
- UI.input(text)
13
- end
14
-
15
- def confirm(text)
16
- UI.confirm(text)
17
- end
18
- end
19
- end
@@ -1,47 +0,0 @@
1
- module Fastlane
2
- class PluginInfo
3
- attr_reader :plugin_name
4
- attr_reader :author
5
- attr_reader :gem_name
6
- attr_reader :email
7
- attr_reader :summary
8
-
9
- def initialize(plugin_name, author, email, summary)
10
- @plugin_name = plugin_name
11
- @author = author
12
- @email = email
13
- @summary = summary
14
- end
15
-
16
- def gem_name
17
- "#{Fastlane::PluginManager::FASTLANE_PLUGIN_PREFIX}#{plugin_name}"
18
- end
19
-
20
- def require_path
21
- gem_name.tr('-', '/')
22
- end
23
-
24
- def actions_path
25
- File.join(require_path, 'actions')
26
- end
27
-
28
- def helper_path
29
- File.join(require_path, 'helper')
30
- end
31
-
32
- # Used to expose a local binding for use in ERB templating
33
- #
34
- # rubocop:disable Style/AccessorMethodName
35
- def get_binding
36
- binding
37
- end
38
- # rubocop:enable Style/AccessorMethodName
39
-
40
- def ==(other)
41
- @plugin_name == other.plugin_name &&
42
- @author == other.author &&
43
- @email == other.email &&
44
- @summary == other.summary
45
- end
46
- end
47
- end
@@ -1,120 +0,0 @@
1
- module Fastlane
2
- class PluginInfoCollector
3
- def initialize(ui = PluginGeneratorUI.new)
4
- @ui = ui
5
- end
6
-
7
- def collect_info(initial_name = nil)
8
- plugin_name = collect_plugin_name(initial_name)
9
- author = collect_author
10
- email = collect_email
11
- summary = collect_summary
12
-
13
- PluginInfo.new(plugin_name, author, email, summary)
14
- end
15
-
16
- #
17
- # Plugin name
18
- #
19
-
20
- def collect_plugin_name(initial_name = nil)
21
- plugin_name = initial_name
22
- first_try = true
23
-
24
- loop do
25
- if !first_try || plugin_name.to_s.empty?
26
- plugin_name = @ui.input("\nWhat would you like to be the name of your plugin?")
27
- end
28
- first_try = false
29
-
30
- unless plugin_name_valid?(plugin_name)
31
- fixed_name = fix_plugin_name(plugin_name)
32
-
33
- if plugin_name_valid?(fixed_name)
34
- plugin_name = fixed_name if @ui.confirm("\nWould '#{fixed_name}' be okay to use for your plugin name?")
35
- end
36
- end
37
-
38
- break if plugin_name_valid?(plugin_name)
39
-
40
- @ui.message("\nPlugin names can only contain lower case letters, numbers, and underscores")
41
- @ui.message("and should not contain 'fastlane' or 'plugin'.")
42
- end
43
-
44
- plugin_name
45
- end
46
-
47
- def plugin_name_valid?(name)
48
- # Only lower case letters, numbers and underscores allowed
49
- /^[a-z0-9_]+$/ =~ name &&
50
- # Does not contain the words 'fastlane' or 'plugin' since those will become
51
- # part of the gem name
52
- [/fastlane/, /plugin/].none? { |regex| regex =~ name }
53
- end
54
-
55
- # Applies a series of replacement rules to turn the requested plugin name into one
56
- # that is acceptable, returning that suggestion
57
- def fix_plugin_name(name)
58
- name = name.to_s.downcase
59
- fixes = {
60
- /[\- ]/ => '_', # dashes and spaces become underscores
61
- /[^a-z0-9_]/ => '', # anything other than lower case letters, numbers and underscores is removed
62
- /fastlane[_]?/ => '', # 'fastlane' or 'fastlane_' is removed
63
- /plugin[_]?/ => '' # 'plugin' or 'plugin_' is removed
64
- }
65
- fixes.each do |regex, replacement|
66
- name = name.gsub(regex, replacement)
67
- end
68
- name
69
- end
70
-
71
- #
72
- # Author
73
- #
74
-
75
- def collect_author
76
- author = nil
77
- loop do
78
- author = @ui.input("\nWhat is the plugin author's name?")
79
- break if author_valid?(author)
80
-
81
- @ui.message('An author name is required.')
82
- end
83
-
84
- author
85
- end
86
-
87
- def author_valid?(author)
88
- !author.to_s.strip.empty?
89
- end
90
-
91
- #
92
- # Email
93
- #
94
-
95
- def collect_email
96
- @ui.input("\nWhat is the plugin author's email address?")
97
- end
98
-
99
- #
100
- # Summary
101
- #
102
-
103
- def collect_summary
104
- summary = nil
105
- loop do
106
- summary = @ui.input("\nPlease enter a short summary of this fastlane plugin:")
107
- break if summary_valid?(summary)
108
-
109
- @ui.message('A summary is required.')
110
- end
111
-
112
- summary
113
- end
114
-
115
- def summary_valid?(summary)
116
- !summary.to_s.strip.empty?
117
- end
118
-
119
- end
120
- end
@@ -1,333 +0,0 @@
1
- module Fastlane
2
- class PluginManager
3
- require "bundler"
4
-
5
- PLUGINFILE_NAME = "Pluginfile".freeze
6
- DEFAULT_GEMFILE_PATH = "Gemfile".freeze
7
- GEMFILE_SOURCE_LINE = "source \"https://rubygems.org\"\n"
8
- FASTLANE_PLUGIN_PREFIX = "fastlane-plugin-"
9
- TROUBLESHOOTING_URL = "https://github.com/fastlane/fastlane/blob/master/fastlane/docs/PluginsTroubleshooting.md"
10
-
11
- #####################################################
12
- # @!group Reading the files and their paths
13
- #####################################################
14
-
15
- def gemfile_path
16
- # This is pretty important, since we don't know what kind of
17
- # Gemfile the user has (e.g. Gemfile, gems.rb, or custom env variable)
18
- Bundler::SharedHelpers.default_gemfile.to_s
19
- rescue Bundler::GemfileNotFound
20
- nil
21
- end
22
-
23
- def pluginfile_path
24
- File.join(FastlaneFolder.path, PLUGINFILE_NAME) if FastlaneFolder.path
25
- end
26
-
27
- def gemfile_content
28
- File.read(gemfile_path) if gemfile_path && File.exist?(gemfile_path)
29
- end
30
-
31
- def pluginfile_content
32
- File.read(pluginfile_path) if pluginfile_path && File.exist?(pluginfile_path)
33
- end
34
-
35
- #####################################################
36
- # @!group Helpers
37
- #####################################################
38
-
39
- def self.plugin_prefix
40
- FASTLANE_PLUGIN_PREFIX
41
- end
42
-
43
- # Returns an array of gems that are added to the Gemfile or Pluginfile
44
- def available_gems
45
- return [] unless gemfile_path
46
- dsl = Bundler::Dsl.evaluate(gemfile_path, nil, true)
47
- return dsl.dependencies.map(&:name)
48
- end
49
-
50
- # Returns an array of fastlane plugins that are added to the Gemfile or Pluginfile
51
- # The returned array contains the string with their prefixes (e.g. fastlane-plugin-xcversion)
52
- def available_plugins
53
- available_gems.keep_if do |current|
54
- current.start_with?(self.class.plugin_prefix)
55
- end
56
- end
57
-
58
- # Check if a plugin is added as dependency to either the
59
- # Gemfile or the Pluginfile
60
- def plugin_is_added_as_dependency?(plugin_name)
61
- UI.user_error!("fastlane plugins must start with '#{self.class.plugin_prefix}' string") unless plugin_name.start_with?(self.class.plugin_prefix)
62
- return available_plugins.include?(plugin_name)
63
- end
64
-
65
- #####################################################
66
- # @!group Modifying dependencies
67
- #####################################################
68
-
69
- def add_dependency(plugin_name)
70
- plugin_name = self.class.plugin_prefix + plugin_name unless plugin_name.start_with?(self.class.plugin_prefix)
71
-
72
- unless plugin_is_added_as_dependency?(plugin_name)
73
- content = pluginfile_content || "# Autogenerated by fastlane\n\n"
74
-
75
- line_to_add = "gem '#{plugin_name}'"
76
- line_to_add += gem_dependency_suffix(plugin_name)
77
- UI.verbose("Adding line: #{line_to_add}")
78
-
79
- content += "#{line_to_add}\n"
80
- File.write(pluginfile_path, content)
81
- UI.success("Plugin '#{plugin_name}' was added to '#{pluginfile_path}'")
82
- end
83
-
84
- # We do this *after* creating the Plugin file
85
- # Since `bundle exec` would be broken if something fails on the way
86
- ensure_plugins_attached!
87
-
88
- true
89
- end
90
-
91
- # Get a suffix (e.g. `path` or `git` for the gem dependency)
92
- def gem_dependency_suffix(plugin_name)
93
- return "" unless self.class.fetch_gem_info_from_rubygems(plugin_name).nil?
94
-
95
- selection_git_url = "Git URL"
96
- selection_path = "Local Path"
97
- selection_rubygems = "RubyGems.org ('#{plugin_name}' seems to not be available there)"
98
- selection = UI.select(
99
- "Seems like the plugin is not available on RubyGems, what do you want to do?",
100
- [selection_git_url, selection_path, selection_rubygems]
101
- )
102
-
103
- if selection == selection_git_url
104
- git_url = UI.input('Please enter the URL to the plugin, including the protocol (e.g. https:// or git://)')
105
- return ", git: '#{git_url}'"
106
- elsif selection == selection_path
107
- path = UI.input('Please enter the relative path to the plugin you want to use. It has to point to the directory containing the .gemspec file')
108
- return ", path: '#{path}'"
109
- elsif selection == selection_rubygems
110
- return ""
111
- else
112
- UI.user_error!("Unknown input #{selection}")
113
- end
114
- end
115
-
116
- # Modify the user's Gemfile to load the plugins
117
- def attach_plugins_to_gemfile!(path_to_gemfile)
118
- content = gemfile_content || GEMFILE_SOURCE_LINE
119
-
120
- # We have to make sure fastlane is also added to the Gemfile, since we now use
121
- # bundler to run fastlane
122
- content += "\ngem 'fastlane'\n" unless available_gems.include?('fastlane')
123
- content += "\n#{self.class.code_to_attach}\n"
124
-
125
- File.write(path_to_gemfile, content)
126
- end
127
-
128
- #####################################################
129
- # @!group Accessing RubyGems
130
- #####################################################
131
-
132
- def self.fetch_gem_info_from_rubygems(gem_name)
133
- require 'open-uri'
134
- require 'json'
135
- url = "https://rubygems.org/api/v1/gems/#{gem_name}.json"
136
- begin
137
- JSON.parse(open(url).read)
138
- rescue
139
- nil
140
- end
141
- end
142
-
143
- #####################################################
144
- # @!group Installing and updating dependencies
145
- #####################################################
146
-
147
- # Warning: This will exec out
148
- # This is necessary since the user might be prompted for their password
149
- def install_dependencies!
150
- # Using puts instead of `UI` to have the same style as the `echo`
151
- puts "Installing plugin dependencies..."
152
- ensure_plugins_attached!
153
- with_clean_bundler_env do
154
- cmd = "bundle install"
155
- cmd << " --quiet" unless $verbose
156
- cmd << " && echo 'Successfully installed plugins'"
157
- UI.command(cmd) if $verbose
158
- exec(cmd)
159
- end
160
- end
161
-
162
- # Warning: This will exec out
163
- # This is necessary since the user might be prompted for their password
164
- def update_dependencies!
165
- puts "Updating plugin dependencies..."
166
- ensure_plugins_attached!
167
- with_clean_bundler_env do
168
- cmd = "bundle update"
169
- cmd << " --quiet" unless $verbose
170
- cmd << " && echo 'Successfully updated plugins'"
171
- UI.command(cmd) if $verbose
172
- exec(cmd)
173
- end
174
- end
175
-
176
- def with_clean_bundler_env
177
- # There is an interesting problem with using exec to call back into Bundler
178
- # The `bundle ________` command that we exec, inherits all of the Bundler
179
- # state we'd already built up during this run. That was causing the command
180
- # to fail, telling us to install the Gem we'd just introduced, even though
181
- # that is exactly what we are trying to do!
182
- #
183
- # Bundler.with_clean_env solves this problem by resetting Bundler state before the
184
- # exec'd call gets merged into this process.
185
-
186
- Bundler.with_clean_env do
187
- yield if block_given?
188
- end
189
- end
190
-
191
- #####################################################
192
- # @!group Initial setup
193
- #####################################################
194
-
195
- def setup
196
- UI.important("It looks like fastlane plugins are not yet set up for this project.")
197
-
198
- path_to_gemfile = gemfile_path || DEFAULT_GEMFILE_PATH
199
-
200
- if gemfile_content.to_s.length > 0
201
- UI.important("fastlane will modify your existing Gemfile at path '#{path_to_gemfile}'")
202
- else
203
- UI.important("fastlane will create a new Gemfile at path '#{path_to_gemfile}'")
204
- end
205
-
206
- UI.important("This change is neccessary for fastlane plugins to work")
207
-
208
- unless UI.confirm("Should fastlane modify the Gemfile at path '#{path_to_gemfile}' for you?")
209
- UI.important("Please add the following code to '#{path_to_gemfile}':")
210
- puts ""
211
- puts self.class.code_to_attach.magenta # we use `puts` instead of `UI` to make it easier to copy and paste
212
- UI.user_error!("Please update '#{path_to_gemfile} and run fastlane again")
213
- end
214
-
215
- attach_plugins_to_gemfile!(path_to_gemfile)
216
- UI.success("Successfully modified '#{path_to_gemfile}'")
217
- end
218
-
219
- # The code required to load the Plugins file
220
- def self.code_to_attach
221
- if FastlaneFolder.path
222
- fastlane_folder_name = File.basename(FastlaneFolder.path)
223
- else
224
- fastlane_folder_name = "fastlane"
225
- end
226
- "plugins_path = File.join(File.dirname(__FILE__), '#{fastlane_folder_name}', '#{PluginManager::PLUGINFILE_NAME}')\n" \
227
- "eval(File.read(plugins_path), binding) if File.exist?(plugins_path)"
228
- end
229
-
230
- # Makes sure, the user's Gemfile actually loads the Plugins file
231
- def plugins_attached?
232
- gemfile_path && gemfile_content.include?(self.class.code_to_attach)
233
- end
234
-
235
- def ensure_plugins_attached!
236
- return if plugins_attached?
237
- self.setup
238
- end
239
-
240
- #####################################################
241
- # @!group Requiring the plugins
242
- #####################################################
243
-
244
- # Iterate over all available plugins
245
- # which follow the naming convention
246
- # fastlane-plugin-[plugin_name]
247
- # This will make sure to load the action
248
- # and all its helpers
249
- def self.load_plugins
250
- UI.verbose("Checking if there are any plugins that should be loaded...")
251
-
252
- loaded_plugins = false
253
- Gem::Specification.each do |current_gem|
254
- gem_name = current_gem.name
255
- next unless gem_name.start_with?(PluginManager.plugin_prefix)
256
-
257
- UI.verbose("Loading '#{gem_name}' plugin")
258
- begin
259
- require gem_name.tr("-", "/") # from "fastlane-plugin-xcversion" to "fastlane/plugin/xcversion"
260
- store_plugin_reference(gem_name)
261
- loaded_plugins = true
262
- rescue => ex
263
- UI.error("Error loading plugin '#{gem_name}': #{ex}")
264
-
265
- # We'll still add it to the table, to make the error
266
- # much more visible and obvious
267
- self.plugin_references[gem_name] = {
268
- version_number: Fastlane::ActionCollector.determine_version(gem_name),
269
- actions: []
270
- }
271
- end
272
- end
273
-
274
- if !loaded_plugins && PluginManager.new.pluginfile_content.to_s.include?(plugin_prefix)
275
- UI.error("It seems like you wanted to load some plugins, however they couldn't be loaded")
276
- UI.error("Please follow the troubleshooting guide: #{TROUBLESHOOTING_URL}")
277
- end
278
-
279
- print_plugin_information(self.plugin_references) unless self.plugin_references.empty?
280
- end
281
-
282
- # Prints a table all the plugins that were loaded
283
- def self.print_plugin_information(references)
284
- rows = references.collect do |current|
285
- if current[1][:actions].empty?
286
- # Something is wrong with this plugin, no available actions
287
- [current[0].red, current[1][:version_number], "No actions found".red]
288
- else
289
- [current[0], current[1][:version_number], current[1][:actions].join("\n")]
290
- end
291
- end
292
-
293
- puts Terminal::Table.new({
294
- rows: rows,
295
- title: "Used plugins".green,
296
- headings: ["Plugin", "Version", "Action"]
297
- })
298
- puts ""
299
- end
300
-
301
- #####################################################
302
- # @!group Reference between plugins to actions
303
- #####################################################
304
-
305
- # Connection between plugins and their actions
306
- # Example value of plugin_references
307
- # => {"fastlane-plugin-ruby" => {
308
- # version_number: "0.1.0",
309
- # actions: [:rspec, :rubocop]
310
- # }}
311
- def self.plugin_references
312
- @plugin_references ||= {}
313
- end
314
-
315
- def self.store_plugin_reference(gem_name)
316
- module_name = gem_name.gsub(PluginManager.plugin_prefix, '').fastlane_class
317
- # We store a collection of the imported plugins
318
- # This way we can tell which action came from what plugin
319
- # (a plugin may contain any number of actions)
320
- version_number = Fastlane::ActionCollector.determine_version(gem_name)
321
- references = Fastlane.const_get(module_name).all_classes.collect do |path|
322
- next unless File.dirname(path).end_with?("/actions") # we only want to match actions
323
-
324
- File.basename(path).gsub("_action", "").gsub(".rb", "").to_sym # the _action is optional
325
- end
326
-
327
- self.plugin_references[gem_name] = {
328
- version_number: version_number,
329
- actions: references.keep_if { |a| !a.nil? }
330
- }
331
- end
332
- end
333
- end