fastlane 1.92.0 → 1.93.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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/assets/AvailablePlugins.md.erb +24 -0
  3. data/lib/fastlane.rb +13 -6
  4. data/lib/fastlane/action_collector.rb +35 -2
  5. data/lib/fastlane/actions/actions_helper.rb +4 -0
  6. data/lib/fastlane/commands_generator.rb +61 -1
  7. data/lib/fastlane/lane.rb +1 -1
  8. data/lib/fastlane/lane_manager.rb +6 -2
  9. data/lib/fastlane/one_off.rb +7 -1
  10. data/lib/fastlane/plugins/plugin_fetcher.rb +59 -0
  11. data/lib/fastlane/plugins/plugin_generator.rb +86 -0
  12. data/lib/fastlane/plugins/plugin_generator_ui.rb +19 -0
  13. data/lib/fastlane/plugins/plugin_info.rb +47 -0
  14. data/lib/fastlane/plugins/plugin_info_collector.rb +150 -0
  15. data/lib/fastlane/plugins/plugin_manager.rb +358 -0
  16. data/lib/fastlane/plugins/plugin_search.rb +46 -0
  17. data/lib/fastlane/plugins/plugins.rb +11 -0
  18. data/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +26 -0
  19. data/lib/fastlane/plugins/template/Gemfile +3 -0
  20. data/lib/fastlane/plugins/template/LICENSE.erb +21 -0
  21. data/lib/fastlane/plugins/template/README.md.erb +31 -0
  22. data/lib/fastlane/plugins/template/Rakefile +1 -0
  23. data/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%.rb.erb +16 -0
  24. data/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +35 -0
  25. data/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +12 -0
  26. data/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/version.rb.erb +5 -0
  27. data/lib/fastlane/plugins/template/spec/%plugin_name%_action_spec.rb.erb +9 -0
  28. data/lib/fastlane/plugins/template/spec/spec_helper.rb.erb +10 -0
  29. data/lib/fastlane/runner.rb +34 -12
  30. data/lib/fastlane/version.rb +1 -1
  31. metadata +60 -27
  32. data/lib/fastlane/actions/xcake.rb +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5a8f36b44fdba28a2384ebaaf3ed6c19640e4ed
4
- data.tar.gz: 97d37d0093e30964336a875e744ddc468b1ebdd9
3
+ metadata.gz: 3c67117c9fa728e8d4a628cd5ab40a74f615dfd1
4
+ data.tar.gz: 1397336e43b8257f610df1af93f04532a8480d18
5
5
  SHA512:
6
- metadata.gz: 9b767890903852e42d1a7a56b0ce9cb18649934ae69ed719534f6f3178f1595e3feeef445bd59f89c860d6a4e028878ce5359ec156627e9c12d58d01b5930270
7
- data.tar.gz: c55a8e615c2e69bb69388316c3618a58d8156d3ecd86b9da53ee9ea8d6f0816e16cf400b4ac9bf1929d3f1a89b68f7181c74221d06a3929e2e9a165d67758671
6
+ metadata.gz: c7400de730419a6c95102c79d32c623a267da6e540c2620241e12d645da46648d3433e36a8c344b5e0e49076607c75c0932e107ace0a4bb4dc0607e1d3666805
7
+ data.tar.gz: f91ff6eb451eff605418e3dc2416402bb7affc8448df7114ffcf13094e402772b74759d8f04b2e0de6f3e2abdaf21fa0e7e46774ce7bd78942d731df1c845b26
@@ -0,0 +1,24 @@
1
+ ### Available Plugins
2
+
3
+ To get an up to date list of all available plugins run
4
+
5
+ ```
6
+ fastlane search_plugins
7
+ ```
8
+
9
+ To search for a specific plugin
10
+
11
+ ```
12
+ fastlane search_plugins [search_query]
13
+ ```
14
+
15
+ You can find more information about how to start using plugins in [Plugins.md](https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Plugins.md).
16
+
17
+ #### List of plugins
18
+
19
+ | Plugin Name | Description | Downloads
20
+ --------------|-------------|----------|----------
21
+ <% @plugins.each do |current| %>
22
+ <%= current.linked_title %> | <%= current.info %> | <%= current.downloads %>
23
+
24
+ <% end %>
data/lib/fastlane.rb CHANGED
@@ -18,18 +18,25 @@ require 'fastlane/one_off'
18
18
  require 'fastlane/command_line_handler'
19
19
  require 'fastlane/documentation/docs_generator'
20
20
  require 'fastlane/other_action'
21
+ require 'fastlane/plugins/plugins'
21
22
 
22
23
  module Fastlane
23
24
  Helper = FastlaneCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in FastlaneCore
