fastlane 1.8.0 → 1.9.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: c339ea21edfc2acca2f46b9a751d03795647c3f6
4
- data.tar.gz: 9c35a144521c7f03f7a9c7fe5441026ed9882d59
3
+ metadata.gz: beef52022ff1b725c056cb6d6b76940e08a80e47
4
+ data.tar.gz: 7d3ae10b2bd5e238fb9476d14ea3133f53c3fb04
5
5
  SHA512:
6
- metadata.gz: cc15fe2094ff6748d3c9f9ba7fc029b60eb7faafe91b9f7c407a749232fed51ab25a852f6b69b746ae4b0b3cd296cc260aa9b4e291385a09c530369978a05beb
7
- data.tar.gz: 4849594603cd554346c5ddc54d97a1365903df26f1a14507719ecd2434ae780c79515a7c8c88c5d0392f5bfffac7da8694bc63487d3abb972bbdd965499fcd06
6
+ metadata.gz: 0cd216d8caabb4f7cbfe99e0d9adf6bba9269fd75f0561939c4f7e0675c9b6bc156f9ec54de1533f3f2d1ef2f17567721799654ffbe2af178dd4e4fb7f086b59
7
+ data.tar.gz: f882d73eb82fc32a530ae6538060c3c9895fe5b222fcbab700253a8dd9e1f1145ade69dc74b0b11453dffc4942640669e520b9fefd4b2ab98d977b163e71dbd8
@@ -24,6 +24,12 @@ module Fastlane
24
24
  "A short description with <= 80 characters of what this action does"
25
25
  end
26
26
 
27
+ def self.details
28
+ # Optional:
29
+ # this is your change to provide a more detailed description of this action
30
+ "You can use this action to do cool things..."
31
+ end
32
+
27
33
  def self.available_options
28
34
  # Define all options your action supports.
29
35
 
data/lib/fastlane.rb CHANGED
@@ -5,6 +5,7 @@ require 'fastlane/fast_file'
5
5
  require 'fastlane/dependency_checker'
6
6
  require 'fastlane/runner'
7
7
  require 'fastlane/setup'
8
+ require 'fastlane/lane'
8
9
  require 'fastlane/fastlane_folder'
9
10
  require 'fastlane/junit_generator'
10
11
  require 'fastlane/lane_manager'
@@ -8,10 +8,7 @@ module Fastlane
8
8
  ENVIRONMENT = :ENVIRONMENT
9
9
  end
10
10
 
11
- def self.executed_actions
12
- @executed_actions ||= []
13
- end
14
-
11
+ # Helper Methods
15
12
  def self.git_author
16
13
  s = `git log --name-status HEAD^..HEAD`
17
14
  s = s.match(/Author:.*<(.*)>/)[1]
@@ -27,6 +24,18 @@ module Fastlane
27
24
  nil
28
25
  end
29
26
 
27
+ # Returns the current git branch - can be replaced using the environment variable `GIT_BRANCH`
28
+ def self.git_branch
29
+ return ENV['GIT_BRANCH'] if ENV['GIT_BRANCH'].to_s.length > 0 # set by Jenkins
30
+ s = `git rev-parse --abbrev-ref HEAD`
31
+ return s.to_s.strip if s.to_s.length > 0
32
+ nil
33
+ end
34
+
35
+
36
+ def self.executed_actions
37
+ @executed_actions ||= []
38
+ end
30
39
 
31
40
  # The shared hash can be accessed by any action and contains information like the screenshots path or beta URL
32
41
  def self.lane_context
@@ -109,14 +118,6 @@ module Fastlane
109
118
  Encoding.default_internal = previous_encoding.last
110
119
  end
111
120
 
112
- # Returns the current git branch - can be replaced using the environment variable `GIT_BRANCH`
113
- def self.git_branch
114
- return ENV['GIT_BRANCH'] if ENV['GIT_BRANCH'].to_s.length > 0 # set by Jenkins
115
- s = `git rev-parse --abbrev-ref HEAD`
116
- return s.to_s.strip if s.to_s.length > 0
117
- nil
118
- end
119
-
120
121
  # returns a list of official integrations
121
122
  def self.get_all_official_actions
122
123
  Dir[File.expand_path '*.rb', File.dirname(__FILE__)].collect do |file|
@@ -7,9 +7,8 @@ module Fastlane
7
7
  class EnsureGitBranchAction < Action
8
8
  def self.run(params)
9
9
  branch = params[:branch]
10
-
11
10
  if Actions.git_branch != branch
12
- raise "Git is not on the `#{branch}` branch! Please ensure the repo is checked out to the correct branch.".red
11
+ raise "Git is not on the `#{branch}` branch, but on `#{Actions.git_branch}`! Please ensure the repo is checked out to the correct branch.".red
13
12
  else
14
13
  Helper.log.info "Git branch is `#{branch}`, all good! 💪".green
15
14
  end
