fastlane-plugin-slack_bot 0.2.0 → 1.0.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
  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: