fastlane 2.180.1 → 2.183.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +90 -90
  3. data/cert/lib/cert/commands_generator.rb +2 -1
  4. data/deliver/lib/assets/summary.html.erb +10 -10
  5. data/deliver/lib/deliver/commands_generator.rb +2 -1
  6. data/deliver/lib/deliver/languages.rb +1 -1
  7. data/deliver/lib/deliver/options.rb +2 -2
  8. data/deliver/lib/deliver/submit_for_review.rb +3 -3
  9. data/deliver/lib/deliver/upload_metadata.rb +1 -1
  10. data/fastlane/lib/fastlane/actions/actions_helper.rb +2 -2
  11. data/fastlane/lib/fastlane/actions/backup_xcarchive.rb +1 -1
  12. data/fastlane/lib/fastlane/actions/clipboard.rb +3 -6
  13. data/fastlane/lib/fastlane/actions/danger.rb +7 -1
  14. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
  15. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +18 -1
  16. data/fastlane/lib/fastlane/actions/ensure_env_vars.rb +2 -6
  17. data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +3 -1
  18. data/fastlane/lib/fastlane/actions/git_branch.rb +1 -1
  19. data/fastlane/lib/fastlane/actions/git_commit.rb +3 -1
  20. data/fastlane/lib/fastlane/actions/git_pull.rb +4 -10
  21. data/fastlane/lib/fastlane/actions/git_submodule_update.rb +16 -8
  22. data/fastlane/lib/fastlane/actions/hipchat.rb +2 -1
  23. data/fastlane/lib/fastlane/actions/import_from_git.rb +5 -5
  24. data/fastlane/lib/fastlane/actions/notification.rb +1 -1
  25. data/fastlane/lib/fastlane/actions/slack.rb +155 -133
  26. data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +4 -2
  27. data/fastlane/lib/fastlane/actions/xcodebuild.rb +5 -5
  28. data/fastlane/lib/fastlane/cli_tools_distributor.rb +1 -1
  29. data/fastlane/lib/fastlane/commands_generator.rb +2 -1
  30. data/fastlane/lib/fastlane/fast_file.rb +10 -2
  31. data/fastlane/lib/fastlane/helper/git_helper.rb +9 -1
  32. data/fastlane/lib/fastlane/lane_manager.rb +3 -2
  33. data/fastlane/lib/fastlane/notification/slack.rb +56 -0
  34. data/fastlane/lib/fastlane/plugins/plugin_info.rb +2 -2
  35. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +7 -6
  36. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +30 -35
  37. data/fastlane/lib/fastlane/plugins/template/spec/spec_helper.rb.erb +1 -1
  38. data/fastlane/lib/fastlane/swift_fastlane_function.rb +35 -14
  39. data/fastlane/lib/fastlane/version.rb +2 -2
  40. data/fastlane/swift/Deliverfile.swift +1 -1
  41. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  42. data/fastlane/swift/Fastlane.swift +6621 -3802
  43. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +4 -0
  44. data/fastlane/swift/Gymfile.swift +1 -1
  45. data/fastlane/swift/GymfileProtocol.swift +1 -1
  46. data/fastlane/swift/Matchfile.swift +1 -1
  47. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  48. data/fastlane/swift/OptionalConfigValue.swift +131 -0
  49. data/fastlane/swift/Precheckfile.swift +1 -1
  50. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  51. data/fastlane/swift/Scanfile.swift +1 -1
  52. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  53. data/fastlane/swift/Screengrabfile.swift +1 -1
  54. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  55. data/fastlane/swift/Snapshotfile.swift +1 -1
  56. data/fastlane/swift/SnapshotfileProtocol.swift +5 -1
  57. data/fastlane/swift/formatting/Brewfile.lock.json +16 -14
  58. data/fastlane/swift/upgrade_manifest.json +1 -1
  59. data/fastlane_core/lib/fastlane_core.rb +22 -21
  60. data/fastlane_core/lib/fastlane_core/build_watcher.rb +65 -11
  61. data/fastlane_core/lib/fastlane_core/clipboard.rb +20 -0
  62. data/fastlane_core/lib/fastlane_core/device_manager.rb +1 -1
  63. data/fastlane_core/lib/fastlane_core/helper.rb +4 -4
  64. data/fastlane_core/lib/fastlane_core/languages.rb +2 -2
  65. data/fastlane_core/lib/fastlane_core/swag.rb +1 -1
  66. data/fastlane_core/lib/fastlane_core/ui/help.erb +35 -0
  67. data/fastlane_core/lib/fastlane_core/ui/help_formatter.rb +16 -0
  68. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +4 -1
  69. data/frameit/lib/frameit/commands_generator.rb +2 -1
  70. data/frameit/lib/frameit/config_parser.rb +2 -2
  71. data/frameit/lib/frameit/frame_downloader.rb +2 -1
  72. data/gym/lib/gym/code_signing_mapping.rb +2 -2
  73. data/gym/lib/gym/commands_generator.rb +2 -1
  74. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +6 -5
  75. data/gym/lib/gym/runner.rb +5 -1
  76. data/match/lib/match/commands_generator.rb +2 -1
  77. data/pem/lib/pem/commands_generator.rb +2 -1
  78. data/pilot/lib/pilot/build_manager.rb +3 -3
  79. data/pilot/lib/pilot/commands_generator.rb +2 -1
  80. data/pilot/lib/pilot/options.rb +2 -2
  81. data/pilot/lib/pilot/tester_exporter.rb +0 -1
  82. data/pilot/lib/pilot/tester_manager.rb +0 -1
  83. data/precheck/lib/precheck/commands_generator.rb +2 -1
  84. data/produce/lib/produce/commands_generator.rb +2 -1
  85. data/scan/lib/scan/commands_generator.rb +2 -1
  86. data/scan/lib/scan/runner.rb +3 -1
  87. data/scan/lib/scan/test_command_generator.rb +3 -1
  88. data/screengrab/lib/screengrab/commands_generator.rb +2 -1
  89. data/sigh/lib/sigh/commands_generator.rb +2 -1
  90. data/snapshot/lib/assets/SnapfileTemplate +1 -1
  91. data/snapshot/lib/snapshot/commands_generator.rb +3 -1
  92. data/snapshot/lib/snapshot/options.rb +5 -0
  93. data/snapshot/lib/snapshot/reports_generator.rb +4 -0
  94. data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +2 -0
  95. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +1 -1
  96. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +8 -4
  97. data/spaceship/README.md +2 -12
  98. data/spaceship/lib/spaceship/base.rb +2 -2
  99. data/spaceship/lib/spaceship/commands_generator.rb +4 -2
  100. data/spaceship/lib/spaceship/connect_api/model.rb +1 -1
  101. data/spaceship/lib/spaceship/connect_api/models/profile.rb +6 -0
  102. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +6 -2
  103. data/spaceship/lib/spaceship/spaceauth_runner.rb +19 -9
  104. data/spaceship/lib/spaceship/tunes/members.rb +1 -1
  105. data/spaceship/lib/spaceship/ui.rb +2 -2
  106. data/supply/lib/supply/client.rb +5 -3
  107. data/supply/lib/supply/commands_generator.rb +2 -1
  108. data/supply/lib/supply/options.rb +2 -2
  109. data/supply/lib/supply/uploader.rb +3 -2
  110. metadata +74 -88
  111. data/fastlane/lib/fastlane/.fastlane_require.rb.swp +0 -0
  112. data/fastlane/lib/fastlane/actions/.cocoapods.rb.swp +0 -0
  113. data/pilot/lib/pilot/tester_util.rb +0 -0
