fastlane-plugin-slack_bot 0.2.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04a1032a218db318334c1eeec0023420f5ca16de0799d7126207dd94dd7e2524
4
- data.tar.gz: a10469f4218ccd56b18bbd84abd2fcd711c8421eb4065f7c6dbc088ae7f62bc7
3
+ metadata.gz: 289a56616a3791c91d4aa9033fe725da23f086ba112f63f383617de611824aa9
4
+ data.tar.gz: 406ed9f6c5809ed39b6ea2024f9c998409bcb11711616006714fdfef28063441
5
5
  SHA512:
6
- metadata.gz: 8562f7d29c2bbd3cdf5423bf6a0031a373f2afe96c5b13d981a73781b1e57a3e15616b66411c4a1695d4138f1d306e2172eb15a6b465b3069046523f1a53190a
7
- data.tar.gz: e3e767e9cefbd08dfc15ab3d98b907d3e509c81ea09484f431ec565086e912e069a3c25fc51f0cff8a9d761a093197064bc891c46d8b9017c6ea779164e7f83f
6
+ metadata.gz: 821fbff8025635a8c8728e40ceccc52f54db653fc2aaa4ddeed6d7bb5aaec10d78798b19a88282c44ba8168fb0342da8804030bbbf715299827e0b38aca60f9e
7
+ data.tar.gz: d9bd6cc8c9aa8d0dd1704ddd583735f3400a38d2ac440b0a61ff63aa586b079d3b93b75d5f5770f28e523ef097abeaf4142b56ceaefaf77e1f08d0e99e959b2c
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Manish Rathi <m.rathi@catawiki.nl>
3
+ Copyright (c) 2021 Manish Rathi
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,11 +1,30 @@
1
1
  ## Fastlane `slack_bot` plugin
2
2
 