@@ -0,0 +1,112 @@
1
+ module Fastlane
2
+ module Actions
3
+ module SharedValues
4
+ GET_GITHUB_RELEASE_INFO = :GET_GITHUB_RELEASE_INFO
5
+ end
6
+
7
+ class GetGithubReleaseAction < Action
8
+ def self.run(params)
9
+ Helper.log.info "Verifying release on GitHub (#{params[:url]}: #{params[:version]})"
10
+ require 'excon'
11
+ result = JSON.parse(Excon.get("https://api.github.com/repos/#{params[:url]}/releases").body)
12
+ result.each do |current|
13
+ if current['tag_name'] == params[:version]
14
+ # Found it
15
+ if current['body'].to_s.length > 0
16
+ Actions.lane_context[SharedValues::GET_GITHUB_RELEASE_INFO] = current
17
+ Helper.log.info "Version is already live on GitHub.com 🚁"
18
+ return current
19
+ else
20
+ raise "No release notes found for #{params[:version]}"
21
+ end
22
+ end
23
+ end
24
+
25
+ Helper.log.error "Couldn't find GitHub release #{params[:version]}".yellow
26
+ return nil
27
+ end
28
+
29
+ #####################################################
30
+ # @!group Documentation
31
+ #####################################################
32
+
33
+ def self.description
34
+ "This will verify if a given release version is avialable on GitHub"
35
+ end
36
+
37
+ def self.details
38
+ sample = '
39
+ {"url"=>"https://api.github.com/repos/KrauseFx/fastlane/releases/1537713",
40
+ "assets_url"=>"https://api.github.com/repos/KrauseFx/fastlane/releases/1537713/assets",
41
+ "upload_url"=>"https://uploads.github.com/repos/KrauseFx/fastlane/releases/1537713/assets{?name}",
42
+ "html_url"=>"https://github.com/KrauseFx/fastlane/releases/tag/1.8.0",
43
+ "id"=>1537713,
44
+ "tag_name"=>"1.8.0",
45
+ "target_commitish"=>"master",
46
+ "name"=>"1.8.0 Switch Lanes & Pass Parameters",
47
+ "draft"=>false,
48
+ "author"=>
49
+ {"login"=>"KrauseFx",
50
+ "id"=>869950,
51
+ "avatar_url"=>"https://avatars.githubusercontent.com/u/869950?v=3",
52
+ "gravatar_id"=>"",
53
+ "url"=>"https://api.github.com/users/KrauseFx",
54
+ "html_url"=>"https://github.com/KrauseFx",
55
+ "followers_url"=>"https://api.github.com/users/KrauseFx/followers",
56
+ "following_url"=>"https://api.github.com/users/KrauseFx/following{/other_user}",
57
+ "gists_url"=>"https://api.github.com/users/KrauseFx/gists{/gist_id}",
58
+ "starred_url"=>"https://api.github.com/users/KrauseFx/starred{/owner}{/repo}",
59
+ "subscriptions_url"=>"https://api.github.com/users/KrauseFx/subscriptions",
60
+ "organizations_url"=>"https://api.github.com/users/KrauseFx/orgs",
61
+ "repos_url"=>"https://api.github.com/users/KrauseFx/repos",
62
+ "events_url"=>"https://api.github.com/users/KrauseFx/events{/privacy}",
63
+ "received_events_url"=>"https://api.github.com/users/KrauseFx/received_events",
64
+ "type"=>"User",
65
+ "site_admin"=>false},
66
+ "prerelease"=>false,
67
+ "created_at"=>"2015-07-14T23:33:01Z",
68
+ "published_at"=>"2015-07-14T23:44:10Z",
69
+ "assets"=>[],
70
+ "tarball_url"=>"https://api.github.com/repos/KrauseFx/fastlane/tarball/1.8.0",
71
+ "zipball_url"=>"https://api.github.com/repos/KrauseFx/fastlane/zipball/1.8.0",
72
+ "body"=>
73
+ "This is one of the biggest updates of `fastlane` yet"
74
+ }'
75
+
76
+ [
77
+ "This will return all information about a release. For example:",
78
+ sample
79
+ ].join("\n")
80
+ end
81
+
82
+ def self.output
83
+ [
84
+ ['GET_GITHUB_RELEASE_INFO', 'Contains all the information about this release']
85
+ ]
86
+ end
87
+
88
+ def self.available_options
89
+ [
90
+ FastlaneCore::ConfigItem.new(key: :url,
91
+ env_name: "FL_GET_GITHUB_RELEASE_URL",
92
+ description: "The path to your repo, e.g. 'KrauseFx/fastlane'",
93
+ verify_block: Proc.new do |value|
94
+ raise "Please only pass the path, e.g. 'KrauseFx/fastlane'".red if value.include?"github.com"
95
+ raise "Please only pass the path, e.g. 'KrauseFx/fastlane'".red if value.split('/').count != 2
96
+ end),
97
+ FastlaneCore::ConfigItem.new(key: :version,
98
+ env_name: "FL_GET_GITHUB_RELEASE_VERSION",
99
+ description: "The version tag of the release to check")
100
+ ]
101
+ end
102
+
103
+ def self.authors
104
+ ["KrauseFx"]
105
+ end
106
+
107
+ def self.is_supported?(platform)
108
+ true
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,41 @@
1
+ module Fastlane
2
+ module Actions
3
+ module SharedValues
4
+
5
+ end
6
+
7
+ class GitBranchAction < Action
8
+ def self.run(params)
9
+ ENV['GIT_BRANCH'] or `git symbolic-ref HEAD --short 2>/dev/null`.strip
10
+ end
11
+
12
+ #####################################################
13
+ # @!group Documentation
14
+ #####################################################
15
+
16
+ def self.description
17
+ "Returns the name of the current git branch"
18
+ end
19
+
20
+ def self.details
21
+ "If no branch could be found, this action will return nil"
22
+ end
23
+
24
+ def self.available_options
25
+ []
26
+ end
27
+
28
+ def self.output
29
+ []
30
+ end
31
+
32
+ def self.authors
33
+ ["KrauseFx"]
34
+ end
35
+
36
+ def self.is_supported?(platform)
37
+ true
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ module Fastlane
2
+ module Actions
3
+ class PromptAction < Action
4
+ def self.run(params)
5
+ params[:text] += " (y/n)" if params[:boolean]
6
+ Helper.log.info params[:text]
7
+
8
+ user_input = params[:ci_input] if Helper.is_ci?
9
+ user_input ||= STDIN.gets.chomp.strip
10
+
11
+ user_input = (user_input.downcase == 'y') if params[:boolean]
12
+
13
+ return user_input
14
+ end
15
+
16
+ #####################################################
17
+ # @!group Documentation
18
+ #####################################################
19
+
20
+ def self.description
21
+ "Ask the user for a value or for confirmation"
22
+ end
23
+
24
+ def self.details
25
+ [
26
+ "You can use `prompt` to ask the user for a value or to just let the user confirm the next step",
27
+ "When this is executed on a CI service, the passed `ci_input` value will be returned"
28
+ ].join("\n")
29
+ end
30
+
31
+ def self.available_options
32
+ [
33
+ FastlaneCore::ConfigItem.new(key: :text,
34
+ description: "The text that will be displayed to the user"),
35
+ FastlaneCore::ConfigItem.new(key: :ci_input,
36
+ description: "The default text that will be used when being executed on a CI service",
37
+ default_value: ''),
38
+ FastlaneCore::ConfigItem.new(key: :boolean,
39
+ description: "Is that a boolean question (yes/no)? This will add (y/n) at the end",
40
+ default_value: false,
41
+ is_string: false)
42
+ ]
43
+ end
44
+
45
+ def self.output
46
+ []
47
+ end
48
+
49
+ def self.authors
50
+ ["KrauseFx"]
51
+ end
52
+
53
+ def self.is_supported?(platform)
54
+ true
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ module Fastlane
2
+ module Actions
3
+ class PutsAction < Action
4
+ def self.run(params)
5
+ Helper.log.info params.join(' ')
6
+ end
7
+
8
+ #####################################################
9
+ # @!group Documentation
10
+ #####################################################
11
+
12
+ def self.description
13
+ "Prints out the given text"
14
+ end
15
+
16
+ def self.authors
17
+ ["KrauseFx"]
18
+ end
19
+
20
+ def self.is_supported?(platform)
21
+ true
22
+ end
23
+ end
24
+ end
25
+ end
@@ -82,6 +82,11 @@ module Fastlane
82
82
  description: "Remove some of the default payloads. More information about the available payloads on GitHub",