@@ -40,7 +40,7 @@ module Fastlane
40
40
  end
41
41
 
42
42
  # Create zip
43
- Actions.sh(%(cd "#{xcarchive_folder}" && zip -r -X "#{zip_file}" "#{xcarchive_file}" > /dev/null))
43
+ Actions.sh(%(cd "#{xcarchive_folder}" && zip -r -X -y "#{zip_file}" "#{xcarchive_file}" > /dev/null))
44
44
 
45
45
  # Moved to its final destination
46
46
  FileUtils.mv(zip_file, full_destination)
@@ -7,10 +7,7 @@ module Fastlane
7
7
  truncated_value = value[0..800].gsub(/\s\w+\s*$/, '...')
8
8
  UI.message("Storing '#{truncated_value}' in the clipboard 🎨")
9
9
 
10
- if FastlaneCore::Helper.mac?
11
- require 'open3'
12
- Open3.popen3('pbcopy') { |input, _, _| input << value }
13
- end
10
+ FastlaneCore::Clipboard.copy(content: value)
14
11
  end
15
12
 
16
13
  #####################################################
@@ -30,11 +27,11 @@ module Fastlane
30
27
  end
31
28
 
32
29
  def self.authors
33
- ["KrauseFx", "joshdholtz"]
30
+ ["KrauseFx", "joshdholtz", "rogerluan"]
34
31
  end