24
25
  UI = FastlaneCore::UI
25
26
 
26
- def self.load_actions
27
- Fastlane::Actions.load_default_actions
28
- Fastlane::Actions.load_helpers
27
+ class << self
28
+ def load_actions
29
+ Fastlane::Actions.load_default_actions
30
+ Fastlane::Actions.load_helpers
29
31
 
30
- if Fastlane::FastlaneFolder.path
31
- actions_path = File.join(Fastlane::FastlaneFolder.path, 'actions')
32
- Fastlane::Actions.load_external_actions(actions_path) if File.directory?(actions_path)
32
+ if Fastlane::FastlaneFolder.path
33
+ actions_path = File.join(Fastlane::FastlaneFolder.path, 'actions')
34
+ Fastlane::Actions.load_external_actions(actions_path) if File.directory?(actions_path)
35
+ end
36
+ end
37
+
38
+ def plugin_manager
39
+ @plugin_manager ||= Fastlane::PluginManager.new
33
40
  end
34
41
  end
35
42
  end
@@ -1,8 +1,19 @@
1
1
  module Fastlane
2
2
  class ActionCollector < FastlaneCore::ToolCollector
3
+ # Is this an official fastlane action, that is bundled with fastlane?
3
4
  def is_official?(name)
4
5
  return true if name == :lane_switch
5
- Actions.get_all_official_actions.include? name
6
+ Actions.get_all_official_actions.include?(name)
7
+ end
8
+
9
+ def name_to_track(name)
10
+ return name if is_official?(name)
11
+
12
+ Fastlane.plugin_manager.plugin_references.each do |plugin_name, value|
13
+ return "#{plugin_name}/#{name}" if value[:actions].include?(name)
14
+ end
15
+
16
+ return nil
6
17
  end
7
18
 
8
19
  def show_message
@@ -15,7 +26,29 @@ module Fastlane
15
26
  end
16
27
 
17
28
  def determine_version(name)
18
- super(name) || Fastlane::VERSION
29
+ self.class.determine_version(name)
30
+ end
31
+
32
+ # e.g.
33
+ # :gym
34
+ # :xcversion
35
+ # "fastlane-plugin-my_plugin/xcversion"
36
+ def self.determine_version(name)
37
+ result = super(name)
38
+ return result if result
39
+
40
+ if name.to_s.include?(PluginManager.plugin_prefix)
41
+ # That's an action from a plugin, we need to fetch its version number
42
+ begin
43
+ plugin_name = name.split("/").first.gsub(PluginManager.plugin_prefix, '')
44
+ return Fastlane.const_get(plugin_name.fastlane_class)::VERSION
45
+ rescue => ex
46
+ UI.verbose(ex)
47
+ return "undefined"
48
+ end
49
+ end
50
+
51
+ return Fastlane::VERSION # that's the case for all built-in actions
19
52
  end
20
53
  end
21
54
  end
@@ -101,5 +101,9 @@ module Fastlane
101
101
  end
102
102
  end
103
103
  end
104
+
105
+ def self.formerly_bundled_actions
106
+ ["xcake"]
107
+ end
104
108
  end
105
109
  end
@@ -8,8 +8,13 @@ module Fastlane
8
8
  include Commander::Methods
9
9
 
10
10
  def self.start
11
+ # since at this point we haven't yet loaded commander
12
+ # however we do want to log verbose information in the PluginManager
13
+ $verbose = true if ARGV.include?("--verbose")
14
+
11
15
  FastlaneCore::UpdateChecker.start_looking_for_update('fastlane')
12
16
  Fastlane.load_actions
17
+ Fastlane.plugin_manager.load_plugins
13
18
  self.new.run
14
19
  ensure
15
20
  FastlaneCore::UpdateChecker.show_update_status('fastlane', Fastlane::VERSION)
@@ -170,8 +175,63 @@ module Fastlane
170
175
  end
171
176
  end
172
177
 
173
- default_command :trigger
178
+ #####################################################
179
+ # @!group Plugins
180
+ #####################################################
181
+
182
+ command :new_plugin do |c|
183
+ c.syntax = 'fastlane new_plugin [plugin_name]'
184
+ c.description = 'Create a new plugin that can be used with fastlane'
185
+
186
+ c.action do |args, options|
187
+ PluginGenerator.new.generate(args.shift)
188
+ end
189
+ end
190
+
191
+ command :add_plugin do |c|
192
+ c.syntax = 'fastlane add_plugin [plugin_name]'
193
+ c.description = 'Add a new plugin to your fastlane setup'
194
+
195
+ c.action do |args, options|
196
+ args << UI.input("Enter the name of the plugin to install: ") if args.empty?
197
+ args.each do |plugin_name|
198
+ Fastlane.plugin_manager.add_dependency(plugin_name)
199
+ end
200
+
201
+ UI.important("Make sure to commit your Gemfile, Gemfile.lock and #{PluginManager::PLUGINFILE_NAME} to version control")
202
+ Fastlane.plugin_manager.install_dependencies!
203
+ end
204
+ end
205
+
206
+ command :install_plugins do |c|
207
+ c.syntax = 'fastlane install_plugins'
208
+ c.description = 'Install all plugins for this project'
174
209
 