83
83
  optional: true,
84
84
  is_string: false),
85
+ FastlaneCore::ConfigItem.new(key: :attachment_properties,
86
+ env_name: "FL_SLACK_ATTACHMENT_PROPERTIES",
87
+ description: "Merge additional properties in the slack attachment, see https://api.slack.com/docs/attachments",
88
+ default_value: {},
89
+ is_string: false),
85
90
  FastlaneCore::ConfigItem.new(key: :success,
86
91
  env_name: "FL_SLACK_SUCCESS",
87
92
  description: "Was this build successful? (true/false)",
@@ -128,7 +133,7 @@ module Fastlane
128
133
  # test_result
129
134
  if should_add_payload[:test_result]
130
135
  slack_attachment[:fields] << {
131
- title: 'Test Result',
136
+ title: 'Result',
132
137
  value: (options[:success] ? 'Success' : 'Error'),
133
138
  short: true
134
139
  }
@@ -165,7 +170,16 @@ module Fastlane
165
170
  }
166
171
  end
167
172
 
168
- slack_attachment
173
+ # merge additional properties
174
+ deep_merge(slack_attachment, options[:attachment_properties])
175
+ end
176
+
177
+ # Adapted from http://stackoverflow.com/a/30225093/158525
178
+ def self.deep_merge(a, b)
179
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ?
180
+ v1.merge(v2, &merger) : Array === v1 && Array === v2 ?
181
+ v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
182
+ a.merge(b, &merger)
169
183
  end
170
184
  end
171
185
  end
@@ -11,17 +11,17 @@ module Fastlane
11
11
 
12
12
  output << "# Available Actions"
13
13
 
14
- all_keys = ff.runner.description_blocks.keys.reject(&:nil?)
14
+ all_keys = ff.runner.lanes.keys.reject(&:nil?)
15
15
  all_keys.unshift(nil) # because we want root elements on top. always! They have key nil
16
16
 
17
17
  all_keys.each do |platform|
18
18
  output << "## #{formatted_platform(platform)}" if platform
19
19
 