35
32
 
36
33
  def self.is_supported?(platform)
37
- true
34
+ FastlaneCore::Clipboard.is_supported?
38
35
  end
39
36
 
40
37
  def self.example_code
@@ -17,6 +17,7 @@ module Fastlane
17
17
  cmd << "--danger_id=#{danger_id}" if danger_id
18
18
  cmd << "--dangerfile=#{dangerfile}" if dangerfile
19
19
  cmd << "--fail-on-errors=true" if params[:fail_on_errors]
20
+ cmd << "--fail-if-no-pr=true" if params[:fail_if_no_pr]
20
21
  cmd << "--new-comment" if params[:new_comment]
21
22
  cmd << "--remove-previous-comments" if params[:remove_previous_comments]
22
23
  cmd << "--base=#{base}" if base
@@ -99,7 +100,12 @@ module Fastlane
99
100
  env_name: "FL_DANGER_PR",
100
101
  description: "Run danger on a specific pull request. e.g. \"https://github.com/danger/danger/pull/518\"",
101
102
  is_string: true,
102
- optional: true)
103
+ optional: true),
104
+ FastlaneCore::ConfigItem.new(key: :fail_if_no_pr,
105
+ env_name: "FL_DANGER_FAIL_IF_NO_PR",
106
+ description: "Fail Danger execution if no PR is found",
107
+ type: Boolean,
108
+ default_value: false)
103
109
  ]
104
110
  end
105
111
 