210
+ c.action do |args, options|
211
+ Fastlane.plugin_manager.install_dependencies!
212
+ end
213
+ end
214
+
215
+ command :update_plugins do |c|
216
+ c.syntax = 'fastlane update_plugins'
217
+ c.description = 'Update all plugin dependencies'
218
+
219
+ c.action do |args, options|
220
+ Fastlane.plugin_manager.update_dependencies!
221
+ end
222
+ end
223
+
224
+ command :search_plugins do |c|
225
+ c.syntax = 'fastlane search_plugins [search_query]'
226
+ c.description = 'Search for plugins, search query is optional'
227
+
228
+ c.action do |args, options|
229
+ search_query = args.last
230
+ PluginSearch.print_plugins(search_query: search_query)
231
+ end
232
+ end
233
+
234
+ default_command :trigger
175
235
  run!
176
236
  end
177
237
 
data/lib/fastlane/lane.rb CHANGED
@@ -55,7 +55,7 @@ module Fastlane
55
55
  end
56
56
 
57
57
  def black_list
58
- %w(run init new_action lanes list docs action actions help)
58
+ %w(run init new_action lanes list docs action actions enable_auto_complete new_plugin add_plugin install_plugins update_plugins search_plugins help)
59
59
  end
60
60
 
61
61
  def gray_list
@@ -44,10 +44,14 @@ module Fastlane
44
44
  e = nil
45
45
  begin
46
46
  ff.runner.execute(lane, platform, parameters)
47
- rescue => ex
47
+ rescue Exception => ex # rubocop:disable Lint/RescueException
48
+ # We also catch Exception, since the implemented action might send a SystemExit signal
49
+ # (or similar). We still want to catch that, since we want properly finish running fastlane
50
+ # Tested with `xcake`, which throws a `Xcake::Informative` object
51
+
48
52
  UI.important 'Variable Dump:'.yellow
49
53
  UI.message Actions.lane_context
50
- UI.error ex.to_s
54
+ UI.error ex.to_s if ex.kind_of?(StandardError) # we don't want to print things like 'system exit'
51
55
  e = ex
52
56
  end
53
57
 
@@ -29,7 +29,13 @@ module Fastlane
29
29
  begin
30
30
  class_ref = Fastlane::Actions.const_get(class_name)
31
31
  rescue NameError
32
- UI.user_error!("Action '#{action}' not available, run `fastlane actions` to get a full list")
32
+ if Fastlane::Actions.formerly_bundled_actions.include?(action)
33
+ # This was a formerly bundled action which is now a plugin.
34
+ UI.verbose(caller.join("\n"))
35
+ UI.user_error!("The action '#{action}' is no longer bundled with fastlane. You can install it using `fastlane add_plugin #{action}`")
36
+ else
37
+ UI.user_error!("Action '#{action}' not available, run `fastlane actions` to get a full list")
38
+ end
33
39
  end
34
40
 
35
41
  r = Runner.new