20
- value = ff.runner.description_blocks[platform]
20
+ value = ff.runner.lanes[platform]
21
21
 
22
22
  if value
23
- value.each do |lane, description|
24
- output << render(platform, lane, description)
23
+ value.each do |lane_name, lane|
24
+ output << render(platform, lane_name, lane.description.join("\n\n"))
25
25
  end
26
26
 
27
27
  output << ""
@@ -1,7 +1,12 @@
1
1
  module Fastlane
2
2
  class FastFile
3
+ # Stores all relevant information from the currently running process
3
4
  attr_accessor :runner
4
5
 
6
+ # the platform in which we're currently in when parsing the Fastfile
7
+ # This is used to identify the platform in which the lane is in
8
+ attr_accessor :current_platform
9
+
5
10
  SharedValues = Fastlane::Actions::SharedValues
6
11
 
7
12
  # @return The runner which can be executed to trigger the given actions
@@ -34,10 +39,10 @@ module Fastlane
34
39
  def lane(lane_name, &block)
35
40
  raise "You have to pass a block using 'do' for lane '#{lane_name}'. Make sure you read the docs on GitHub.".red unless block
36
41
 
37
- desc = desc_collection.join("\n\n")
38
- platform = @current_platform
39
-
40
- @runner.set_block(lane_name, platform, block, desc)
42
+ self.runner.add_lane(Lane.new(platform: self.current_platform,
43
+ block: block,
44
+ description: desc_collection,
45
+ name: lane_name))
41
46
 
42
47
  @desc_collection = nil # reset the collected description again for the next lane
43
48
  end
@@ -46,11 +51,11 @@ module Fastlane
46
51
  def platform(platform_name, &block)
47
52
  SupportedPlatforms.verify!platform_name
48
53
 
49
- @current_platform = platform_name
54
+ self.current_platform = platform_name
50
55
 
51
56
  block.call
52
57
 
53
- @current_platform = nil
58
+ self.current_platform = nil
54
59
  end
55
60
 
56
61
  # Is executed before each test run
@@ -68,61 +73,6 @@ module Fastlane
68
73
  @runner.set_error(@current_platform, block)
69
74
  end
70
75
 
71
- def try_switch_to_lane(new_lane, parameters)
72
- current_platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
73
- block = @runner.blocks.fetch(current_platform, {}).fetch(new_lane, nil)
74
- platform_nil = (block == nil) # used for the output
75
- block ||= @runner.blocks.fetch(nil, {}).fetch(new_lane, nil) # fallback to general lane for multiple platforms
76
- if block
77
- pretty = [new_lane]
78
- pretty = [current_platform, new_lane] unless platform_nil
79
- Helper.log.info "Cruising over to lane '#{pretty.join(' ')}' 🚖".green
80
- collector.did_launch_action(:lane_switch)
81
- result = block.call(parameters.first || {}) # to always pass a hash
82
- original_lane = Actions.lane_context[Actions::SharedValues::LANE_NAME]
83
- Helper.log.info "Cruising back to lane '#{original_lane}' 🚘".green
84
- return result
85
- else
86
- # No action and no lane, raising an exception now
87
- raise "Could not find action or lane '#{new_lane}'. Check out the README for more details: https://github.com/KrauseFx/fastlane".red
88
- end
89
- end
90
-
91
- def execute_action(method_sym, class_ref, arguments)
92
- collector.did_launch_action(method_sym)
93
-
94
- step_name = class_ref.step_text rescue nil
95
- step_name = method_sym.to_s unless step_name
96
-
97
- verify_supported_os(method_sym, class_ref)
98
-
99
- Helper.log_alert("Step: " + step_name)
100
-
101
- begin
102
- Dir.chdir('..') do # go up from the fastlane folder, to the project folder
103
- Actions.execute_action(method_sym) do
104
- # arguments is an array by default, containing an hash with the actual parameters
105
- # Since we usually just need the passed hash, we'll just use the first object if there is only one
106
- if arguments.count == 0
107
- arguments = ConfigurationHelper.parse(class_ref, {}) # no parameters => empty hash
108
- elsif arguments.count == 1 and arguments.first.kind_of?Hash
109
- arguments = ConfigurationHelper.parse(class_ref, arguments.first) # Correct configuration passed
110
- elsif not class_ref.available_options
111
- # This action does not use the new action format
112
- # Just passing the arguments to this method
113
- else
114
- raise "You have to pass the options for '#{method_sym}' in a different way. Please check out the current documentation on GitHub!".red
115
- end
116
-
117
- class_ref.run(arguments)
118
- end
119
- end
120
- rescue => ex
121
- collector.did_raise_error(method_sym)
122
- raise ex
123
- end
124
- end
125
-
126
76
  # Is used to look if the method is implemented as an action
127
77
  def method_missing(method_sym, *arguments, &_block)
128
78
  # First, check if there is a predefined method in the actions folder
@@ -132,14 +82,14 @@ module Fastlane
132
82
  class_ref = Fastlane::Actions.const_get(class_name)
133
83
  if class_ref && class_ref.respond_to?(:run)
134
84
  # Action is available, now execute it
135
- return execute_action(method_sym, class_ref, arguments)
85
+ return self.runner.execute_action(method_sym, class_ref, arguments)
136
86
  else