@@ -332,7 +332,7 @@ To get more information about language and locale codes please read [Internation
332
332
 
333
333
  ## Use a clean status bar
334
334
 
335
- You can set `override_status_bar` to `true` to set the status bar to Tuesday January 9th at 9:41AM with full battery and reception.
335
+ You can set `override_status_bar` to `true` to set the status bar to Tuesday January 9th at 9:41AM with full battery and reception. If you need more granular customization, to set a Carrier name for example, also set `override_status_bar_arguments` to the specific arguments to be passed to the `xcrun simctl status_bar override` command. Run `xcrun simctl status_bar --help` to see the options available.
336
336
 
337
337
  ## Editing the `Snapfile`
338
338
 
@@ -332,7 +332,24 @@ Use [_deliver_](https://docs.fastlane.tools/actions/deliver/) to upload iOS scre
332
332
 
333
333
  ## Use a clean status bar
334
334
 
335
- You can set `override_status_bar` to `true` in snapshot to set the status bar to Tuesday January 9th at 9:41AM with full battery and reception.
335
+ You can set `override_status_bar` to `true` in snapshot to set the status bar to Tuesday January 9th at 9:41AM with full battery and reception. If you need more granular customization, to set a Carrier name for example, also set `override_status_bar_arguments` to the specific arguments to be passed to the `xcrun simctl status_bar override` command. Run `xcrun simctl status_bar --help` to see the options available.
336
+
337
+ ### Examples
338
+
339
+ ```ruby
340
+ # Sets the time to 9:41AM with full battery and reception, with the default carrier name: Carrier
341
+ capture_ios_screenshots(
342
+ override_status_bar: true
343
+ )
344
+ ```
345
+
346
+ ```ruby
347
+ # Set the time to 9:41AM, battery at 75% and charging, on the TELUS LTE network
348
+ capture_ios_screenshots(
349
+ override_status_bar: true,
350
+ override_status_bar_arguments: "--time 9:41 --dataNetwork lte --cellularMode active --cellularBars 4 --batteryState charging --batteryLevel 75 --operatorName TELUS"
351
+ )
352
+ ```
336
353
 
337
354
  ## Gray artifacts around text
338
355
 
@@ -3,15 +3,11 @@ module Fastlane
3
3
  class EnsureEnvVarsAction < Action
4
4
  def self.run(params)
5
5
  variables = params[:env_vars]
6
+ missing_variables = variables.select { |variable| ENV[variable].to_s.strip.empty? }
6
7
 
7
- variables.each do |variable|
8
- next unless ENV[variable].to_s.strip.empty?
9
-
10
- UI.user_error!("Missing environment variable '#{variable}'")
11
- end
8
+ UI.user_error!("Missing environment variable(s) '#{missing_variables.join('\', \'')}'") unless missing_variables.empty?
12
9
 
13
10
  is_one = variables.length == 1
14
-
15
11
  UI.success("Environment variable#{is_one ? '' : 's'} '#{variables.join('\', \'')}' #{is_one ? 'is' : 'are'} set!")
16
12
  end
17
13
 
@@ -26,7 +26,9 @@ module Fastlane
26
26
  # Login
27
27
  credentials = JSON.parse(json_key_data)
28
28
  callback_uri = 'https://fastlane.github.io/managed_google_play-callback/callback.html'
29
- uri = "https://play.google.com/apps/publish/delegatePrivateApp?service_account=#{credentials['client_email']}&continueUrl=#{URI.encode_www_form_component(callback_uri)}"
29
+ require 'addressable/uri'
30
+ continueUrl = Addressable::URI.encode(callback_uri)
31
+ uri = "https://play.google.com/apps/publish/delegatePrivateApp?service_account=#{credentials['client_email']}&continueUrl=#{continueUrl}"
30
32
 
31
33
  UI.message("To obtain publishing rights for custom apps on Managed Play Store, open the following URL and log in:")
32
34
  UI.message("")
@@ -2,7 +2,7 @@ module Fastlane
2
2
  module Actions
3
3
  class GitBranchAction < Action
4
4
  def self.run(params)
5
- branch = Actions.git_branch
5
+ branch = Actions.git_branch || ""
6
6
  return "" if branch == "HEAD" # Backwards compatibility with the original (and documented) implementation
7
7
  branch
8
8
  end
@@ -42,11 +42,13 @@ module Fastlane
42
42
  FastlaneCore::ConfigItem.new(key: :message,
43
43
  description: "The commit message that should be used"),
44
44
  FastlaneCore::ConfigItem.new(key: :skip_git_hooks,
45
- description: "Set to true to pass --no-verify to git",
45
+ description: "Set to true to pass `--no-verify` to git",
46
+ default_value: false,
46
47
  type: Boolean,
47
48
  optional: true),
48
49
  FastlaneCore::ConfigItem.new(key: :allow_nothing_to_commit,
49
50
  description: "Set to true to allow commit without any git changes in the files you want to commit",
51
+ default_value: false,
50
52
  type: Boolean,
51
53
  optional: true)
52
54
  ]
@@ -23,20 +23,14 @@ module Fastlane
23
23
  [
24
24
  FastlaneCore::ConfigItem.new(key: :only_tags,
25
25
  description: "Simply pull the tags, and not bring new commits to the current branch from the remote",
26
- is_string: false,
26
+ type: Boolean,
27
27
  optional: true,
28
- default_value: false,
29
- verify_block: proc do |value|
30
- UI.user_error!("Please pass a valid value for only_tags. Use one of the following: true, false") unless value.kind_of?(TrueClass) || value.kind_of?(FalseClass)
31
- end),
28
+ default_value: false),
32
29
  FastlaneCore::ConfigItem.new(key: :rebase,
33
30
  description: "Rebase on top of the remote branch instead of merge",
34
- is_string: false,
31
+ type: Boolean,
35
32
  optional: true,
36
- default_value: false,
37
- verify_block: proc do |value|
38
- UI.user_error!("Please pass a valid value for rebase. Use one of the following: true, false") unless value.kind_of?(TrueClass) || value.kind_of?(FalseClass)
39
- end)
33
+ default_value: false)
40
34
  ]
41
35
  end
42
36
 
@@ -13,20 +13,19 @@ module Fastlane
13
13
  #####################################################
14
14
 
15
15
  def self.description
16
- "Executes a git submodule command"
16
+ "Executes a git submodule update command"
17
17
  end
18
18
 
19
19
  def self.available_options
