smart_todo 1.9.1 → 1.9.2
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 +4 -4
- data/.github/workflows/build.yml +1 -1
- data/.github/workflows/rubocop.yml +1 -1
- data/Gemfile.lock +26 -23
- data/lib/smart_todo/dispatchers/slack.rb +23 -8
- data/lib/smart_todo/slack_client.rb +12 -9
- data/lib/smart_todo/version.rb +1 -1
- data/lib/smart_todo_cop.rb +8 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: beb68e6ca2807c8c2fb782fb34109d5abe45f3e306cab7ad2f34b211f6a250aa
|
4
|
+
data.tar.gz: cc9978ba39c42bf194de59836c945197d066537187e34285857758bfcaf63ed5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 580080fabbbcc83ad8f372e56b5d4c2238688fc4617edd1501ac3032ddd61497db9e9c2a648f7a7b32acdda27790fa63fe0eb5c5c08d8b97c2e72116f2868f92
|
7
|
+
data.tar.gz: 6593132b64a848caa0205518b8c2124d04e6099b225af92e18ff997b5d204c1518c70c556280b766f3d6ea639bf9d4b44460152230f37baeda08f49f707bc889
|
data/.github/workflows/build.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
smart_todo (1.9.
|
4
|
+
smart_todo (1.9.2)
|
5
5
|
prism (~> 1.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -9,44 +9,47 @@ GEM
|
|
9
9
|
specs:
|
10
10
|
addressable (2.8.7)
|
11
11
|
public_suffix (>= 2.0.2, < 7.0)
|
12
|
-
ast (2.4.
|
12
|
+
ast (2.4.3)
|
13
13
|
bigdecimal (3.1.9)
|
14
14
|
crack (1.0.0)
|
15
15
|
bigdecimal
|
16
16
|
rexml
|
17
17
|
hashdiff (1.1.2)
|
18
|
-
json (2.
|
19
|
-
language_server-protocol (3.17.0.
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
json (2.10.2)
|
19
|
+
language_server-protocol (3.17.0.4)
|
20
|
+
lint_roller (1.1.0)
|
21
|
+
minitest (5.25.5)
|
22
|
+
parallel (1.26.3)
|
23
|
+
parser (3.3.7.3)
|
23
24
|
ast (~> 2.4.1)
|
24
25
|
racc
|
25
|
-
prism (1.
|
26
|
+
prism (1.4.0)
|
26
27
|
public_suffix (6.0.1)
|
27
|
-
racc (1.
|
28
|
+
racc (1.8.1)
|
28
29
|
rainbow (3.1.1)
|
29
|
-
rake (13.
|
30
|
-
regexp_parser (2.
|
31
|
-
rexml (3.4.
|
32
|
-
rubocop (1.
|
30
|
+
rake (13.2.1)
|
31
|
+
regexp_parser (2.10.0)
|
32
|
+
rexml (3.4.1)
|
33
|
+
rubocop (1.74.0)
|
33
34
|
json (~> 2.3)
|
34
|
-
language_server-protocol (
|
35
|
+
language_server-protocol (~> 3.17.0.2)
|
36
|
+
lint_roller (~> 1.1.0)
|
35
37
|
parallel (~> 1.10)
|
36
38
|
parser (>= 3.3.0.2)
|
37
39
|
rainbow (>= 2.2.2, < 4.0)
|
38
|
-
regexp_parser (>=
|
39
|
-
|
40
|
-
rubocop-ast (>= 1.31.1, < 2.0)
|
40
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
41
|
+
rubocop-ast (>= 1.38.0, < 2.0)
|
41
42
|
ruby-progressbar (~> 1.7)
|
42
|
-
unicode-display_width (>= 2.4.0, <
|
43
|
-
rubocop-ast (1.
|
44
|
-
parser (>= 3.3.
|
45
|
-
rubocop-shopify (2.
|
43
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
44
|
+
rubocop-ast (1.42.0)
|
45
|
+
parser (>= 3.3.7.2)
|
46
|
+
rubocop-shopify (2.15.1)
|
46
47
|
rubocop (~> 1.51)
|
47
48
|
ruby-progressbar (1.13.0)
|
48
|
-
unicode-display_width (
|
49
|
-
|
49
|
+
unicode-display_width (3.1.4)
|
50
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
51
|
+
unicode-emoji (4.0.4)
|
52
|
+
webmock (3.25.1)
|
50
53
|
addressable (>= 2.8.0)
|
51
54
|
crack (>= 0.3.2)
|
52
55
|
hashdiff (>= 0.4.0, < 2.0.0)
|
@@ -35,15 +35,17 @@ module SmartTodo
|
|
35
35
|
def dispatch_one(assignee)
|
36
36
|
user = slack_user_or_channel(assignee)
|
37
37
|
|
38
|
-
|
39
|
-
rescue SlackClient::Error => error
|
40
|
-
if ["users_not_found", "channel_not_found", "is_archived"].include?(error.error_code)
|
41
|
-
user = { "user" => { "id" => @options[:fallback_channel] }, "fallback" => true }
|
42
|
-
else
|
43
|
-
raise(error)
|
44
|
-
end
|
38
|
+
return unless user
|
45
39
|
|
46
|
-
|
40
|
+
begin
|
41
|
+
client.post_message(user.dig("user", "id"), slack_message(user, assignee))
|
42
|
+
rescue SlackClient::Error => error
|
43
|
+
user = handle_slack_error(error, "Error dispatching message")
|
44
|
+
retry
|
45
|
+
rescue Net::HTTPError => error
|
46
|
+
$stderr.puts "Error dispatching message: #{error.message}"
|
47
|
+
$stderr.puts "Response: #{error.response.body}"
|
48
|
+
end
|
47
49
|
end
|
48
50
|
|
49
51
|
private
|
@@ -58,12 +60,25 @@ module SmartTodo
|
|
58
60
|
else
|
59
61
|
{ "user" => { "id" => assignee } }
|
60
62
|
end
|
63
|
+
rescue SlackClient::Error => error
|
64
|
+
handle_slack_error(error, "Error finding user or channel")
|
65
|
+
rescue Net::HTTPError => error
|
66
|
+
$stderr.puts "Error finding user or channel: #{error.message}"
|
67
|
+
$stderr.puts "Response: #{error.response.body}"
|
61
68
|
end
|
62
69
|
|
63
70
|
# @return [SlackClient] an instance of SlackClient
|
64
71
|
def client
|
65
72
|
@client ||= SlackClient.new(@options[:slack_token])
|
66
73
|
end
|
74
|
+
|
75
|
+
def handle_slack_error(error, message)
|
76
|
+
if ["users_not_found", "channel_not_found", "is_archived"].include?(error.error_code)
|
77
|
+
{ "user" => { "id" => @options[:fallback_channel] }, "fallback" => true }
|
78
|
+
else
|
79
|
+
$stderr.puts "#{message}: #{error.message}"
|
80
|
+
end
|
81
|
+
end
|
67
82
|
end
|
68
83
|
end
|
69
84
|
end
|
@@ -32,16 +32,17 @@ module SmartTodo
|
|
32
32
|
# Retrieve the Slack ID of a user from his email
|
33
33
|
#
|
34
34
|
# @param email [String]
|
35
|
+
# @param min_sleep [Integer] - the minimum sleep time in seconds in case of rate limiting
|
35
36
|
# @return [Hash]
|
36
37
|
#
|
37
38
|
# @raise [Net::HTTPError] in case the request to Slack failed
|
38
39
|
# @raise [SlackClient::Error] in case Slack returns a { ok: false } in the body
|
39
40
|
#
|
40
41
|
# @see https://api.slack.com/methods/users.lookupByEmail
|
41
|
-
def lookup_user_by_email(email)
|
42
|
+
def lookup_user_by_email(email, min_sleep = 30)
|
42
43
|
headers = default_headers.merge("Content-Type" => "application/x-www-form-urlencoded")
|
43
44
|
request = Net::HTTP::Get.new("/api/users.lookupByEmail?email=#{CGI.escape(email)}", headers)
|
44
|
-
dispatch(request)
|
45
|
+
dispatch(request, 5, min_sleep)
|
45
46
|
end
|
46
47
|
|
47
48
|
# Send a message to a Slack channel or to a user
|
@@ -63,25 +64,27 @@ module SmartTodo
|
|
63
64
|
|
64
65
|
private
|
65
66
|
|
66
|
-
# @param
|
67
|
-
# @param
|
68
|
-
# @param
|
69
|
-
# @param headers [Hash]
|
67
|
+
# @param request [Net::HTTPRequest]
|
68
|
+
# @param max_attempts [Integer] - the maximum number of attempts to make
|
69
|
+
# @param min_sleep [Integer] - the minimum sleep time in seconds in case of rate limiting
|
70
70
|
#
|
71
71
|
# @raise [Net::HTTPError] in case the request to Slack failed
|
72
72
|
# @raise [SlackClient::Error] in case Slack returns a { ok: false } in the body
|
73
|
-
def dispatch(request, max_attempts = 5)
|
73
|
+
def dispatch(request, max_attempts = 5, min_sleep = 30)
|
74
74
|
response = @client.request(request)
|
75
75
|
attempts = 1
|
76
76
|
|
77
77
|
while response.is_a?(Net::HTTPTooManyRequests) && attempts < max_attempts
|
78
|
-
|
78
|
+
sleep_time = Integer(response["Retry-After"]).clamp(min_sleep, 120)
|
79
|
+
puts "Rate limited, sleeping for #{sleep_time} seconds"
|
80
|
+
sleep(sleep_time)
|
79
81
|
response = @client.request(request)
|
80
82
|
attempts += 1
|
81
83
|
end
|
82
84
|
|
83
85
|
unless response.code_type < Net::HTTPSuccess
|
84
|
-
|
86
|
+
message = "Request to slack failed #{response.body}, code #{response.code}, attempt #{attempts}"
|
87
|
+
raise(Net::HTTPError.new(message, response))
|
85
88
|
end
|
86
89
|
|
87
90
|
body = JSON.parse(response.body)
|
data/lib/smart_todo/version.rb
CHANGED
data/lib/smart_todo_cop.rb
CHANGED
@@ -27,6 +27,8 @@ module RuboCop
|
|
27
27
|
add_offense(comment)
|
28
28
|
elsif (methods = invalid_event_methods(metadata.events)).any?
|
29
29
|
add_offense(comment, message: "Invalid event method(s): #{methods.join(", ")}. #{HELP}")
|
30
|
+
elsif invalid_assignees(metadata.assignees).any?
|
31
|
+
add_offense(comment, message: "Invalid event assignee. This method only accepts strings. #{HELP}")
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
@@ -52,6 +54,12 @@ module RuboCop
|
|
52
54
|
def invalid_event_methods(events)
|
53
55
|
events.map(&:method_name).reject { |method| ::SmartTodo::Events.method_defined?(method) }
|
54
56
|
end
|
57
|
+
|
58
|
+
# @param assignees [Array]
|
59
|
+
# @return [Array]
|
60
|
+
def invalid_assignees(assignees)
|
61
|
+
assignees.reject { |assignee| assignee.is_a?(String) }
|
62
|
+
end
|
55
63
|
end
|
56
64
|
end
|
57
65
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_todo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-03-31 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: prism
|
@@ -147,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
147
|
- !ruby/object:Gem::Version
|
148
148
|
version: '0'
|
149
149
|
requirements: []
|
150
|
-
rubygems_version: 3.6.
|
150
|
+
rubygems_version: 3.6.6
|
151
151
|
specification_version: 4
|
152
152
|
summary: Enhance todo's comments in your codebase.
|
153
153
|
test_files: []
|