137
87
  raise "Action '#{method_sym}' of class '#{class_name}' was found, but has no `run` method.".red
138
88
  end
139
89
  rescue NameError => ex
140
90
  # Action not found
141
91
  # Is there a lane under this name?
142
- return try_switch_to_lane(method_sym, arguments)
92
+ return self.runner.try_switch_to_lane(method_sym, arguments)
143
93
  end
144
94
  end
145
95
 
@@ -147,21 +97,16 @@ module Fastlane
147
97
  # @!group Other things
148
98
  #####################################################
149
99
 
150
- # Speak out loud
151
- def say(value)
152
- # Overwrite this, since there is already a 'say' method defined in the Ruby standard library
153
- value ||= yield
154
- Actions.execute_action('say') do
155
- Fastlane::Actions::SayAction.run([value])
156
- end
100
+ def collector
101
+ runner.collector
157
102
  end
158
103
 
159
104
  # Is the given key a platform block or a lane?
160
105
  def is_platform_block?(key)
161
106
  raise 'No key given'.red unless key
162
107
 
163
- return false if (self.runner.blocks[nil][key.to_sym] rescue false)
164
- return true if self.runner.blocks[key.to_sym].kind_of?Hash
108
+ return false if (self.runner.lanes[nil][key.to_sym] rescue false)
109
+ return true if self.runner.lanes[key.to_sym].kind_of?Hash
165
110
 
166
111
  raise "Could not find '#{key}'. Available lanes: #{self.runner.available_lanes.join(', ')}".red
167
112
  end
@@ -179,34 +124,35 @@ module Fastlane
179
124
  end
180
125
  end
181
126
 
182
- def verify_supported_os(name, class_ref)
183
- if class_ref.respond_to?(:is_supported?)
184
- if Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
185
- # This value is filled in based on the executed platform block. Might be nil when lane is in root of Fastfile
186
- platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
187
-
188
- unless class_ref.is_supported?(platform)
189
- raise "Action '#{name}' doesn't support required operating system '#{platform}'.".red
190
- end
191
- end
192
- end
127
+ def desc(string)
128
+ desc_collection << string
193
129
  end
194
130
 
195
- # Fastfile was finished executing
196
- def did_finish
197
- collector.did_finish
131
+ def desc_collection
132
+ @desc_collection ||= []
198
133
  end
199
134
 
200
- def desc(string)
201
- desc_collection << string
202
- end
135
+ #####################################################
136
+ # @!group Overwriting Ruby methods
137
+ #####################################################
203
138
 
204
- def collector
205
- @collector ||= ActionCollector.new
139
+ # Speak out loud
140
+ def say(value)
141
+ # Overwrite this, since there is already a 'say' method defined in the Ruby standard library
142
+ value ||= yield
143
+ Actions.execute_action('say') do
144
+ collector.did_launch_action(:say)
145
+ Fastlane::Actions::SayAction.run([value])
146
+ end
206
147
  end
207
148
 
208
- def desc_collection
209
- @desc_collection ||= []
149
+ def puts(value)
150
+ # Overwrite this, since there is already a 'puts' method defined in the Ruby standard library
151
+ value ||= yield
152
+ Actions.execute_action('puts') do
153
+ collector.did_launch_action(:pus)
154
+ Fastlane::Actions::PutsAction.run([value])
155
+ end
210
156
  end
211
157
  end
212
158
  end
@@ -4,11 +4,13 @@ module Fastlane
4
4
 
5
5
  # Path to the fastlane folder containing the Fastfile and other configuration files
6
6
  def self.path
7
- return "./#{FOLDER_NAME}/" if File.directory?("./#{FOLDER_NAME}/")
8
- return "./.#{FOLDER_NAME}/" if File.directory?("./.#{FOLDER_NAME}/") # hidden folder
9
- return './' if File.basename(Dir.getwd) == FOLDER_NAME && File.exist?('Fastfile') # inside the folder
10
- return './' if File.basename(Dir.getwd) == ".#{FOLDER_NAME}" && File.exist?('Fastfile') # inside the folder and hidden
11
- nil
7
+ value ||= "./#{FOLDER_NAME}/" if File.directory?("./#{FOLDER_NAME}/")
8
+ value ||= "./.#{FOLDER_NAME}/" if File.directory?("./.#{FOLDER_NAME}/") # hidden folder
9
+ value ||= "./" if File.basename(Dir.getwd) == FOLDER_NAME && File.exist?('Fastfile') # inside the folder
10
+ value ||= "./" if File.basename(Dir.getwd) == ".#{FOLDER_NAME}" && File.exist?('Fastfile') # inside the folder and hidden
11
+
12
+ value = nil if Helper.is_test? # this is required, as the tests would use the ./fastlane folder otherwise
13
+ return value
12
14
  end
13
15
 
14
16
  # Does a fastlane configuration already exist?
