fastlane-plugin-slack_bot 0.1.1 → 0.4.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: 84150b4d8bfe68f61b291cc1fc396fda4433d946eac7ab1e20a59f64bdb09c28
4
- data.tar.gz: 35388a239d7fea67abd814b89dd4221a93512f484005856a929f60bf3b5d442f
3
+ metadata.gz: 4f2aabbc8c122fde9ab66c2f19a43ee068eeb1905fe71676b58f3f97615df758
4
+ data.tar.gz: 2f14989f7e4afcf43fd873748b385bb9fb30c5e8b419d4c4ad35b5f910dedd8b
5
5
  SHA512:
6
- metadata.gz: 9fc6ea47846538f9d50ac3993933a178bcdc0d121b4f0cc6e66a1064b957acc768e837f5b7f6468eef569dddb735761c0cdfe04d608aaad61da0c806e0f2f7cf
7
- data.tar.gz: eb2ad02684ebeba9c283990ccc35767cb307aeb174512e0a46dc5db6773e58e8c9897ccedc1235923bbec0153f5c575d9e0b3d27ada869f91c4afbf972528b49
6
+ metadata.gz: 4aa6547bd6c2d4b3f4275be0296027171e1e4f47e90540bd676e1adedc92840bc5945972e1462ada73f1a30eabf8ba7eeebaf9d46e76205d81053bc2595ceb3b
7
+ data.tar.gz: 15a515660c49d9ca4b7d9de700c4212692402c05d53feba5b039fadc82c00f7bf03fcd6255b8467c659ef8545028f823723ef3e30cde8efbd7144fc1b1e8ebfc
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,15 +1,34 @@
1
1
  ## Fastlane `slack_bot` plugin
2
2
 
3
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
-
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 limitations.
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/manish_rathi_)
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
 