20
20
  [
21
21
  FastlaneCore::ConfigItem.new(key: :recursive,
22
- description: "Should the submodules be updated recursively",
23
- type: Boolean,
24
- default_value: false),
22
+ description: "Should the submodules be updated recursively?",
23
+ type: Boolean,
24
+ default_value: false),
25
25
  FastlaneCore::ConfigItem.new(key: :init,
26
- description: "Should the submodules be initiated before update",
27
- type: Boolean,
28
- is_string: false,
29
- default_value: false)
26
+ description: "Should the submodules be initiated before update?",
27
+ type: Boolean,
28
+ default_value: false)
30
29
  ]
31
30
  end
32
31
 
@@ -44,6 +43,15 @@ module Fastlane
44
43
  return true
45
44
  end
46
45
 
46
+ def self.example_code
47
+ [
48
+ 'git_submodule_update',
49
+ 'git_submodule_update(recursive: true)',
50
+ 'git_submodule_update(init: true)',
51
+ 'git_submodule_update(recursive: true, init: true)'
52
+ ]
53
+ end
54
+
47
55
  def self.category
48
56
  :source_control
49
57
  end
@@ -49,7 +49,8 @@ module Fastlane
49
49
  # Escape channel's name to guarantee it is a valid URL resource.
50
50
  # First of all we verify that the value is not already escaped,
51
51
  # escaping an escaped value will produce a wrong channel name.
52
- escaped_channel = URI.unescape(channel) == channel ? URI.escape(channel) : channel
52
+ require 'addressable/uri'
53
+ escaped_channel = Addressable::URI.encode(channel) == channel ? Addressable::URI.encode(channel) : channel
53
54
  if user?(channel)
54
55
  params = { 'message' => message, 'message_format' => message_format }
55
56
  json_headers = { 'Content-Type' => 'application/json',
@@ -43,7 +43,7 @@ module Fastlane
43
43
  is_string: false,
44
44
  optional: true),
45
45
  FastlaneCore::ConfigItem.new(key: :cache_path,
46
- description: "The path to a directory where the repository should be cloned into. This is ignored if `version` is not specified. Defaults to `nil`, which causes the repository to be cloned on every call, to a temporary directory",
46
+ description: "The path to a directory where the repository should be cloned into. Defaults to `nil`, which causes the repository to be cloned on every call, to a temporary directory",
47
47
  default_value: nil,
48
48
  optional: true)
49
49
  ]
@@ -61,14 +61,14 @@ module Fastlane
61
61
  [
62
62
  'import_from_git(
63
63
  url: "git@github.com:fastlane/fastlane.git", # The URL of the repository to import the Fastfile from.
64
- branch: "HEAD", # The branch to checkout on the repository
65
- path: "fastlane/Fastfile", # The path of the Fastfile in the repository
64
+ branch: "HEAD", # The branch to checkout on the repository.
65
+ path: "fastlane/Fastfile", # The path of the Fastfile in the repository.
66
66
  version: "~> 1.0.0" # The version to checkout on the repository. Optimistic match operator can be used to select the latest version within constraints.
67
67
  )',
68
68
  'import_from_git(
69
69
  url: "git@github.com:fastlane/fastlane.git", # The URL of the repository to import the Fastfile from.
70
- branch: "HEAD", # The branch to checkout on the repository
71
- path: "fastlane/Fastfile", # The path of the Fastfile in the repository
70
+ branch: "HEAD", # The branch to checkout on the repository.
71
+ path: "fastlane/Fastfile", # The path of the Fastfile in the repository.
72
72
  version: [">= 1.1.0", "< 2.0.0"], # The version to checkout on the repository. Multiple conditions can be used to select the latest version within constraints.
73
73
  cache_path: "~/.cache/fastlane/imported" # A directory in which the repository will be added, which means that it will not be cloned again on subsequent calls.
74
74
  )'
@@ -13,7 +13,7 @@ module Fastlane
13
13
  app_icon: :appIcon,
14
14
  content_image: :contentImage
15
15
  }
16
- options = Hash[options.map { |k, v| [option_map.fetch(k, k), v] }]
16
+ options = options.transform_keys { |k| option_map.fetch(k, k) }
17
17
  TerminalNotifier.notify(message, options)
18
18
  end
19
19
 
@@ -1,70 +1,178 @@
1
+ require 'fastlane/notification/slack'
2
+
1
3
  # rubocop:disable Style/CaseEquality
2
4
  # rubocop:disable Style/MultilineTernaryOperator
3
5
  # rubocop:disable Style/NestedTernaryOperator
4
6
  module Fastlane