@@ -0,0 +1,33 @@
1
+ module Fastlane
2
+ # Represents a lane
3
+ class Lane
4
+ attr_accessor :platform
5
+
6
+ attr_accessor :name
7
+
8
+ # @return (Array) An array containing the description of this lane
9
+ # Each item of the array is one line
10
+ attr_accessor :description
11
+
12
+ attr_accessor :block
13
+
14
+ def initialize(platform: nil, name: nil, description: nil, block: nil)
15
+ raise "description must be an array" unless description.kind_of?Array
16
+
17
+ self.platform = platform
18
+ self.name = name
19
+ self.description = description
20
+ self.block = block
21
+ end
22
+
23
+ # Execute this lane
24
+ def call(parameters)
25
+ block.call(parameters || {})
26
+ end
27
+
28
+ # @return [String] The lane + name of the lane. If there is no platform, it will only be the lane name
29
+ def pretty_name
30
+ [platform, name].reject(&:nil?).join(' ')
31
+ end
32
+ end
33
+ end
@@ -12,25 +12,21 @@ module Fastlane
12
12
  ff = Fastlane::FastFile.new(path)
13
13
  output = ""
14
14
 
15
- all_keys = ff.runner.description_blocks.keys.reject(&:nil?)
15
+ all_keys = ff.runner.lanes.keys.reject(&:nil?)
16
16
  all_keys.unshift(nil) # because we want root elements on top. always! They have key nil
17
17
 
18
18
  all_keys.each do |platform|
19
- next if (ff.runner.description_blocks[platform] || []).count == 0
19
+ next if (ff.runner.lanes[platform] || []).count == 0
20
20
  plat_text = platform
21
21
  plat_text = "general" if platform.to_s.empty?
22
22
  output += "\n--------- #{plat_text}---------\n".yellow
23
23
 
24
- value = ff.runner.description_blocks[platform]
24
+ value = ff.runner.lanes[platform]
25
25
 
26
26
  if value
27
- value.each do |lane, description|
28
- lane_text = "----- fastlane "
29
- lane_text += platform.to_s + " " if platform
30
- lane_text += lane.to_s + "\n"
31
-
32
- output += lane_text.green
33
- output += description.gsub("\n\n", "\n") + "\n\n" if description.to_s.length > 0
27
+ value.each do |lane_name, lane|
28
+ output += "----- fastlane #{lane.pretty_name}".green
29
+ output += "\n" + lane.description.join("\n") + "\n\n" if lane.description.count > 0
34
30
  end
35
31
  end
36
32
  end
@@ -50,7 +50,7 @@ module Fastlane
50
50
 
51
51
  # All the finishing up that needs to be done
52
52
  def self.finish_fastlane(ff, duration, error)
53
- ff.did_finish
53
+ ff.runner.did_finish
54
54
 
55
55
  # Finished with all the lanes
56
56
  Fastlane::JUnitGenerator.generate(Fastlane::Actions.executed_actions)
@@ -1,48 +1,56 @@
1
1
  module Fastlane
2
2
  class Runner
3
+ # Symbol for the current lane
4
+ attr_accessor :current_lane
3
5
 
4
- # This will take care of executing **one** lane.
6
+ # Symbol for the current platform
7
+ attr_accessor :current_platform
8
+
9
+ # @return [Hash] All the lanes available, first the platform, then the lane
10
+ attr_accessor :lanes
11
+
12
+ def full_lane_name
13
+ [current_platform, current_lane].reject(&:nil?).join(' ')
14
+ end
15
+
16
+ # This will take care of executing **one** lane. That's when the user triggers a lane from the CLI for example
17
+ # This method is **not** executed when switching a lane
5
18
  # @param lane_name The name of the lane to execute
6
19
  # @param platform The name of the platform to execute
7
20
  # @param parameters [Hash] The parameters passed from the command line to the lane
8
21
  def execute(lane, platform = nil, parameters = nil)
9
22
  raise "No lane given" unless lane
10
23
 
11
- ENV["FASTLANE_LANE_NAME"] = lane.to_s
12
- if platform
13
- ENV["FASTLANE_PLATFORM_NAME"] = platform.to_s
14
- else
15
- ENV["FASTLANE_PLATFORM_NAME"] = nil
16
- end
17
-
18
- lane = lane.to_sym
19
- platform = platform.to_sym if platform # might be nil, which is okay => root element
24
+ self.current_lane = lane.to_sym
25
+ self.current_platform = (platform ? platform.to_sym : nil)
20
26
 
21
- Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] = platform # set this in any case: important
27
+ ENV["FASTLANE_LANE_NAME"] = current_lane.to_s
28
+ ENV["FASTLANE_PLATFORM_NAME"] = (current_platform ? current_platform.to_s : nil)
29
+
30
+ Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] = current_platform
31
+ Actions.lane_context[Actions::SharedValues::LANE_NAME] = full_lane_name
22
32
 
23
- full_lane_name = [platform, lane].reject(&:nil?).join(' ')
24
33
  Helper.log.info "Driving the lane '#{full_lane_name}' 🚀".green
25
- Actions.lane_context[Actions::SharedValues::LANE_NAME] = full_lane_name
26
34
 
27
35
  return_val = nil
28
36
 
29
37
  path_to_use = Fastlane::FastlaneFolder.path || Dir.pwd
30
38
  Dir.chdir(path_to_use) do # the file is located in the fastlane folder
31
39
 