3
- [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-slack_bot) ![![License]](https://img.shields.io/badge/license-MIT-green.svg?style=flat) [![Gem Version](https://badge.fury.io/rb/fastlane-plugin-slack_bot.svg)](https://badge.fury.io/rb/fastlane-plugin-slack_bot) ![![RubyGem Download Badge]](https://ruby-gem-downloads-badge.herokuapp.com/fastlane-plugin-slack_bot?type=total) [![Twitter: @manish](https://img.shields.io/badge/contact-@manish-blue.svg?style=flat)](https://twitter.com/manish_rathi_)
4
-
5
- ## About slack_bot
6
-
7
- A fastlane plugin to post slack message using bot api token. 🚀\
8
- Note: `Fastlane` comes with `slack` plugin by default, which uses slack webhook url, which can't send direct message & other webhook limitations.
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-slack_bot)
4
+ ![![License]](https://img.shields.io/badge/license-MIT-green.svg?style=flat)
5
+ [![Gem Version](https://badge.fury.io/rb/fastlane-plugin-slack_bot.svg)](https://badge.fury.io/rb/fastlane-plugin-slack_bot)
6
+ ![![RubyGem Download Badge]](https://ruby-gem-downloads-badge.herokuapp.com/fastlane-plugin-slack_bot?type=total)
7
+ [![Twitter: @manish](https://img.shields.io/badge/contact-@manish-blue.svg?style=flat)](https://twitter.com/iammanishrathi)
8
+
9
+ A fastlane plugin to customize your automation workflow(s) with a **Slack Bot** 🤖 using the [Slack APIs](https://api.slack.com/)
10
+
11
+ - [About](#about)
12
+ - [Getting Started](#getting-started)
13
+ - [Features](#features)
14
+ - [Post a message](#examples-post-a-message) examples
15
+ - [Upload a file](#examples-upload-a-message) examples
16
+ - [About Fastlane](#about-fastlane)
17
+
18
+ ## About
19
+
20
+ A fastlane plugin to post slack message and much more using Slack bot api token. 🚀\
21
+ **Note:** `Fastlane` comes with built-in `slack` action by default, which uses slack webhook url and have webhook limitations.
22
+ i.e Listing couple of slack **webhook url** limitations:
23
+ - can't post a direct message to a slack user.
24
+ - can’t post a message inside a slack thread.
25
+ - can’t update a posted slack message.
26
+ - can’t list and upload a file inside a slack channel.
27
+ - much more, compare to a **Slack Bot** 🤖 using the [Slack APIs](https://api.slack.com/)
9
28
 
10
29
  ## Getting Started
11
30
 
@@ -23,41 +42,65 @@ fastlane add_plugin slack_bot
23
42
  ```
24
43
  If you are using fastlane using Gemfile in your project, add it to your project by running:
25
44
  ```bash
26
- bundle exec fastlane add_plugin slack_bot
45
+ bundle exec fastlane add_plugin slack_bot
27
46
  ```
28
47
 
29
- 3. Add `slack_bot` to your lane in `Fastfile` whenever you want to post a slack message
48
+ 3. Use `slack_bot` features inside your lane in `Fastfile` whenever you want.
49
+
50
+ ## Features
51
+ Using this `slack_bot` plugin, you can:
52
+
53
+ - Post a message using [chat.postMessage](https://api.slack.com/methods/chat.postMessage) Slack API
54
+ - [x] Post a message to a _public_ channel
55
+ - [x] Post a message to a _private_ channel
56
+ - [x] Post a message to a _slack user_ (DM)
57
+ - [x] Post a message inside a _slack thread_ 🧵
58
+ - [x] Post a message with _custom Bot username and icon_
59
+
60
+ - Update a message using [chat.update](https://api.slack.com/methods/chat.update) Slack API
61
+ - [x] update a message in a channel
62
+
63
+ - List of files in a channel using [files.list](https://api.slack.com/methods/files.list) Slack API
64
+ - [x] A list of files in a channel, It can be filtered and sliced in various ways.
65
+
66
+ - Upload a file using [files.upload](https://api.slack.com/methods/files.upload) Slack API
67
+ - [x] Upload a file to a _public_ channel
68
+ - [x] Upload a file to a _private_ channel
69
+ - [x] Upload a file to a _slack user_ (DM)
70
+ - [x] Upload a file inside a _slack thread_ 🧵
71
+ - [x] Upload a file with _multiple channels/users_
72
+
30
73
 
31
- ## Examples
74
+ ## Examples (Post a message)
32
75
 
33
- In the following example lets send a message to the default slack bot channel.
76
+ Let’s post a message to the default slack bot channel.
34
77
 
35
78
  ```ruby
36
79
  # share on Slack
37
- post_to_slack(message: "App successfully released!")
80
+ post_to_slack(message: "App successfully released!")
38
81
  ```
39
82
 
40
- In the following example lets send a direct message to a slack user that unit tests CI has been failed.
83
+ Let’s post a direct message to a slack user that unit tests CI has been failed.
41
84
 
42
85
  ```ruby
43
86
  # share on Slack
44
- post_to_slack(
45
- message: "CI: Your unit tests on #{ENV['CI_COMMIT_REF_NAME']} failed",
46
- channel: "@SlackUsername" # This can be Slack userID, instead of username i.e @UXXXXX
47
- )
87
+ post_to_slack(
88
+ message: "CI: Your unit tests on #{ENV['CI_COMMIT_REF_NAME']} failed",
89
+ channel: "@SlackUsername" # This can be Slack userID, instead of username i.e @UXXXXX
90
+ )
48
91
  ```
49
92
 
50
- In the following example lets send slack message to `#ios-team` channel for test-flight build.
93
+ Let’s post a slack message to the `#ios-team` channel about the new test-flight build.
51
94
 
52
95
  ```ruby
53
96
  lane :beta do
54
97
  gym # Build the app and create .ipa file
55
98
  pilot # Upload build to TestFlight
56
-
99
+
57
100
  version_number = get_version_number # Get project version
58
101
  build_number = get_build_number # Get build number
59
102
  beta_release_name = "#{version_number}-#{build_number}-beta-release"
60
-
103
+
61
104
  # share on Slack
62
105
  post_to_slack(
63
106
  message: "Hi team, we have a new test-flight beta build: #{beta_release_name}",
@@ -66,7 +109,7 @@ lane :beta do
66
109
  end
67
110
  ```
68
111
 
69
- In the following example lets send slack message with custom payload.
112
+ Let’s post a slack message with custom payload.
70
113
 
71
114
  ```ruby
72
115
  # share on Slack
@@ -93,18 +136,115 @@ post_to_slack(
93
136
  )
94
137
  ```
95
138
 
96
- ## Issues and Feedback
139
+ Let’s post a slack message inside a slack thread 🧵
140
+
141
+ ```ruby
142
+ lane :release do
143
+ # Start the release with slack release thread
144
+ release_thread = post_to_slack(
145
+ message: "Good morning team, CI has started the AppStore release. You can find more information inside this thread 🧵",
146
+ channel: "#ios-team"
147
+ )
148
+
149
+ # Important: Save this slack thread timestamp for futher slack messages
150
+ release_thread_ts = release_thread[:json]["ts"]
151
+
152
+ gym # Build the app and create .ipa file
97
153
 
98
- For any other issues and feedback about this plugin, please submit it to this repository.
154
+ # Post an update in release thread
155
+ post_to_slack(
156
+ message: "App has been build successfully! 💪",
157
+ channel: "#ios-team",
158
+ thread_ts: release_thread_ts
159
+ )
99
160
 
100
- ## Troubleshooting
161
+ deliver # Upload build to AppStore
101
162
 
102
- If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
163
+ # Post an update in release thread
164
+ post_to_slack(
165
+ message: "App has been uploaded to the AppStore and submitted for Apple's review! 🚀",
166
+ channel: "#ios-team",
167
+ thread_ts: release_thread_ts
168
+ )
169
+ end
170
+ ```
103
171
 
104
- ## Using _fastlane_ Plugins
172
+ Let’s post a message with custom slack bot username and icon
105
173
 
106
- For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
174
+ ```ruby
175
+ # share on Slack
176
+ post_to_slack(
177
+ message: "App successfully released!",
178
+ username: "Release Bot", # Overrides the bot's username
179
+ icon_url: "https://fastlane.tools/assets/img/fastlane_icon.png" # Overrides the bot's icon
180
+ )
181
+ ```
182
+
183
+ ## Examples (Upload a file)
184
+
185
+ Let’s Upload a file to a slack channel that main branch unit tests has been failed, see scan logs.
186
+
187
+ ```ruby
188
+ # File upload on Slack
189
+ file_upload_to_slack(
190
+ initial_comment: "CI: main-branch unit tests failed",
191
+ file_path: "scan.log",
192
+ channels: "#ios-team" # Comma-separated list of slack #channel names where the file will be shared
193
+ )
194
+ ```
195
+
196
+ Let’s Upload a file to a slack user that your branch unit tests has been failed, see scan logs.
197
+
198
+ ```ruby
199
+ # File upload on Slack
200
+ file_upload_to_slack(
201
+ initial_comment: "CI: Your unit tests on #{ENV['CI_COMMIT_REF_NAME']} failed",
202
+ file_path: "scan.log",
203
+ channels: "@SlackUsername" # This can be Slack userID, instead of username i.e @UXXXXX
204
+ )
205
+ ```
206
+
207
+ Let’s Upload a file inside a slack thread 🧵
208
+
209
+ ```ruby
210
+ lane :release do
211
+ # Start the release with slack release thread
212
+ release_thread = post_to_slack(
213
+ message: "Good morning team, CI has started the AppStore release. You can find more information inside this thread 🧵",
214
+ channel: "#ios-team"
215
+ )
216
+
217
+ # Important: Save this slack thread timestamp for futher slack messages
218
+ release_thread_ts = release_thread[:json]["ts"]
219
+
220
+ gym # Build the app and create .ipa file
221
+
222
+ # Post an update in release thread
223
+ post_to_slack(
224
+ message: "App has been build successfully! 💪",
225
+ channel: "#ios-team",
226
+ thread_ts: release_thread_ts
227
+ )
228
+
229
+ deliver # Upload build to AppStore
230
+
231
+ # Post an update in release thread
232
+ post_to_slack(
233
+ message: "App has been uploaded to the AppStore and submitted for Apple's review! 🚀",
234
+ channel: "#ios-team",
235
+ thread_ts: release_thread_ts
236
+ )
237
+
238
+ # Spaceship logs file upload on Slack
239
+ file_upload_to_slack(
240
+ initial_comment: "Deliver:: Spaceship logs",
241
+ file_path: "spaceship.log",
242
+ channels: "#ios-team",
243
+ thread_ts: release_thread_ts
244
+ )
245
+ end
246
+ ```
107
247
 
108
- ## About _fastlane_
248
+ ## About Fastlane
109
249
 
110
250
  _fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
@@ -0,0 +1,176 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/slack_bot_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ FILE_UPLOAD_TO_SLACK_RESULT = :FILE_UPLOAD_TO_SLACK_RESULT
8
+ end
9
+
10
+ class FileUploadToSlackAction < Action
11
+ def self.run(params)
12
+ file_path = params[:file_path]
13
+
14
+ if params[:file_name].to_s.empty?
15
+ file_name = File.basename(file_path, ".*") # if file_path = "/path/file_name.jpeg" then will return "file_name"
16
+ else
17
+ file_name = params[:file_name]
18
+ end
19
+
20
+ if params[:file_type].to_s.empty?
21
+ file_type = File.extname(file_path)[1..-1] # if file_path = "/path/file_name.jpeg" then will return "jpeg"
22
+ else
23
+ file_type = params[:file_type]
24
+ end
25
+
26
+ begin
27
+ require 'faraday'
28
+
29
+ api_url = "https://slack.com/api/files.upload"
30
+ conn = Faraday.new(url: api_url) do |faraday|
31
+ faraday.request :multipart
32
+ faraday.request :url_encoded
33
+ faraday.adapter :net_http
34
+ end
35
+
36
+ payload = {
37
+ channels: params[:channels],
38
+ file: Faraday::FilePart.new(file_path, file_type),
39
+ filename: file_name,
40
+ filetype: file_type
41
+ }
42
+
43
+ payload[:title] = params[:title] unless params[:title].nil?
44
+ payload[:initial_comment] = params[:initial_comment] unless params[:initial_comment].nil?
45
+ payload[:thread_ts] = params[:thread_ts] unless params[:thread_ts].nil?
46
+
47
+ response = conn.post do |req|
48
+ req.headers['Authorization'] = "Bearer #{params[:api_token]}"
49
+ req.body = payload
50
+ end
51
+
52
+ result = self.formatted_result(response)
53
+ rescue => exception
54
+ UI.error("Exception: #{exception}")
55
+ return nil
56
+ else
57
+ UI.success("Successfully uploaded file to Slack! 🚀")
58
+ Actions.lane_context[SharedValues::FILE_UPLOAD_TO_SLACK_RESULT] = result
59
+ return result
60
+ end
61
+ end
62
+
63
+ def self.formatted_result(response)
64
+ result = {
65
+ status: response[:status],
66
+ body: response.body || "",
67
+ json: self.parse_json(response.body) || {}
68
+ }
69
+ end
70
+
71
+ def self.parse_json(value)
72
+ require 'json'
73
+
74
+ JSON.parse(value)
75
+ rescue JSON::ParserError
76
+ nil
77
+ end
78
+
79
+ #####################################################
80
+ # @!group Documentation
81
+ #####################################################
82
+
83
+ def self.description
84
+ "Upload a file to slack channel"
85
+ end
86
+
87
+ def self.details
88
+ "Upload a file to slack channel or DM to a slack user"
89
+ end
90
+
91
+ def self.available_options
92
+ [
93
+ FastlaneCore::ConfigItem.new(key: :api_token,
94
+ env_name: "FL_FILE_UPLOAD_TO_SLACK_BOT_TOKEN",
95
+ description: "Slack bot Token",
96
+ sensitive: true,
97
+ code_gen_sensitive: true,
98
+ is_string: true,
99
+ default_value: ENV["SLACK_API_TOKEN"],
100
+ default_value_dynamic: true,
101
+ optional: false),
102
+ FastlaneCore::ConfigItem.new(key: :channels,
103
+ env_name: "FL_FETCH_FILES_SLACK_CHANNELS",
104
+ description: "Comma-separated list of slack #channel names where the file will be shared",
105
+ is_string: true,
106
+ optional: false),
107
+ FastlaneCore::ConfigItem.new(key: :file_path,
108
+ env_name: "FL_FILE_UPLOAD_TO_SLACK_FILE_PATH",
109
+ description: "relative file path which will upload to slack",
110
+ is_string: true,
111
+ optional: false),
112
+ FastlaneCore::ConfigItem.new(key: :file_name,
113
+ env_name: "FL_FILE_UPLOAD_TO_SLACK_FILE_NAME",
114
+ description: "This is optional filename of the file",
115
+ is_string: true,
116
+ optional: true),
117
+ FastlaneCore::ConfigItem.new(key: :file_type,
118
+ env_name: "FL_FILE_UPLOAD_TO_SLACK_FILE_TYPE",
119
+ description: "This is optional filetype of the file",
120
+ is_string: true,
121
+ optional: true),
122
+ FastlaneCore::ConfigItem.new(key: :title,
123
+ env_name: "FL_FILE_UPLOAD_TO_SLACK_TITLE",
124
+ description: "This is optional Title of file",
125
+ is_string: true,
126
+ optional: true),
127
+ FastlaneCore::ConfigItem.new(key: :initial_comment,
128
+ env_name: "FL_FILE_UPLOAD_TO_SLACK_INITIAL_COMMENT",
129
+ description: "This is optional message text introducing the file",
130
+ is_string: true,
131
+ optional: true),
132
+ FastlaneCore::ConfigItem.new(key: :thread_ts,
133
+ env_name: "FL_FILE_UPLOAD_TO_SLACK_THREAD_TS",
134
+ description: "Provide another message's ts value to make this message a reply",
135
+ is_string: true,
136
+ optional: true)
137
+ ]
138
+ end
139
+
140
+ def self.authors
141
+ ["crazymanish"]
142
+ end
143
+
144
+ def self.example_code
145
+ [
146
+ 'file_upload_to_slack(
147
+ channels: "slack_channel_name",
148
+ file_path: "fastlane/test.png"
149
+ )',
150
+ 'file_upload_to_slack(
151
+ title: "This is test title",
152
+ channels: "slack_channel_name1, slack_channel_name2",
153
+ file_path: "fastlane/report.xml"
154
+ )',
155
+ 'file_upload_to_slack(
156
+ title: "This is test title",
157
+ initial_comment: "This is test initial comment",
158
+ channels: "slack_channel_name",
159
+ file_path: "fastlane/screenshots.zip"
160
+ )',
161
+ 'file_upload_to_slack(
162
+ title: "This is test title", # Optional, uploading file title
163
+ initial_comment: "This is test initial comment", # Optional, uploading file initial comment
164
+ channels: "slack_channel_name",
165
+ file_path: "fastlane/screenshots.zip",
166
+ thread_ts: thread_ts # Optional, Provide parent slack message `ts` value to upload this file as a reply.
167
+ )'
168
+ ]
169
+ end
170
+
171
+ def self.is_supported?(platform)
172
+ true
173
+ end
174
+ end
175
+ end
176
+ end
@@ -1,5 +1,7 @@
1
1
  require 'fastlane/action'
2
2
  require_relative '../helper/slack_bot_helper'
3
+ require_relative '../helper/slack_bot_attachments_helper'
4
+ require_relative '../helper/slack_bot_link_formatter_helper'
3
5
 
4
6
  module Fastlane
5
7
  module Actions
@@ -9,10 +11,8 @@ module Fastlane
9
11
 
10
12
  class PostToSlackAction < Action
11
13
  def self.run(options)
12
- require 'slack-notifier'
13
-
14
14
  options[:message] = (options[:message].to_s || '').gsub('\n', "\n")
15
- options[:message] = Slack::Notifier::Util::LinkFormatter.format(options[:message])
15
+ options[:message] = Helper::SlackBotLinkFormatterHelper.format(options[:message])
16
16
  options[:pretext] = options[:pretext].gsub('\n', "\n") unless options[:pretext].nil?
17
17
 
18
18
  if options[:channel].to_s.length > 0
@@ -20,14 +20,25 @@ module Fastlane
20
20
  slack_channel = ('#' + options[:channel]) unless ['#', 'C', '@'].include?(slack_channel[0]) # Add prefix(#) by default, if needed
21
21
  end
22
22
 
23
- slack_attachment = SlackAction.generate_slack_attachments(options)
23
+ slack_attachment = Helper::SlackBotAttachmentsHelper.generate_slack_attachments(options)
24
+ bot_username = options[:username]
25
+ bot_icon_url = options[:icon_url]
24
26
 
25
27
  begin
26
28
  require 'excon'
27
29
 
28
30
  api_url = "https://slack.com/api/chat.postMessage"
29
- headers = { "Content-Type": "application/json", "Authorization": "Bearer #{options[:api_token]}" }
30
- payload = { channel: slack_channel, attachments: [slack_attachment] }
31
+ headers = {
32
+ "Content-Type": "application/json; charset=utf-8",
33
+ "Authorization": "Bearer #{options[:api_token]}"
34
+ }
35
+ payload = {
36
+ channel: slack_channel,
37
+ username: bot_username,
38
+ icon_url: bot_icon_url,
39
+ attachments: [slack_attachment]
40
+ }
41
+ payload[:as_user] = options[:as_user] if options[:as_user] # default is false
31
42
  payload[:thread_ts] = options[:thread_ts] unless options[:thread_ts].nil?
32
43
  payload = payload.to_json
33
44
 
@@ -82,6 +93,24 @@ module Fastlane
82
93
  env_name: "FL_POST_TO_SLACK_CHANNEL",
83
94
  description: "#channel or @username",
84
95
  optional: true),
96
+ FastlaneCore::ConfigItem.new(key: :username,
97
+ env_name: "FL_SLACK_USERNAME",
98
+ description: "Overrides the bot's username (chat:write.customize scope required)",
99
+ default_value: "fastlane",
100
+ is_string: true,
101
+ optional: true),
102
+ FastlaneCore::ConfigItem.new(key: :icon_url,
103
+ env_name: "FL_SLACK_ICON_URL",
104
+ description: "Overrides the bot's image (chat:write.customize scope required)",
105
+ default_value: "https://fastlane.tools/assets/img/fastlane_icon.png",
106
+ is_string: true,
107
+ optional: true),
108
+ FastlaneCore::ConfigItem.new(key: :as_user,
109
+ env_name: "FL_POST_TO_SLACK_AS_USER",
110
+ description: "Pass true to post the message as the authed user. Defaults to false",
111
+ optional: true,
112
+ default_value: false,
113
+ is_string: false),
85
114
  FastlaneCore::ConfigItem.new(key: :pretext,
86
115
  env_name: "FL_POST_TO_SLACK_PRETEXT",
87
116
  description: "This is optional text that appears above the message attachment block. This supports the standard Slack markup language",
@@ -99,6 +128,7 @@ module Fastlane
99
128
  env_name: "FL_POST_TO_SLACK_DEFAULT_PAYLOADS",
100
129
  description: "Remove some of the default payloads. More information about the available payloads on GitHub",
101
130
  optional: true,
131
+ default_value: ['lane', 'test_result', 'git_branch', 'git_author', 'last_git_commit', 'last_git_commit_hash'],
102
132
  type: Array),
103
133
  FastlaneCore::ConfigItem.new(key: :attachment_properties,
104
134
  env_name: "FL_POST_TO_SLACK_ATTACHMENT_PROPERTIES",
@@ -1,5 +1,7 @@
1
1
  require 'fastlane/action'
2
2
  require_relative '../helper/slack_bot_helper'
3
+ require_relative '../helper/slack_bot_attachments_helper'
4
+ require_relative '../helper/slack_bot_link_formatter_helper'
3
5
 
4
6
  module Fastlane
5
7
  module Actions
@@ -8,12 +10,10 @@ module Fastlane
8
10
  end
9
11
  class UpdateSlackMessageAction < Action
10
12
  def self.run(options)
11
- require 'slack-notifier'
12
-
13
13
  options[:message] = (options[:message].to_s || '').gsub('\n', "\n")
14
- options[:message] = Slack::Notifier::Util::LinkFormatter.format(options[:message])
14
+ options[:message] = Helper::SlackBotLinkFormatterHelper.format(options[:message])
15
15
  options[:pretext] = options[:pretext].gsub('\n', "\n") unless options[:pretext].nil?
16
- slack_attachment = SlackAction.generate_slack_attachments(options)
16
+ slack_attachment = Helper::SlackBotAttachmentsHelper.generate_slack_attachments(options)
17
17
 
18
18
  begin
19
19
  require 'excon'
@@ -90,6 +90,7 @@ module Fastlane
90
90
  env_name: "FL_UPDATE_SLACK_MESSAGE_DEFAULT_PAYLOADS",
91
91
  description: "Remove some of the default payloads. More information about the available payloads on GitHub",
92
92
  optional: true,
93
+ default_value: ['lane', 'test_result', 'git_branch', 'git_author', 'last_git_commit', 'last_git_commit_hash'],
93
94
  type: Array),
94
95
  FastlaneCore::ConfigItem.new(key: :attachment_properties,
95
96
  env_name: "FL_UPDATE_SLACK_MESSAGE_ATTACHMENT_PROPERTIES",
@@ -0,0 +1,113 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'fastlane_core/env'
3
+ require_relative 'slack_bot_link_formatter_helper'
4
+
5
+ module Fastlane
6
+ UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
7
+
8
+ module Helper
9
+ class SlackBotAttachmentsHelper
10
+ # class methods that you define here become available in your action
11
+ # as `Helper::SlackBotAttachmentsHelper.your_method`
12
+ #
13
+ def self.show_message
14
+ UI.message("Hello from the slack_bot plugin attachments helper!")
15
+ end
16
+
17
+ def self.generate_slack_attachments(options)
18
+ color = (options[:success] ? 'good' : 'danger')
19
+ should_add_payload = ->(payload_name) { options[:default_payloads].map(&:to_sym).include?(payload_name.to_sym) }
20
+
21
+ slack_attachment = {
22
+ fallback: options[:message],
23
+ text: options[:message],
24
+ pretext: options[:pretext],
25
+ color: color,
26
+ mrkdwn_in: ["pretext", "text", "fields", "message"],
27
+ fields: []
28
+ }
29
+
30
+ # custom user payloads
31
+ slack_attachment[:fields] += options[:payload].map do |k, v|
32
+ {
33
+ title: k.to_s,
34
+ value: SlackBotLinkFormatterHelper.format(v.to_s),
35
+ short: false
36
+ }
37
+ end
38
+
39
+ # Add the lane to the Slack message
40
+ # This might be nil, if slack is called as "one-off" action
41
+ if should_add_payload[:lane] && Actions.lane_context[Actions::SharedValues::LANE_NAME]
42
+ slack_attachment[:fields] << {
43
+ title: 'Lane',
44
+ value: Actions.lane_context[Actions::SharedValues::LANE_NAME],
45
+ short: true
46
+ }
47
+ end
48
+
49
+ # test_result
50
+ if should_add_payload[:test_result]
51
+ slack_attachment[:fields] << {
52
+ title: 'Result',
53
+ value: (options[:success] ? 'Success' : 'Error'),
54
+ short: true
55
+ }
56
+ end
57
+
58
+ # git branch
59
+ if Actions.git_branch && should_add_payload[:git_branch]
60
+ slack_attachment[:fields] << {
61
+ title: 'Git Branch',
62
+ value: Actions.git_branch,
63
+ short: true
64
+ }
65
+ end
66
+
67
+ # git_author
68
+ if Actions.git_author_email && should_add_payload[:git_author]
69
+ if FastlaneCore::Env.truthy?('FASTLANE_SLACK_HIDE_AUTHOR_ON_SUCCESS') && options[:success]
70
+ # We only show the git author if the build failed
71
+ else
72
+ slack_attachment[:fields] << {
73
+ title: 'Git Author',
74
+ value: Actions.git_author_email,
75
+ short: true
76
+ }
77
+ end
78
+ end
79
+
80
+ # last_git_commit
81
+ if Actions.last_git_commit_message && should_add_payload[:last_git_commit]
82
+ slack_attachment[:fields] << {
83
+ title: 'Git Commit',
84
+ value: Actions.last_git_commit_message,
85
+ short: false
86
+ }
87
+ end
88
+
89
+ # last_git_commit_hash
90
+ if Actions.last_git_commit_hash(true) && should_add_payload[:last_git_commit_hash]
91
+ slack_attachment[:fields] << {
92
+ title: 'Git Commit Hash',
93
+ value: Actions.last_git_commit_hash(short: true),
94
+ short: false
95
+ }
96
+ end
97
+
98
+ # merge additional properties
99
+ deep_merge(slack_attachment, options[:attachment_properties])
100
+ end
101
+
102
+ # Adapted from https://stackoverflow.com/a/30225093/158525
103
+ def self.deep_merge(a, b)
104
+ merger = proc do |key, v1, v2|
105
+ Hash === v1 && Hash === v2 ?
106
+ v1.merge(v2, &merger) : Array === v1 && Array === v2 ?
107
+ v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2
108
+ end
109
+ a.merge(b, &merger)
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,82 @@
1
+ require 'fastlane_core/ui/ui'
2
+
3
+ module Fastlane
4
+ UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
5
+
6
+ module Helper
7
+ # Fastlane is moving away 'slack-notifier' gem, https://github.com/fastlane/fastlane/pull/18512
8
+ # Duplicate of: https://github.com/stevenosloan/slack-notifier/blob/master/lib/slack-notifier/util/link_formatter.rb
9
+ class SlackBotLinkFormatterHelper
10
+ # http://rubular.com/r/19cNXW5qbH
11
+ HTML_PATTERN = %r{
12
+ <a
13
+ (?:.*?)
14
+ href=['"](.+?)['"]
15
+ (?:.*?)>
16
+ (.+?)
17
+ </a>
18
+ }x
19
+
20
+ # the path portion of a url can contain these characters
21
+ VALID_PATH_CHARS = '\w\-\.\~\/\?\#\='
22
+
23
+ # Attempt at only matching pairs of parens per
24
+ # the markdown spec http://spec.commonmark.org/0.27/#links
25
+ #
26
+ # http://rubular.com/r/y107aevxqT
27
+ MARKDOWN_PATTERN = %r{
28
+ \[ ([^\[\]]*?) \]
29
+ \( ((https?://.*?) | (mailto:.*?)) \)
30
+ (?! [#{VALID_PATH_CHARS}]* \) )
31
+ }x
32
+
33
+ class << self
34
+ def format string, opts={}
35
+ SlackBotLinkFormatterHelper.new(string, opts).formatted
36
+ end
37
+ end
38
+
39
+ attr_reader :formats
40
+
41
+ def initialize string, formats: %i[html markdown]
42
+ @formats = formats
43
+ @orig = string.respond_to?(:scrub) ? string.scrub : string
44
+ end
45
+
46
+ # rubocop:disable Lint/RescueWithoutErrorClass
47
+ def formatted
48
+ return @orig unless @orig.respond_to?(:gsub)
49
+
50
+ sub_markdown_links(sub_html_links(@orig))
51
+ rescue => e
52
+ raise e unless RUBY_VERSION < "2.1" && e.message.include?("invalid byte sequence")
53
+ raise e, "#{e.message}. Consider including the 'string-scrub' gem to strip invalid characters"
54
+ end
55
+ # rubocop:enable Lint/RescueWithoutErrorClass
56
+
57
+ private
58
+
59
+ def sub_html_links string
60
+ return string unless formats.include?(:html)
61
+
62
+ string.gsub(HTML_PATTERN) do
63
+ slack_link Regexp.last_match[1], Regexp.last_match[2]
64
+ end
65
+ end
66
+
67
+ def sub_markdown_links string
68
+ return string unless formats.include?(:markdown)
69
+
70
+ string.gsub(MARKDOWN_PATTERN) do
71
+ slack_link Regexp.last_match[2], Regexp.last_match[1]
72
+ end
73
+ end
74
+
75
+ def slack_link link, text=nil
76
+ "<#{link}" \
77
+ "#{text && !text.empty? ? "|#{text}" : ''}" \
78
+ ">"
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module SlackBot
3
- VERSION = "0.2.0"
3
+ VERSION = "1.0.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-slack_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manish Rathi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-03 00:00:00.000000000 Z
11
+ date: 2021-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -146,9 +146,12 @@ files:
146
146
  - README.md
147
147
  - lib/fastlane/plugin/slack_bot.rb
148
148
  - lib/fastlane/plugin/slack_bot/actions/fetch_files_slack.rb
149
+ - lib/fastlane/plugin/slack_bot/actions/file_upload_to_slack.rb
149
150
  - lib/fastlane/plugin/slack_bot/actions/post_to_slack.rb
150
151
  - lib/fastlane/plugin/slack_bot/actions/update_slack_message.rb
152
+ - lib/fastlane/plugin/slack_bot/helper/slack_bot_attachments_helper.rb
151
153
  - lib/fastlane/plugin/slack_bot/helper/slack_bot_helper.rb
154
+ - lib/fastlane/plugin/slack_bot/helper/slack_bot_link_formatter_helper.rb
152
155
  - lib/fastlane/plugin/slack_bot/version.rb
153
156
  homepage: https://github.com/crazymanish/fastlane-plugin-slack_bot
154
157
  licenses: