Class: Fastlane::Runner
- Inherits:
-
Object
- Object
- Fastlane::Runner
- Defined in:
- lib/fastlane/runner.rb
Defined Under Namespace
Classes: LaneNotAvailableError
Instance Attribute Summary collapse
-
#current_lane ⇒ Object
Symbol for the current lane.
-
#current_platform ⇒ Object
Symbol for the current platform.
-
#lanes ⇒ Hash
All the lanes available, first the platform, then the lane.
Instance Method Summary collapse
- #add_lane(lane, override = false) ⇒ Object
- #after_all_blocks ⇒ Object
- #after_each_blocks ⇒ Object
-
#available_lanes(filter_platform = nil) ⇒ Object
An array of lanes (platform lane_name) to print them out to the user.
- #before_all_blocks ⇒ Object
- #before_each_blocks ⇒ Object
-
#class_reference_from_action_name(method_sym) ⇒ Object
Pass a action symbol (e.g. :deliver or :commit_version_bump) and this method will return a reference to the action class if it exists.
- #collector ⇒ Object
-
#did_finish ⇒ Object
Fastfile was finished executing.
- #error_blocks ⇒ Object
-
#execute(lane, platform = nil, parameters = nil) ⇒ Object
This will take care of executing one lane.
- #execute_action(method_sym, class_ref, arguments, custom_dir: nil) ⇒ Object
- #execute_flow_block(block, current_platform, lane, parameters) ⇒ Object
- #full_lane_name ⇒ Object
- #set_after_all(platform, block) ⇒ Object
- #set_after_each(platform, block) ⇒ Object
- #set_before_all(platform, block) ⇒ Object
- #set_before_each(platform, block) ⇒ Object
- #set_error(platform, block) ⇒ Object
-
#trigger_action_by_name(method_sym, custom_dir, *arguments) ⇒ Object
This is being called from ‘method_missing` from the Fastfile It’s also used when an action is called from another action.
- #try_switch_to_lane(new_lane, parameters) ⇒ Object
- #verify_supported_os(name, class_ref) ⇒ Object
Instance Attribute Details
#current_lane ⇒ Object
Symbol for the current lane
4 5 6 |
# File 'lib/fastlane/runner.rb', line 4 def current_lane @current_lane end |
#current_platform ⇒ Object
Symbol for the current platform
7 8 9 |
# File 'lib/fastlane/runner.rb', line 7 def current_platform @current_platform end |
#lanes ⇒ Hash
Returns All the lanes available, first the platform, then the lane.
10 11 12 |
# File 'lib/fastlane/runner.rb', line 10 def lanes @lanes end |
Instance Method Details
#add_lane(lane, override = false) ⇒ Object
248 249 250 251 252 253 254 255 256 |
# File 'lib/fastlane/runner.rb', line 248 def add_lane(lane, override = false) lanes[lane.platform] ||= {} if !override and lanes[lane.platform][lane.name] UI.user_error!("Lane '#{lane.name}' was defined multiple times!") end lanes[lane.platform][lane.name] = lane end |
#after_all_blocks ⇒ Object
294 295 296 |
# File 'lib/fastlane/runner.rb', line 294 def after_all_blocks @after_all ||= {} end |
#after_each_blocks ⇒ Object
286 287 288 |
# File 'lib/fastlane/runner.rb', line 286 def after_each_blocks @after_each ||= {} end |
#available_lanes(filter_platform = nil) ⇒ Object
Returns an array of lanes (platform lane_name) to print them out to the user.
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/fastlane/runner.rb', line 73 def available_lanes(filter_platform = nil) all = [] lanes.each do |platform, platform_lanes| next if filter_platform && filter_platform.to_s != platform.to_s # skip actions that don't match platform_lanes.each do |lane_name, lane| all << [platform, lane_name].reject(&:nil?).join(' ') unless lane.is_private end end all end |
#before_all_blocks ⇒ Object
290 291 292 |
# File 'lib/fastlane/runner.rb', line 290 def before_all_blocks @before_all ||= {} end |
#before_each_blocks ⇒ Object
282 283 284 |
# File 'lib/fastlane/runner.rb', line 282 def before_each_blocks @before_each ||= {} end |
#class_reference_from_action_name(method_sym) ⇒ Object
Pass a action symbol (e.g. :deliver or :commit_version_bump) and this method will return a reference to the action class if it exists. In case the action with this name can’t be found this method will return nil. This method is being called by ‘trigger_action_by_name` to see if a given action is available (either built-in or loaded from a plugin) and is also being called from the fastlane docs generator
92 93 94 95 96 97 98 |
# File 'lib/fastlane/runner.rb', line 92 def class_reference_from_action_name(method_sym) method_str = method_sym.to_s.delete("?") # as a `?` could be at the end of the method name class_ref = Actions.action_class_ref(method_str) return class_ref if class_ref && class_ref.respond_to?(:run) nil end |
#collector ⇒ Object
235 236 237 |
# File 'lib/fastlane/runner.rb', line 235 def collector @collector ||= ActionCollector.new end |
#did_finish ⇒ Object
Fastfile was finished executing
240 241 242 |
# File 'lib/fastlane/runner.rb', line 240 def did_finish collector.did_finish end |
#error_blocks ⇒ Object
298 299 300 |
# File 'lib/fastlane/runner.rb', line 298 def error_blocks @error_blocks ||= {} end |
#execute(lane, platform = nil, parameters = nil) ⇒ Object
This will take care of executing one lane. That’s when the user triggers a lane from the CLI for example This method is not executed when switching a lane
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/fastlane/runner.rb', line 21 def execute(lane, platform = nil, parameters = nil) UI.crash!("No lane given") unless lane self.current_lane = lane.to_sym self.current_platform = (platform ? platform.to_sym : nil) lane_obj = lanes.fetch(current_platform, {}).fetch(current_lane, nil) UI.user_error!("Could not find lane '#{full_lane_name}'. Available lanes: #{available_lanes.join(', ')}") unless lane_obj UI.user_error!("You can't call the private lane '#{lane}' directly") if lane_obj.is_private ENV["FASTLANE_LANE_NAME"] = current_lane.to_s ENV["FASTLANE_PLATFORM_NAME"] = (current_platform ? current_platform.to_s : nil) Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] = current_platform Actions.lane_context[Actions::SharedValues::LANE_NAME] = full_lane_name UI.success "Driving the lane '#{full_lane_name}' 🚀" return_val = nil path_to_use = Fastlane::FastlaneFolder.path || Dir.pwd parameters ||= {} begin Dir.chdir(path_to_use) do # the file is located in the fastlane folder execute_flow_block(before_all_blocks, current_platform, current_lane, parameters) execute_flow_block(before_each_blocks, current_platform, current_lane, parameters) return_val = lane_obj.call(parameters) # by default no parameters # after blocks are only called if no exception was raised before # Call the platform specific after block and then the general one execute_flow_block(after_each_blocks, current_platform, current_lane, parameters) execute_flow_block(after_all_blocks, current_platform, current_lane, parameters) end return return_val rescue => ex Dir.chdir(path_to_use) do # Provide error block exception without colour code error_ex = ex.exception(ex..gsub(/\033\[\d+m/, '')) error_blocks[current_platform].call(current_lane, error_ex, parameters) if error_blocks[current_platform] && current_platform error_blocks[nil].call(current_lane, error_ex, parameters) if error_blocks[nil] end raise ex end end |
#execute_action(method_sym, class_ref, arguments, custom_dir: nil) ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/fastlane/runner.rb', line 179 def execute_action(method_sym, class_ref, arguments, custom_dir: nil) custom_dir ||= '..' collector.did_launch_action(method_sym) verify_supported_os(method_sym, class_ref) begin Dir.chdir(custom_dir) do # go up from the fastlane folder, to the project folder Actions.execute_action(class_ref.step_text) do # arguments is an array by default, containing an hash with the actual parameters # Since we usually just need the passed hash, we'll just use the first object if there is only one if arguments.count == 0 arguments = ConfigurationHelper.parse(class_ref, {}) # no parameters => empty hash elsif arguments.count == 1 and arguments.first.kind_of? Hash arguments = ConfigurationHelper.parse(class_ref, arguments.first) # Correct configuration passed elsif !class_ref. # This action does not use the new action format # Just passing the arguments to this method else UI.user_error!("You have to call the integration like `#{method_sym}(key: \"value\")`. Run `fastlane action #{method_sym}` for all available keys. Please check out the current documentation on GitHub.") end class_ref.runner = self # needed to call another action form an action class_ref.run(arguments) end end rescue FastlaneCore::Interface::FastlaneError => e # user_error! collector.did_raise_error(method_sym) raise e rescue Exception => e # rubocop:disable Lint/RescueException # high chance this is actually FastlaneCore::Interface::FastlaneCrash, but can be anything else # Catches all exceptions, since some plugins might use system exits to get out collector.did_crash(method_sym) raise e end end |
#execute_flow_block(block, current_platform, lane, parameters) ⇒ Object
216 217 218 219 220 |
# File 'lib/fastlane/runner.rb', line 216 def execute_flow_block(block, current_platform, lane, parameters) # Call the platform specific block and default back to the general one block[current_platform].call(lane, parameters) if block[current_platform] && current_platform block[nil].call(lane, parameters) if block[nil] end |
#full_lane_name ⇒ Object
12 13 14 |
# File 'lib/fastlane/runner.rb', line 12 def full_lane_name [current_platform, current_lane].reject(&:nil?).join(' ') end |
#set_after_all(platform, block) ⇒ Object
270 271 272 |
# File 'lib/fastlane/runner.rb', line 270 def set_after_all(platform, block) after_all_blocks[platform] = block end |
#set_after_each(platform, block) ⇒ Object
262 263 264 |
# File 'lib/fastlane/runner.rb', line 262 def set_after_each(platform, block) after_each_blocks[platform] = block end |
#set_before_all(platform, block) ⇒ Object
266 267 268 |
# File 'lib/fastlane/runner.rb', line 266 def set_before_all(platform, block) before_all_blocks[platform] = block end |
#set_before_each(platform, block) ⇒ Object
258 259 260 |
# File 'lib/fastlane/runner.rb', line 258 def set_before_each(platform, block) before_each_blocks[platform] = block end |
#set_error(platform, block) ⇒ Object
274 275 276 |
# File 'lib/fastlane/runner.rb', line 274 def set_error(platform, block) error_blocks[platform] = block end |
#trigger_action_by_name(method_sym, custom_dir, *arguments) ⇒ Object
This is being called from ‘method_missing` from the Fastfile It’s also used when an action is called from another action
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/fastlane/runner.rb', line 102 def trigger_action_by_name(method_sym, custom_dir, *arguments) # First, check if there is a predefined method in the actions folder class_ref = class_reference_from_action_name(method_sym) # It's important to *not* have this code inside the rescue block # otherwise all NameErrors will be caught and the error message is # confusing if class_ref if class_ref.respond_to?(:run) # Action is available, now execute it return self.execute_action(method_sym, class_ref, arguments, custom_dir: custom_dir) else UI.user_error!("Action '#{method_sym}' of class '#{class_name}' was found, but has no `run` method.") end else # Action was not found # Is there a lane under this name? begin return self.try_switch_to_lane(method_sym, arguments) rescue LaneNotAvailableError # No lane, no action, let's at least show the correct error message if Fastlane.plugin_manager.plugin_is_added_as_dependency?(PluginManager.plugin_prefix + method_sym.to_s) # That's a plugin, but for some reason we can't find it UI.user_error!("Plugin '#{method_sym}' was not properly loaded, make sure to follow the plugin docs for troubleshooting: #{PluginManager::TROUBLESHOOTING_URL}") elsif Fastlane::Actions.formerly_bundled_actions.include?(method_sym.to_s) # This was a formerly bundled action which is now a plugin. UI.verbose(caller.join("\n")) UI.user_error!("The action '#{method_sym}' is no longer bundled with fastlane. You can install it using `fastlane add_plugin #{method_sym}`") else # So there is no plugin under that name, so just show the error message generated by the lane switch UI.verbose(caller.join("\n")) UI.user_error!("Could not find action or lane '#{method_sym}'. Check out the README for more details: https://github.com/fastlane/fastlane/tree/master/fastlane") end end end end |
#try_switch_to_lane(new_lane, parameters) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/fastlane/runner.rb', line 146 def try_switch_to_lane(new_lane, parameters) block = lanes.fetch(current_platform, {}).fetch(new_lane, nil) block ||= lanes.fetch(nil, {}).fetch(new_lane, nil) # fallback to general lane for multiple platforms if block original_full = full_lane_name original_lane = current_lane UI.user_error!("Parameters for a lane must always be a hash") unless (parameters.first || {}).kind_of? Hash execute_flow_block(before_each_blocks, current_platform, new_lane, parameters) pretty = [new_lane] pretty = [current_platform, new_lane] if current_platform Actions.execute_action("Switch to #{pretty.join(' ')} lane") {} # log the action UI. "Cruising over to lane '#{pretty.join(' ')}' 🚖" # Actually switch lane now self.current_lane = new_lane collector.did_launch_action(:lane_switch) result = block.call(parameters.first || {}) # to always pass a hash self.current_lane = original_lane # after blocks are only called if no exception was raised before # Call the platform specific after block and then the general one execute_flow_block(after_each_blocks, current_platform, new_lane, parameters) UI. "Cruising back to lane '#{original_full}' 🚘" return result else raise LaneNotAvailableError.new, "Lane not found" end end |
#verify_supported_os(name, class_ref) ⇒ Object
222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/fastlane/runner.rb', line 222 def verify_supported_os(name, class_ref) if class_ref.respond_to?(:is_supported?) if Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] # This value is filled in based on the executed platform block. Might be nil when lane is in root of Fastfile platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] unless class_ref.is_supported?(platform) UI.user_error!("Action '#{name}' doesn't support required operating system '#{platform}'.") end end end end |