32
- unless (blocks[platform][lane] rescue nil)
40
+ unless (lanes[current_platform][current_lane] rescue nil)
33
41
  raise "Could not find lane '#{full_lane_name}'. Available lanes: #{available_lanes.join(', ')}".red
34
42
  end
35
43
 
36
44
  # Call the platform specific before_all block and then the general one
37
- before_all_blocks[platform].call(lane) if (before_all_blocks[platform] and platform != nil)
38
- before_all_blocks[nil].call(lane) if before_all_blocks[nil]
45
+ before_all_blocks[current_platform].call(current_lane) if (before_all_blocks[current_platform] and current_platform)
46
+ before_all_blocks[nil].call(current_lane) if before_all_blocks[nil]
39
47
 
40
- return_val = blocks[platform][lane].call(parameters || {}) # by default no parameters
48
+ return_val = lanes[current_platform][current_lane].call(parameters || {}) # by default no parameters
41
49
 
42
50
  # `after_all` is only called if no exception was raised before
43
51
  # Call the platform specific before_all block and then the general one
44
- after_all_blocks[platform].call(lane) if (after_all_blocks[platform] and platform != nil)
45
- after_all_blocks[nil].call(lane) if (after_all_blocks[nil])
52
+ after_all_blocks[current_platform].call(current_lane) if (after_all_blocks[current_platform] and current_platform)
53
+ after_all_blocks[nil].call(current_lane) if (after_all_blocks[nil])
46
54
  end
47
55
 
48
56
  return return_val
@@ -51,26 +59,126 @@ module Fastlane
51
59
  # Provide error block exception without colour code