5
7
  module Actions
6
8
  class SlackAction < Action
7
- def self.is_supported?(platform)
8
- true
9
- end
9
+ class Runner
10
+ def initialize(slack_url)
11
+ @notifier = Fastlane::Notification::Slack.new(slack_url)
12
+ end
10
13
 
11
- # As there is a text limit in the notifications, we are
12
- # usually interested in the last part of the message
13
- # e.g. for tests
14
- def self.trim_message(message)
15
- # We want the last 7000 characters, instead of the first 7000, as the error is at the bottom
16
- start_index = [message.length - 7000, 0].max
17
- message = message[start_index..-1]
18
- # We want line breaks to be shown on slack output so we replace
19
- # input non-interpreted line break with interpreted line break
20
- message.gsub('\n', "\n")
21
- end
14
+ def run(options)
15
+ options[:message] = self.class.trim_message(options[:message].to_s || '')
16
+ options[:message] = Fastlane::Notification::Slack::LinkConverter.convert(options[:message])
22
17
 
23
- def self.run(options)
24
- require 'slack-notifier'
18
+ options[:pretext] = options[:pretext].gsub('\n', "\n") unless options[:pretext].nil?
25
19
 
26
- options[:message] = self.trim_message(options[:message].to_s || '')
27
- options[:message] = Slack::Notifier::Util::LinkFormatter.format(options[:message])
20
+ if options[:channel].to_s.length > 0
21
+ channel = options[:channel]
22
+ channel = ('#' + options[:channel]) unless ['#', '@'].include?(channel[0]) # send message to channel by default
23
+ end
28
24
 
29
- options[:pretext] = options[:pretext].gsub('\n', "\n") unless options[:pretext].nil?
25
+ username = options[:use_webhook_configured_username_and_icon] ? nil : options[:username]
30
26
 
31
- if options[:channel].to_s.length > 0
32
- channel = options[:channel]
33
- channel = ('#' + options[:channel]) unless ['#', '@'].include?(channel[0]) # send message to channel by default
27
+ slack_attachment = self.class.generate_slack_attachments(options)
28
+ link_names = options[:link_names]
29
+ icon_url = options[:use_webhook_configured_username_and_icon] ? nil : options[:icon_url]
30
+
31
+ post_message(
32
+ channel: channel,
33
+ username: username,
34
+ attachments: [slack_attachment],
35
+ link_names: link_names,
36
+ icon_url: icon_url,
37
+ fail_on_error: options[:fail_on_error]
38
+ )
34
39
  end
35
40
 
36
- username = options[:use_webhook_configured_username_and_icon] ? nil : options[:username]
41
+ def post_message(channel:, username:, attachments:, link_names:, icon_url:, fail_on_error:)
42
+ @notifier.post_to_legacy_incoming_webhook(
43
+ channel: channel,
44
+ username: username,
45
+ link_names: link_names,
46
+ icon_url: icon_url,
47
+ attachments: attachments
48
+ )
49
+ UI.success('Successfully sent Slack notification')
50
+ rescue => error
51
+ UI.error("Exception: #{error}")
52
+ message = "Error pushing Slack message, maybe the integration has no permission to post on this channel? Try removing the channel parameter in your Fastfile, this is usually caused by a misspelled or changed group/channel name or an expired SLACK_URL"
53
+ if fail_on_error
54
+ UI.user_error!(message)
55
+ else
56
+ UI.error(message)
57
+ end
58
+ end
37
59
 
38
- notifier = Slack::Notifier.new(options[:slack_url], channel: channel, username: username)
60
+ # As there is a text limit in the notifications, we are
61
+ # usually interested in the last part of the message
62
+ # e.g. for tests
63
+ def self.trim_message(message)
64
+ # We want the last 7000 characters, instead of the first 7000, as the error is at the bottom
65
+ start_index = [message.length - 7000, 0].max
66
+ message = message[start_index..-1]
67
+ # We want line breaks to be shown on slack output so we replace
68
+ # input non-interpreted line break with interpreted line break
69
+ message.gsub('\n', "\n")
70
+ end
39
71
 
40
- link_names = options[:link_names]
72
+ def self.generate_slack_attachments(options)
73
+ color = (options[:success] ? 'good' : 'danger')
74
+ should_add_payload = ->(payload_name) { options[:default_payloads].map(&:to_sym).include?(payload_name.to_sym) }
41
75
 