@@ -0,0 +1,59 @@
1
+ module Fastlane
2
+ # Use the RubyGems API to get all fastlane plugins
3
+ class PluginFetcher
4
+ require 'fastlane_core'
5
+ require 'fastlane/plugins/plugin_manager'
6
+
7
+ # Returns an array of FastlanePlugin objects
8
+ def self.fetch_gems(search_query: nil)
9
+ require 'json'
10
+ require 'open-uri'
11
+ url = "https://rubygems.org/api/v1/search.json?query=#{PluginManager.plugin_prefix}"
12
+ results = JSON.parse(open(url).read)
13
+
14
+ plugins = results.collect do |current|
15
+ FastlanePlugin.new(current)
16
+ end
17
+
18
+ return plugins if search_query.to_s.length == 0
19
+
20
+ plugins.keep_if do |current|
21
+ current.full_name.include?(search_query)
22
+ end
23
+ end
24
+
25
+ def self.update_md_file!
26
+ @plugins = fetch_gems
27
+
28
+ lib_path = FastlaneCore::Helper.gem_path('fastlane')
29
+ template_path = File.join(lib_path, "lib/assets/AvailablePlugins.md.erb")
30
+ md = ERB.new(File.read(template_path), nil, '<>').result(binding) # http://www.rrn.dk/rubys-erb-templating-system
31
+
32
+ puts md
33
+ output_path = "docs/AvailablePlugins.md"
34
+ File.write(output_path, md)
35
+ FastlaneCore::UI.success("Successfully written plugin file to '#{output_path}'")
36
+ end
37
+ end
38
+
39
+ class FastlanePlugin
40
+ attr_accessor :full_name
41
+ attr_accessor :name
42
+ attr_accessor :downloads
43
+ attr_accessor :info
44
+ attr_accessor :homepage
45
+
46
+ def initialize(hash)
47
+ self.full_name = hash["name"]
48
+ self.name = self.full_name.gsub(PluginManager.plugin_prefix, '')
49
+ self.downloads = hash["downloads"]
50
+ self.info = hash["info"]
51
+ self.homepage = hash["homepage_uri"]
52
+ end
53
+
54
+ def linked_title
55
+ return "`#{name}`" if homepage.to_s.length == 0
56
+ return "[#{name}](#{homepage})"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,86 @@
1
+ module Fastlane
2
+ # Generates a sample plugin by traversing a template directory structure
3
+ # and reproducing it in a destination location. At the same time, it runs
4
+ # variable replacements on directory names, file names, and runs ERB
5
+ # templating on file contents whose names end with '.erb'.
6
+ #
7
+ # Directory and file name variable replacements are defined like: %gem_name%
8
+ # The text between the percent signs will be used to invoke an accessor
9
+ # method on the PluginInfo object to get the replacement value.
10
+ class PluginGenerator
11
+ def initialize(ui: PluginGeneratorUI.new,
12
+ info_collector: PluginInfoCollector.new(ui),
13
+ template_root: File.join(File.dirname(__FILE__), 'template'),
14
+ dest_root: FileUtils.pwd)
15
+ @ui = ui
16
+ @info_collector = info_collector
17
+ @template_root = template_root
18
+ @dest_root = dest_root
19
+ end
20
+
21
+ # entry point
22
+ def generate(plugin_name = nil)
23
+ plugin_info = @info_collector.collect_info(plugin_name)
24
+
25
+ # Traverse all the files and directories in the template root,
26
+ # handling each in turn
27
+ Find.find(@template_root) do |template_path|
28
+ handle_template_path(template_path, plugin_info)
29
+ end
30
+
31
+ @ui.success "\nYour plugin was successfully generated at #{plugin_info.gem_name}/ 🚀"
32
+ @ui.success "\nTo get started with using this plugin, run"
33
+ @ui.message "\n fastlane add_plugin #{plugin_info.plugin_name}\n"
34
+ @ui.success "\nfrom a fastlane-enabled app project directory and provide the following as the path:"
35
+ @ui.message "\n #{File.expand_path(plugin_info.gem_name)}\n\n"
36
+ end
37
+
38
+ def handle_template_path(template_path, plugin_info)
39
+ dest_path = derive_dest_path(template_path, plugin_info)
40
+
41
+ if File.directory?(template_path)
42
+ FileUtils.mkdir_p(dest_path)
43
+ else
44
+ copy_file(template_path, dest_path, plugin_info)
45
+ end
46
+ end
47
+
48
+ def derive_dest_path(template_path, plugin_info)
49
+ relative_template_path = template_path.gsub(@template_root, '')
50
+ replaced_path = replace_path_variables(relative_template_path, plugin_info)
51
+
52
+ File.join(@dest_root, plugin_info.gem_name, replaced_path)
53
+ end
54
+
55
+ def copy_file(template_path, dest_path, plugin_info)
56
+ contents = File.read(template_path)
57
+
58
+ if dest_path.end_with?('.erb')
59
+ contents = ERB.new(contents).result(plugin_info.get_binding)
60
+ dest_path = dest_path[0...-4] # Remove the .erb suffix
61
+ end
62
+
63
+ File.write(dest_path, contents)
64
+ end
65
+
66
+ # Path variables can be defined like: %gem_name%
67
+ #
68
+ # The text between the percent signs will be used to invoke an accessor
69
+ # method on the PluginInfo object to be the replacement value.
70
+ def replace_path_variables(template_path, plugin_info)
71
+ path = template_path.dup
72
+
73
+ loop do
74
+ replacement_variable_regexp = /%([\w\-]*)%/
75
+ match = replacement_variable_regexp.match(path)
76
+
77
+ break unless match
78
+
79
+ replacement_value = plugin_info.send(match[1].to_sym)
80
+ path.gsub!(replacement_variable_regexp, replacement_value)
81
+ end
82
+
83
+ path
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,19 @@
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
@@ -0,0 +1,47 @@
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