52
60
  error_ex = ex.exception(ex.message.gsub(/\033\[\d+m/, ''))
53
61
 
54
- error_blocks[platform].call(lane, error_ex) if (error_blocks[platform] and platform != nil)
55
- error_blocks[nil].call(lane, error_ex) if error_blocks[nil]
62
+ error_blocks[current_platform].call(current_lane, error_ex) if (error_blocks[current_platform] and current_platform)
63
+ error_blocks[nil].call(current_lane, error_ex) if error_blocks[nil]
56
64
  end
57
65
  raise ex
58
66
  end
59
67
 
60
68
  # @param filter_platform: Filter, to only show the lanes of a given platform
69
+ # @return an array of lanes (platform lane_name) to print them out to the user
61
70
  def available_lanes(filter_platform = nil)
62
71
  all = []
63
- blocks.each do |platform, lane|
72
+ lanes.each do |platform, platform_lanes|
64
73
  next if (filter_platform and filter_platform.to_s != platform.to_s) # skip actions that don't match
65
74
 
66
- lane.each do |lane_name, block|
75
+ platform_lanes.each do |lane_name, lane|
67
76
  all << [platform, lane_name].reject(&:nil?).join(' ')
68
77
  end
69
78
  end
70
79
  all
71
80
  end
72
81
 
73
- # Called internally
82
+ #
83
+ # All the methods that are usually called on execution
84
+ #
85
+
86
+ def try_switch_to_lane(new_lane, parameters)
87
+ block = lanes.fetch(current_platform, {}).fetch(new_lane, nil)
88
+ block ||= lanes.fetch(nil, {}).fetch(new_lane, nil) # fallback to general lane for multiple platforms
89
+ if block
90
+ original_full = full_lane_name
91
+ original_lane = current_lane
92
+
93
+ raise "Parameters for a lane must always be a hash".red unless (parameters.first || {}).kind_of?Hash
94
+
95
+ pretty = [new_lane]
96
+ pretty = [current_platform, new_lane] if current_platform
97
+ Helper.log.info "Cruising over to lane '#{pretty.join(' ')}' 🚖".green
98
+
99
+ # Actually switch lane now
100
+ current_lane = new_lane
101
+ collector.did_launch_action(:lane_switch)
102
+ result = block.call(parameters.first || {}) # to always pass a hash
103
+ current_lane = original_lane
104
+
105
+ Helper.log.info "Cruising back to lane '#{original_full}' 🚘".green
106
+ return result
107
+ else
108
+ # No action and no lane, raising an exception now
109
+ raise "Could not find action or lane '#{new_lane}'. Check out the README for more details: https://github.com/KrauseFx/fastlane".red
110
+ end
111
+ end
112
+
113
+ def execute_action(method_sym, class_ref, arguments)
114
+ collector.did_launch_action(method_sym)
115
+
116
+ step_name = class_ref.step_text rescue nil
117
+ step_name = method_sym.to_s unless step_name
118
+
119
+ verify_supported_os(method_sym, class_ref)
120
+
121
+ Helper.log_alert("Step: " + step_name)
122
+
123
+ begin
124
+ Dir.chdir('..') do # go up from the fastlane folder, to the project folder
125
+ Actions.execute_action(method_sym) do
126
+ # arguments is an array by default, containing an hash with the actual parameters
127
+ # Since we usually just need the passed hash, we'll just use the first object if there is only one
128
+ if arguments.count == 0
129
+ arguments = ConfigurationHelper.parse(class_ref, {}) # no parameters => empty hash
130
+ elsif arguments.count == 1 and arguments.first.kind_of?Hash
131
+ arguments = ConfigurationHelper.parse(class_ref, arguments.first) # Correct configuration passed
132
+ elsif not class_ref.available_options
133
+ # This action does not use the new action format
134
+ # Just passing the arguments to this method
135
+ else
136
+ raise "You have to pass the options for '#{method_sym}' in a different way. Please check out the current documentation on GitHub!".red
137
+ end
138
+
139
+ class_ref.run(arguments)
140
+ end
141
+ end
142
+ rescue => ex
143
+ collector.did_raise_error(method_sym)
144
+ raise ex
145
+ end
146
+ end
147
+
148
+ def verify_supported_os(name, class_ref)
149
+ if class_ref.respond_to?(:is_supported?)
150
+ if Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
151
+ # This value is filled in based on the executed platform block. Might be nil when lane is in root of Fastfile
152
+ platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
153
+
154
+ unless class_ref.is_supported?(platform)
155
+ raise "Action '#{name}' doesn't support required operating system '#{platform}'.".red
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ def collector
162
+ @collector ||= ActionCollector.new
163
+ end
164
+
165
+ # Fastfile was finished executing
166
+ def did_finish
167
+ collector.did_finish
168
+ end
169
+
170
+ # Called internally to setup the runner object
171
+ #
172
+
173
+ # @param lane [Lane] A lane object
174
+ def add_lane(lane)
175
+ lanes[lane.platform] ||= {}
176
+
177
+ raise "Lane '#{lane.name}' was defined multiple times!".red if lanes[lane.platform][lane.name]
178
+
179
+ lanes[lane.platform][lane.name] = lane
180
+ end
181
+
74
182
  def set_before_all(platform, block)
75
183
  before_all_blocks[platform] = block
76
184
  end
@@ -83,22 +191,8 @@ module Fastlane
83
191
  error_blocks[platform] = block
84
192
  end
85
193
 
86
- # @param lane: The name of the lane
87
- # @param platform: The platform for the given block - might be nil - nil is actually the root of Fastfile with no specific platform
88
- # @param block: The block of the lane
89
- # @param desc: Description of this action
90
- def set_block(lane, platform, block, desc = nil)
91
- blocks[platform] ||= {}
92
- description_blocks[platform] ||= {}
93
-
94
- raise "Lane '#{lane}' was defined multiple times!".red if blocks[platform][lane]
95
-
96
- blocks[platform][lane] = block
97
- description_blocks[platform][lane] = desc
98
- end
99
-
100
- def blocks
101
- @blocks ||= {}
194
+ def lanes
195
+ @lanes ||= {}
102
196
  end
103
197
 
104
198
  def before_all_blocks
@@ -112,9 +206,5 @@ module Fastlane
112
206
  def error_blocks
113
207
  @error_blocks ||= {}
114
208
  end
115
-
116
- def description_blocks
117
- @description_blocks ||= {}
118
- end
119
209
  end
120
210
  end
@@ -1,3 +1,3 @@
1
1
  module Fastlane
2
- VERSION = '1.8.0'
2
+ VERSION = '1.9.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-14 00:00:00.000000000 Z
11
+ date: 2015-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -430,6 +430,8 @@ files:
430
430
  - lib/fastlane/actions/fastlane_version.rb
431
431
  - lib/fastlane/actions/frameit.rb
432
432
  - lib/fastlane/actions/gcovr.rb
433
+ - lib/fastlane/actions/get_github_release.rb
434
+ - lib/fastlane/actions/git_branch.rb
433
435
  - lib/fastlane/actions/hg_add_tag.rb
434
436
  - lib/fastlane/actions/hg_commit_version_bump.rb
435
437
  - lib/fastlane/actions/hg_ensure_clean_status.rb
@@ -442,6 +444,7 @@ files:
442
444
  - lib/fastlane/actions/install_carthage.rb
443
445
  - lib/fastlane/actions/install_cocapods.rb
444
446
  - lib/fastlane/actions/ipa.rb
447
+ - lib/fastlane/actions/lane_context.rb
445
448
  - lib/fastlane/actions/lcov.rb
446
449
  - lib/fastlane/actions/mailgun.rb
447
450
  - lib/fastlane/actions/notify.rb
@@ -449,7 +452,9 @@ files:
449
452
  - lib/fastlane/actions/opt_out_usage.rb
450
453
  - lib/fastlane/actions/pem.rb
451
454
  - lib/fastlane/actions/produce.rb
455
+ - lib/fastlane/actions/prompt.rb
452
456
  - lib/fastlane/actions/push_to_git_remote.rb
457
+ - lib/fastlane/actions/puts.rb
453
458
  - lib/fastlane/actions/register_devices.rb
454
459
  - lib/fastlane/actions/reset_git_repo.rb
455
460
  - lib/fastlane/actions/resign.rb
@@ -483,7 +488,7 @@ files:
483
488
  - lib/fastlane/fast_file.rb
484
489
  - lib/fastlane/fastlane_folder.rb
485
490
  - lib/fastlane/junit_generator.rb
486
- - lib/fastlane/lane_context.rb
491
+ - lib/fastlane/lane.rb
487
492
  - lib/fastlane/lane_list.rb
488
493
  - lib/fastlane/lane_manager.rb
489
494
  - lib/fastlane/new_action.rb