42
- icon_url = options[:use_webhook_configured_username_and_icon] ? nil : options[:icon_url]
76
+ slack_attachment = {
77
+ fallback: options[:message],
78
+ text: options[:message],
79
+ pretext: options[:pretext],
80
+ color: color,
81
+ mrkdwn_in: ["pretext", "text", "fields", "message"],
82
+ fields: []
83
+ }
43
84
 
44
- slack_attachment = generate_slack_attachments(options)
85
+ # custom user payloads
86
+ slack_attachment[:fields] += options[:payload].map do |k, v|
87
+ {
88
+ title: k.to_s,
89
+ value: Fastlane::Notification::Slack::LinkConverter.convert(v.to_s),
90
+ short: false
91
+ }
92
+ end
45
93
 
46
- return [notifier, slack_attachment] if Helper.test? # tests will verify the slack attachments and other properties
94
+ # Add the lane to the Slack message
95
+ # This might be nil, if slack is called as "one-off" action
96
+ if should_add_payload[:lane] && Actions.lane_context[Actions::SharedValues::LANE_NAME]
97
+ slack_attachment[:fields] << {
98
+ title: 'Lane',
99
+ value: Actions.lane_context[Actions::SharedValues::LANE_NAME],
100
+ short: true
101
+ }
102
+ end
47
103
 
48
- begin
49
- results = notifier.ping('', link_names: link_names, icon_url: icon_url, attachments: [slack_attachment])
50
- rescue => exception
51
- UI.error("Exception: #{exception}")
52
- ensure
53
- result = results.first if results
54
- if !result.nil? && result.code.to_i == 200
55
- UI.success('Successfully sent Slack notification')
56
- else
57
- UI.verbose(result) unless result.nil?
58
- message = "Error pushing Slack message, maybe the integration has no permission to post on this channel? Try removing the channel parameter in your Fastfile, this is usually caused by a misspelled or changed group/channel name or an expired SLACK_URL"
59
- if options[:fail_on_error]
60
- UI.user_error!(message)
104
+ # test_result
105
+ if should_add_payload[:test_result]
106
+ slack_attachment[:fields] << {
107
+ title: 'Result',
108
+ value: (options[:success] ? 'Success' : 'Error'),
109
+ short: true
110
+ }
111
+ end
112
+
113
+ # git branch
114
+ if Actions.git_branch && should_add_payload[:git_branch]
115
+ slack_attachment[:fields] << {
116
+ title: 'Git Branch',
117
+ value: Actions.git_branch,
118
+ short: true
119
+ }
120
+ end
121
+
122
+ # git_author
123
+ if Actions.git_author_email && should_add_payload[:git_author]
124
+ if FastlaneCore::Env.truthy?('FASTLANE_SLACK_HIDE_AUTHOR_ON_SUCCESS') && options[:success]
125
+ # We only show the git author if the build failed
61
126
  else
62
- UI.error(message)
127
+ slack_attachment[:fields] << {
128
+ title: 'Git Author',
129
+ value: Actions.git_author_email,
130
+ short: true
131
+ }
63
132
  end
64
133
  end
134
+
135
+ # last_git_commit
136
+ if Actions.last_git_commit_message && should_add_payload[:last_git_commit]
137
+ slack_attachment[:fields] << {
138
+ title: 'Git Commit',
139
+ value: Actions.last_git_commit_message,
140
+ short: false
141
+ }
142
+ end
143
+
144
+ # last_git_commit_hash
145
+ if Actions.last_git_commit_hash(true) && should_add_payload[:last_git_commit_hash]
146
+ slack_attachment[:fields] << {
147
+ title: 'Git Commit Hash',
148
+ value: Actions.last_git_commit_hash(short: true),
149
+ short: false
150
+ }
151
+ end
152
+
153
+ # merge additional properties
154
+ deep_merge(slack_attachment, options[:attachment_properties])
155
+ end
156
+
157
+ # Adapted from https://stackoverflow.com/a/30225093/158525
158
+ def self.deep_merge(a, b)
159
+ merger = proc do |key, v1, v2|
160
+ Hash === v1 && Hash === v2 ?
161
+ v1.merge(v2, &merger) : Array === v1 && Array === v2 ?
162
+ v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2
163
+ end
164
+ a.merge(b, &merger)
65
165
  end