12
- 1. Generate `Slack token` for `Fastlane` bot
31
+ 1. [Generate `Slack token` for `Fastlane` bot](https://slack.com/intl/en-nl/help/articles/115005265703-Create-a-bot-for-your-workspace)
13
32
  - From your Slack organization page, go to `Manage` -> `Custom Integrations`
14
33
  - Open `Bots`
15
34
  - Add Configuration
@@ -23,43 +42,197 @@ 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_ 🧵 (DM)
58
+
59
+ - Update a message using [chat.update](https://api.slack.com/methods/chat.update) Slack API
60
+ - [x] update a message in a channel
61
+
62
+ - List of files in a channel using [files.list](https://api.slack.com/methods/files.list) Slack API
63
+ - [x] A list of files in a channel, It can be filtered and sliced in various ways.
64
+
65
+ - Upload a file using [files.upload](https://api.slack.com/methods/files.upload) Slack API
66
+ - [x] Upload a file to a _public_ channel
67
+ - [x] Upload a file to a _private_ channel
68
+ - [x] Upload a file to a _slack user_ (DM)
69
+ - [x] Upload a file inside a _slack thread_ 🧵 (DM)
70
+ - [x] Upload a file with multiple channels/users
71
+
30
72
 
31
- In the following example lets send slack message to `#ios-team` channel for test-flight build.
73
+ ## Examples (Post a message)
74
+
75
+ Let’s post a message to the default slack bot channel.
76
+
77
+ ```ruby
78
+ # share on Slack
79
+ post_to_slack(message: "App successfully released!")
80
+ ```
81
+
82
+ Let’s post a direct message to a slack user that unit tests CI has been failed.
83
+
84
+ ```ruby
85
+ # share on Slack
86
+ post_to_slack(
87
+ message: "CI: Your unit tests on #{ENV['CI_COMMIT_REF_NAME']} failed",
88
+ channel: "@SlackUsername" # This can be Slack userID, instead of username i.e @UXXXXX
89
+ )
90
+ ```
91
+
92
+ Let’s post a slack message to the `#ios-team` channel about the new test-flight build.
32
93
 
33
94
  ```ruby
34
95
  lane :beta do
35
96
  gym # Build the app and create .ipa file
36
97
  pilot # Upload build to TestFlight
37
-
98
+
38
99
  version_number = get_version_number # Get project version
39
100
  build_number = get_build_number # Get build number
40
101
  beta_release_name = "#{version_number}-#{build_number}-beta-release"
41
-
102
+
42
103
  # share on Slack
43
104
  post_to_slack(
44
- api_token: "xyz", # Preferably configure as ENV['SLACK_API_TOKEN']
45
105
  message: "Hi team, we have a new test-flight beta build: #{beta_release_name}",
46
106
  channel: "#ios-team"
47
107
  )
48
108
  end
49
109
  ```
50
110
 
51
- ## Issues and Feedback
111
+ Let’s post a slack message with custom payload.
112
+
113
+ ```ruby
114
+ # share on Slack
115
+ post_to_slack(
116
+ api_token: "xyz", # Preferably configure as ENV['SLACK_API_TOKEN']
117
+ message: "App successfully released!",
118
+ channel: "#channel", # Optional, by default will post to the default channel configured for the Slack Bot.
119
+ success: true, # Optional, defaults to true.
120
+ payload: { # Optional, lets you specify any number of your own Slack attachments.
121
+ "Build Date" => Time.new.to_s,
122
+ "Built by" => "Jenkins",
123
+ },
124
+ default_payloads: [:git_branch, :git_author], # Optional, lets you specify an allowlist of default payloads to include. Pass an empty array to suppress all the default payloads.
125
+ # Don't add this key, or pass nil, if you want all the default payloads. The available default payloads are: `lane`, `test_result`, `git_branch`, `git_author`, `last_git_commit`, `last_git_commit_hash`.
126
+ attachment_properties: { # Optional, lets you specify any other properties available for attachments in the slack API (see https://api.slack.com/docs/attachments).
127
+ # This hash is deep merged with the existing properties set using the other properties above. This allows your own fields properties to be appended to the existing fields that were created using the `payload` property for instance.
128
+ thumb_url: "http://example.com/path/to/thumb.png",
129
+ fields: [{
130
+ title: "My Field",
131
+ value: "My Value",
132
+ short: true
133
+ }]
134
+ }
135
+ )
136
+ ```
137
+
138
+ Let’s post a slack message inside a slack thread 🧵
139
+
140
+ ```ruby
141
+ lane :release do
142
+ # Start the release with slack release thread
143
+ release_thread = post_to_slack(
144
+ message: "Good morning team, CI has started the AppStore release. You can find more information inside this thread 🧵",
145
+ channel: "#ios-team"
146
+ )
147
+
148
+ # Important: Save this slack thread timestamp for futher slack messages
149
+ release_thread_ts = release_thread[:json]["ts"]
150
+
151
+ gym # Build the app and create .ipa file
152
+
153
+ # Post an update in release thread
154
+ post_to_slack(
155
+ message: "App has been build successfully! 💪",
156
+ channel: "#ios-team",
157
+ thread_ts: release_thread_ts
158
+ )
159
+
160
+ deliver # Upload build to AppStore
161
+
162
+ # Post an update in release thread
163
+ post_to_slack(
164
+ message: "App has been uploaded to the AppStore and submitted for Apple's review! 🚀",
165
+ channel: "#ios-team",
166
+ thread_ts: release_thread_ts
167
+ )
168
+ end
169
+ ```
170
+
171
+ ## Examples (Upload a file)
172
+
173
+ Let’s Upload a file to a slack channel that main branch unit tests has been failed, see scan logs.
52
174
 
53
- For any other issues and feedback about this plugin, please submit it to this repository.
175
+ ```ruby
176
+ # File upload on Slack
177
+ file_upload_to_slack(
178
+ initial_comment: "CI: main-branch unit tests failed",
179
+ file_path: "scan.log",
180
+ channels: "#ios-team" # Comma-separated list of slack #channel names where the file will be shared
181
+ )
182
+ ```
54
183
 
55
- ## Troubleshooting
184
+ Let’s Upload a file to a slack user that your branch unit tests has been failed, see scan logs.
56
185
 
57
- If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
186
+ ```ruby
187
+ # File upload on Slack
188
+ file_upload_to_slack(
189
+ initial_comment: "CI: Your unit tests on #{ENV['CI_COMMIT_REF_NAME']} failed",
190
+ file_path: "scan.log",
191
+ channels: "@SlackUsername" # This can be Slack userID, instead of username i.e @UXXXXX
192
+ )
193
+ ```
58
194
 
59
- ## Using _fastlane_ Plugins
195
+ Let’s Upload a file inside a slack thread 🧵
60
196
 
61
- For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
197
+ ```ruby
198
+ lane :release do
199
+ # Start the release with slack release thread
200
+ release_thread = post_to_slack(
201
+ message: "Good morning team, CI has started the AppStore release. You can find more information inside this thread 🧵",
202
+ channel: "#ios-team"
203
+ )
204
+
205
+ # Important: Save this slack thread timestamp for futher slack messages
206
+ release_thread_ts = release_thread[:json]["ts"]
207
+
208
+ gym # Build the app and create .ipa file
209
+
210
+ # Post an update in release thread
211
+ post_to_slack(
212
+ message: "App has been build successfully! 💪",
213
+ channel: "#ios-team",
214
+ thread_ts: release_thread_ts
215
+ )
216
+
217
+ deliver # Upload build to AppStore
218
+
219
+ # Post an update in release thread
220
+ post_to_slack(
221
+ message: "App has been uploaded to the AppStore and submitted for Apple's review! 🚀",
222
+ channel: "#ios-team",
223
+ thread_ts: release_thread_ts
224
+ )
225
+
226
+ # Spaceship logs file upload on Slack
227
+ file_upload_to_slack(
228
+ initial_comment: "Deliver:: Spaceship logs",
229
+ file_path: "spaceship.log",
230
+ channels: "#ios-team",
231
+ thread_ts: release_thread_ts
232
+ )
233
+ end
234
+ ```
62
235
 
63
- ## About _fastlane_
236
+ ## About Fastlane
64
237
 
65
238
  _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,81 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/slack_bot_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ FETCH_FILES_SLACK_RESULT = :FETCH_FILES_SLACK_RESULT
8
+ end
9
+ class FetchFilesSlackAction < Action
10
+ def self.run(options)
11
+ require 'excon'
12
+ require 'json'
13
+
14
+ api_url = "https://slack.com/api/files.list"
15
+ headers = { "Content-Type": "application/json", "Authorization": "Bearer #{options[:api_token]}" }
16
+ query = { channel: options[:channel], count: options[:count], page: options[:page] }
17
+
18
+ response = Excon.get(api_url, headers: headers, query: query)
19
+ status_code = response[:status]
20
+ UI.user_error!("Response body is nil, status code: #{status_code} 💥") if response.body.nil?
21
+
22
+ result = {
23
+ status: status_code,
24
+ body: response.body,
25
+ json: JSON.parse(response.body)
26
+ }
27
+
28
+ Actions.lane_context[SharedValues::FETCH_FILES_SLACK_RESULT] = result
29
+ return result
30
+ end
31
+
32
+ def self.description
33
+ "List files of any #channel using Slack bot `files.list` api."
34
+ end
35
+
36
+ def self.available_options
37
+ [
38
+ FastlaneCore::ConfigItem.new(key: :api_token,
39
+ env_name: "FL_FETCH_FILES_SLACK_BOT_TOKEN",
40
+ description: "Slack bot Token",
41
+ sensitive: true,
42
+ code_gen_sensitive: true,
43
+ is_string: true,
44
+ default_value: ENV["SLACK_API_TOKEN"],
45
+ default_value_dynamic: true,
46
+ optional: false),
47
+ FastlaneCore::ConfigItem.new(key: :channel,
48
+ env_name: "FL_FETCH_FILES_SLACK_CHANNEL",
49
+ description: "slack #channel ID",
50
+ optional: false),
51
+ FastlaneCore::ConfigItem.new(key: :count,
52
+ env_name: "FL_FETCH_FILES_SLACK_COUNT",
53
+ description: "Number of items to return per page, default value: 100",
54
+ default_value: "100",
55
+ optional: true),
56
+ FastlaneCore::ConfigItem.new(key: :page,
57
+ env_name: "FL_FETCH_FILES_SLACK_PAGE",
58
+ description: "Page number of results to return, default value: 1",
59
+ default_value: "1",
60
+ optional: true)
61
+ ]
62
+ end
63
+
64
+ def self.authors
65
+ ["crazymanish"]
66
+ end
67
+
68
+ def self.example_code
69
+ [
70
+ 'fetch_files_slack(channel: "CHXYMXXXX")',
71
+ 'fetch_files_slack(channel: "CHXYMXXXX", count: "10")',
72
+ 'fetch_files_slack(channel: "CHXYMXXXX", count: "10", page: "2")'
73
+ ]
74
+ end
75
+
76
+ def self.is_supported?(platform)
77
+ true
78
+ end
79
+ end
80
+ end
81
+ end
@@ -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
@@ -3,37 +3,72 @@ require_relative '../helper/slack_bot_helper'
3
3
 
4
4
  module Fastlane
5
5
  module Actions
6
+ module SharedValues
7
+ POST_TO_SLACK_RESULT = :POST_TO_SLACK_RESULT
8
+ end
9
+
6
10
  class PostToSlackAction < Action
7
11
  def self.run(options)
8
12
  require 'slack-notifier'
9
13
 
10
14
  options[:message] = (options[:message].to_s || '').gsub('\n', "\n")
11
15
  options[:message] = Slack::Notifier::Util::LinkFormatter.format(options[:message])
12
-
13
16
  options[:pretext] = options[:pretext].gsub('\n', "\n") unless options[:pretext].nil?
14
17
 
15
18
  if options[:channel].to_s.length > 0
16
19
  slack_channel = options[:channel]
17
- slack_channel = ('#' + options[:channel]) unless ['#', '@'].include?(slack_channel[0]) # send message to channel by default
20
+ slack_channel = ('#' + options[:channel]) unless ['#', 'C', '@'].include?(slack_channel[0]) # Add prefix(#) by default, if needed
18
21
  end
19
22
 
20
23
  slack_attachment = SlackAction.generate_slack_attachments(options)
24
+ bot_username = options[:username]
25
+ bot_icon_url = options[:icon_url]
21
26
 
22
27
  begin
23
28
  require 'excon'
24
29
 
25
30
  api_url = "https://slack.com/api/chat.postMessage"
26
- headers = { "Content-Type": "application/json", "Authorization": "Bearer #{options[:api_token]}" }
27
- payload = { channel: slack_channel, attachments: [slack_attachment] }.to_json
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[:thread_ts] = options[:thread_ts] unless options[:thread_ts].nil?
42
+ payload = payload.to_json
28
43
 
29
- Excon.post(api_url, headers: headers, body: payload)
44
+ response = Excon.post(api_url, headers: headers, body: payload)
45
+ result = self.formatted_result(response)
30
46
  rescue => exception
31
47
  UI.error("Exception: #{exception}")
48
+ return nil
32
49
  else
33
50
  UI.success("Successfully sent Slack notification")
51
+ Actions.lane_context[SharedValues::POST_TO_SLACK_RESULT] = result
52
+ return result
34
53
  end
35
54
  end
36
55
 
56
+ def self.formatted_result(response)
57
+ result = {
58
+ status: response[:status],
59
+ body: response.body || "",
60
+ json: self.parse_json(response.body) || {}
61
+ }
62
+ end
63
+
64
+ def self.parse_json(value)
65
+ require 'json'
66
+
67
+ JSON.parse(value)
68
+ rescue JSON::ParserError
69
+ nil
70
+ end
71
+
37
72
  def self.description
38
73
  "Post a slack message"
39
74
  end
@@ -57,6 +92,18 @@ module Fastlane
57
92
  env_name: "FL_POST_TO_SLACK_CHANNEL",
58
93
  description: "#channel or @username",
59
94
  optional: true),
95
+ FastlaneCore::ConfigItem.new(key: :username,
96
+ env_name: "FL_SLACK_USERNAME",
97
+ description: "Overrides the bot's username (chat:write.customize scope required)",
98
+ default_value: "fastlane",
99
+ is_string: true,
100
+ optional: true),
101
+ FastlaneCore::ConfigItem.new(key: :icon_url,
102
+ env_name: "FL_SLACK_ICON_URL",
103
+ description: "Overrides the bot's image (chat:write.customize scope required)",
104
+ default_value: "https://fastlane.tools/assets/img/fastlane_icon.png",
105
+ is_string: true,
106
+ optional: true),
60
107
  FastlaneCore::ConfigItem.new(key: :pretext,
61
108
  env_name: "FL_POST_TO_SLACK_PRETEXT",
62
109
  description: "This is optional text that appears above the message attachment block. This supports the standard Slack markup language",
@@ -74,6 +121,7 @@ module Fastlane
74
121
  env_name: "FL_POST_TO_SLACK_DEFAULT_PAYLOADS",
75
122
  description: "Remove some of the default payloads. More information about the available payloads on GitHub",
76
123
  optional: true,
124
+ default_value: ['lane', 'test_result', 'git_branch', 'git_author', 'last_git_commit', 'last_git_commit_hash'],
77
125
  type: Array),
78
126
  FastlaneCore::ConfigItem.new(key: :attachment_properties,
79
127
  env_name: "FL_POST_TO_SLACK_ATTACHMENT_PROPERTIES",
@@ -85,7 +133,11 @@ module Fastlane
85
133
  description: "Was this successful? (true/false)",
86
134
  optional: true,
87
135
  default_value: true,
88
- is_string: false)
136
+ is_string: false),
137
+ FastlaneCore::ConfigItem.new(key: :thread_ts,
138
+ env_name: "FL_POST_TO_SLACK_THREAD_TS",
139
+ description: "Provide another message's ts value to make this message a reply",
140
+ optional: true)
89
141
  ]
90
142
  end
91
143
 
@@ -0,0 +1,149 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/slack_bot_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ UPDATE_SLACK_MESSAGE_RESULT = :UPDATE_SLACK_MESSAGE_RESULT
8
+ end
9
+ class UpdateSlackMessageAction < Action
10
+ def self.run(options)
11
+ require 'slack-notifier'
12
+
13
+ options[:message] = (options[:message].to_s || '').gsub('\n', "\n")
14
+ options[:message] = Slack::Notifier::Util::LinkFormatter.format(options[:message])
15
+ options[:pretext] = options[:pretext].gsub('\n', "\n") unless options[:pretext].nil?
16
+ slack_attachment = SlackAction.generate_slack_attachments(options)
17
+
18
+ begin
19
+ require 'excon'
20
+
21
+ api_url = "https://slack.com/api/chat.update"
22
+ headers = { "Content-Type": "application/json", "Authorization": "Bearer #{options[:api_token]}" }
23
+ payload = { channel: options[:channel], attachments: [slack_attachment], ts: options[:ts] }.to_json
24
+
25
+ response = Excon.post(api_url, headers: headers, body: payload)
26
+ result = self.formatted_result(response)
27
+ rescue => exception
28
+ UI.error("Exception: #{exception}")
29
+ return nil
30
+ else
31
+ UI.success("Successfully updated the Slack message")
32
+ Actions.lane_context[SharedValues::UPDATE_SLACK_MESSAGE_RESULT] = result
33
+ return result
34
+ end
35
+ end
36
+
37
+ def self.formatted_result(response)
38
+ result = {
39
+ status: response[:status],
40
+ body: response.body || "",
41
+ json: self.parse_json(response.body) || {}
42
+ }
43
+ end
44
+
45
+ def self.parse_json(value)
46
+ require 'json'
47
+
48
+ JSON.parse(value)
49
+ rescue JSON::ParserError
50
+ nil
51
+ end
52
+
53
+ def self.description
54
+ "Update a slack message using time-stamp(ts) value"
55
+ end
56
+
57
+ def self.available_options
58
+ [
59
+ FastlaneCore::ConfigItem.new(key: :api_token,
60
+ env_name: "FL_UPDATE_SLACK_MESSAGE_BOT_TOKEN",
61
+ description: "Slack bot Token",
62
+ sensitive: true,
63
+ code_gen_sensitive: true,
64
+ is_string: true,
65
+ default_value: ENV["SLACK_API_TOKEN"],
66
+ default_value_dynamic: true,
67
+ optional: false),
68
+ FastlaneCore::ConfigItem.new(key: :ts,
69
+ env_name: "FL_UPDATE_SLACK_MESSAGE_TS",
70
+ description: "Timestamp of the message to be updated",
71
+ optional: false),
72
+ FastlaneCore::ConfigItem.new(key: :channel,
73
+ env_name: "FL_UPDATE_SLACK_MESSAGE_CHANNEL",
74
+ description: "Slack channel i.e C1234567890",
75
+ optional: false),
76
+ FastlaneCore::ConfigItem.new(key: :pretext,
77
+ env_name: "FL_UPDATE_SLACK_MESSAGE_PRETEXT",
78
+ description: "This is optional text that appears above the message attachment block. This supports the standard Slack markup language",
79
+ optional: true),
80
+ FastlaneCore::ConfigItem.new(key: :message,
81
+ env_name: "FL_UPDATE_SLACK_MESSAGE_MESSAGE",
82
+ description: "The message that should be displayed on Slack",
83
+ optional: true),
84
+ FastlaneCore::ConfigItem.new(key: :payload,
85
+ env_name: "FL_UPDATE_SLACK_MESSAGE_PAYLOAD",
86
+ description: "Add additional information to this post. payload must be a hash containing any key with any value",
87
+ default_value: {},
88
+ is_string: false),
89
+ FastlaneCore::ConfigItem.new(key: :default_payloads,
90
+ env_name: "FL_UPDATE_SLACK_MESSAGE_DEFAULT_PAYLOADS",
91
+ description: "Remove some of the default payloads. More information about the available payloads on GitHub",
92
+ optional: true,
93
+ default_value: ['lane', 'test_result', 'git_branch', 'git_author', 'last_git_commit', 'last_git_commit_hash'],
94
+ type: Array),
95
+ FastlaneCore::ConfigItem.new(key: :attachment_properties,
96
+ env_name: "FL_UPDATE_SLACK_MESSAGE_ATTACHMENT_PROPERTIES",
97
+ description: "Merge additional properties in the slack attachment, see https://api.slack.com/docs/attachments",
98
+ default_value: {},
99
+ is_string: false),
100
+ FastlaneCore::ConfigItem.new(key: :success,
101
+ env_name: "FL_UPDATE_SLACK_MESSAGE_SUCCESS",
102
+ description: "Was this successful? (true/false)",
103
+ optional: true,
104
+ default_value: true,
105
+ is_string: false)
106
+ ]
107
+ end
108
+
109
+ def self.authors
110
+ ["crazymanish"]
111
+ end
112
+
113
+ def self.example_code
114
+ [
115
+ 'update_slack_message(
116
+ ts: "1609711037.000100",
117
+ channel: "C1234567890",
118
+ message: "Update: App successfully released!"
119
+ )',
120
+ 'update_slack_message(
121
+ ts: "1609711037.000100",
122
+ channel: "C1234567890",
123
+ message: "Update: App successfully released!",
124
+ success: true, # Optional, defaults to true.
125
+ payload: { # Optional, lets you specify any number of your own Slack attachments.
126
+ "Build Date" => Time.new.to_s,
127
+ "Built by" => "Jenkins",
128
+ },
129
+ default_payloads: [:git_branch, :git_author], # Optional, lets you specify a whitelist of default payloads to include. Pass an empty array to suppress all the default payloads.
130
+ # Don\'t add this key, or pass nil, if you want all the default payloads. The available default payloads are: `lane`, `test_result`, `git_branch`, `git_author`, `last_git_commit`, `last_git_commit_hash`.
131
+ attachment_properties: { # Optional, lets you specify any other properties available for attachments in the slack API (see https://api.slack.com/docs/attachments).
132
+ # This hash is deep merged with the existing properties set using the other properties above. This allows your own fields properties to be appended to the existing fields that were created using the `payload` property for instance.
133
+ thumb_url: "http://example.com/path/to/thumb.png",
134
+ fields: [{
135
+ title: "My Field",
136
+ value: "My Value",
137
+ short: true
138
+ }]
139
+ }
140
+ )'
141
+ ]
142
+ end
143
+
144
+ def self.is_supported?(platform)
145
+ true
146
+ end
147
+ end
148
+ end
149
+ end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module SlackBot
3
- VERSION = "0.1.1"
3
+ VERSION = "0.4.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.1.1
4
+ version: 0.4.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: 2020-05-27 00:00:00.000000000 Z
11
+ date: 2021-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -145,7 +145,10 @@ files:
145
145
  - LICENSE
146
146
  - README.md
147
147
  - lib/fastlane/plugin/slack_bot.rb
148
+ - lib/fastlane/plugin/slack_bot/actions/fetch_files_slack.rb
149
+ - lib/fastlane/plugin/slack_bot/actions/file_upload_to_slack.rb
148
150
  - lib/fastlane/plugin/slack_bot/actions/post_to_slack.rb
151
+ - lib/fastlane/plugin/slack_bot/actions/update_slack_message.rb
149
152
  - lib/fastlane/plugin/slack_bot/helper/slack_bot_helper.rb
150
153
  - lib/fastlane/plugin/slack_bot/version.rb
151
154
  homepage: https://github.com/crazymanish/fastlane-plugin-slack_bot
@@ -167,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
170
  - !ruby/object:Gem::Version
168
171
  version: '0'
169
172
  requirements: []
170
- rubygems_version: 3.0.3
173
+ rubygems_version: 3.1.4
171
174
  signing_key:
172
175
  specification_version: 4
173
176
  summary: "A fastlane plugin to post slack message using bot api token. \U0001F680"