66
166
  end
67
167
 
168
+ def self.is_supported?(platform)
169
+ true
170
+ end
171
+
172
+ def self.run(options)
173
+ Runner.new(options[:slack_url]).run(options)
174
+ end
175
+
68
176
  def self.description
69
177
  "Send a success/error message to your [Slack](https://slack.com) group"
70
178
  end
@@ -185,99 +293,13 @@ module Fastlane
185
293
  # @!group Helper
186
294
  #####################################################
187
295
 
188
- def self.generate_slack_attachments(options)
189
- color = (options[:success] ? 'good' : 'danger')
190
- should_add_payload = ->(payload_name) { options[:default_payloads].map(&:to_sym).include?(payload_name.to_sym) }
191
-
192
- slack_attachment = {
193
- fallback: options[:message],
194
- text: options[:message],
195
- pretext: options[:pretext],
196
- color: color,
197
- mrkdwn_in: ["pretext", "text", "fields", "message"],
198
- fields: []
199
- }
200
-
201
- # custom user payloads
202
- slack_attachment[:fields] += options[:payload].map do |k, v|
203
- {
204
- title: k.to_s,
205
- value: Slack::Notifier::Util::LinkFormatter.format(v.to_s),
206
- short: false
207
- }
208
- end
209
-
210
- # Add the lane to the Slack message
211
- # This might be nil, if slack is called as "one-off" action
212
- if should_add_payload[:lane] && Actions.lane_context[Actions::SharedValues::LANE_NAME]
213
- slack_attachment[:fields] << {
214
- title: 'Lane',
215
- value: Actions.lane_context[Actions::SharedValues::LANE_NAME],
216
- short: true
217
- }
218
- end
219
-
220
- # test_result
221
- if should_add_payload[:test_result]
222
- slack_attachment[:fields] << {
223
- title: 'Result',
224
- value: (options[:success] ? 'Success' : 'Error'),
225
- short: true
226
- }
227
- end
228
-
229
- # git branch
230
- if Actions.git_branch && should_add_payload[:git_branch]
231
- slack_attachment[:fields] << {
232
- title: 'Git Branch',
233
- value: Actions.git_branch,
234
- short: true
235
- }
236
- end
237
-
238
- # git_author
239
- if Actions.git_author_email && should_add_payload[:git_author]
240
- if FastlaneCore::Env.truthy?('FASTLANE_SLACK_HIDE_AUTHOR_ON_SUCCESS') && options[:success]
241
- # We only show the git author if the build failed
242
- else
243
- slack_attachment[:fields] << {
244
- title: 'Git Author',
245
- value: Actions.git_author_email,
246
- short: true
247
- }
248
- end
249
- end
250
-
251
- # last_git_commit
252
- if Actions.last_git_commit_message && should_add_payload[:last_git_commit]
253
- slack_attachment[:fields] << {
254
- title: 'Git Commit',
255
- value: Actions.last_git_commit_message,
256
- short: false
257
- }
258
- end
259
-
260
- # last_git_commit_hash
261
- if Actions.last_git_commit_hash(true) && should_add_payload[:last_git_commit_hash]
262
- slack_attachment[:fields] << {
263
- title: 'Git Commit Hash',
264
- value: Actions.last_git_commit_hash(short: true),
265
- short: false
266
- }
267
- end
268
-
269
- # merge additional properties
270
- deep_merge(slack_attachment, options[:attachment_properties])
296
+ def self.trim_message(message)
297
+ Runner.trim_message(message)
271
298
  end
272
299
 
273
- # Adapted from https://stackoverflow.com/a/30225093/158525
274
- def self.deep_merge(a, b)
275
- merger = proc do |key, v1, v2|
276
- Hash === v1 && Hash === v2 ?
277
- v1.merge(v2, &merger) : Array === v1 && Array === v2 ?
278
- v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2
279
- end
280
- a.merge(b, &merger)
300
+ def self.generate_slack_attachments(options)
301
+ UI.deprecated('`Fastlane::Actions::Slack.generate_slack_attachments` is subject to be removed as Slack recommends migrating `attachments` to Block Kit. fastlane will also follow the same direction.')
302
+ Runner.generate_slack_attachments(options)
281
303
  end
282
304
  end
283
305
  end