smart_todo 1.0.2 → 1.3.1
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 +27 -0
- data/.github/workflows/rubocop.yml +22 -0
- data/.rubocop.yml +3 -3
- data/Gemfile +2 -2
- data/Gemfile.lock +33 -26
- data/README.md +1 -1
- data/dev.yml +5 -1
- data/exe/smart_todo +3 -5
- data/lib/smart_todo/cli.rb +17 -11
- data/lib/smart_todo/dispatchers/base.rb +94 -0
- data/lib/smart_todo/dispatchers/output.rb +15 -0
- data/lib/smart_todo/dispatchers/slack.rb +67 -0
- data/lib/smart_todo/events/date.rb +1 -1
- data/lib/smart_todo/events/gem_bump.rb +57 -0
- data/lib/smart_todo/events/gem_release.rb +5 -5
- data/lib/smart_todo/events/issue_close.rb +7 -7
- data/lib/smart_todo/events.rb +11 -2
- data/lib/smart_todo/parser/comment_parser.rb +1 -1
- data/lib/smart_todo/parser/metadata_parser.rb +10 -7
- data/lib/smart_todo/parser/todo_node.rb +3 -3
- data/lib/smart_todo/slack_client.rb +20 -19
- data/lib/smart_todo/version.rb +1 -1
- data/lib/smart_todo.rb +15 -9
- data/lib/smart_todo_cop.rb +6 -4
- data/service.yml +1 -0
- data/smart_todo.gemspec +7 -6
- metadata +27 -23
- data/.rubocop-http---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
- data/.travis.yml +0 -15
- data/CHANGELOG.md +0 -24
- data/lib/smart_todo/dispatcher.rb +0 -99
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "ripper"
|
4
4
|
|
5
5
|
module SmartTodo
|
6
6
|
module Parser
|
@@ -35,7 +35,7 @@ module SmartTodo
|
|
35
35
|
# @param args [Array]
|
36
36
|
# @return [Array, MethodNode]
|
37
37
|
def on_method_add_arg(method, args)
|
38
|
-
if method ==
|
38
|
+
if method == "TODO"
|
39
39
|
args
|
40
40
|
else
|
41
41
|
MethodNode.new(method, args)
|
@@ -58,12 +58,12 @@ module SmartTodo
|
|
58
58
|
# @param key [String]
|
59
59
|
# @param value [String, Integer, MethodNode]
|
60
60
|
def on_assoc_new(key, value)
|
61
|
-
key.tr!(
|
61
|
+
key.tr!(":", "")
|
62
62
|
|
63
63
|
case key
|
64
|
-
when
|
64
|
+
when "on"
|
65
65
|
[:on_todo_event, value]
|
66
|
-
when
|
66
|
+
when "to"
|
67
67
|
[:on_todo_assignee, value]
|
68
68
|
else
|
69
69
|
[:unknown, value]
|
@@ -78,10 +78,11 @@ module SmartTodo
|
|
78
78
|
end
|
79
79
|
|
80
80
|
class Visitor
|
81
|
-
attr_reader :events, :
|
81
|
+
attr_reader :events, :assignees
|
82
82
|
|
83
83
|
def initialize
|
84
84
|
@events = []
|
85
|
+
@assignees = []
|
85
86
|
end
|
86
87
|
|
87
88
|
# Iterate over each tokens returned from the parser and call
|
@@ -103,13 +104,15 @@ module SmartTodo
|
|
103
104
|
# @param method_node [MethodNode]
|
104
105
|
# @return [void]
|
105
106
|
def on_todo_event(method_node)
|
107
|
+
return unless method_node.is_a?(MethodNode)
|
108
|
+
|
106
109
|
events << method_node
|
107
110
|
end
|
108
111
|
|
109
112
|
# @param assignee [String]
|
110
113
|
# @return [void]
|
111
114
|
def on_todo_assignee(assignee)
|
112
|
-
@
|
115
|
+
@assignees << assignee
|
113
116
|
end
|
114
117
|
end
|
115
118
|
end
|
@@ -11,7 +11,7 @@ module SmartTodo
|
|
11
11
|
|
12
12
|
# @param todo [String] the actual Ruby comment
|
13
13
|
def initialize(todo)
|
14
|
-
@metadata = MetadataParser.parse(todo.gsub(/^#/,
|
14
|
+
@metadata = MetadataParser.parse(todo.gsub(/^#/, ""))
|
15
15
|
@comments = []
|
16
16
|
@start = todo.match(/^#(\s+)/)[1].size
|
17
17
|
end
|
@@ -26,7 +26,7 @@ module SmartTodo
|
|
26
26
|
# @param comment [String]
|
27
27
|
# @return [void]
|
28
28
|
def <<(comment)
|
29
|
-
@comments << comment.gsub(/^#(\s+)/,
|
29
|
+
@comments << comment.gsub(/^#(\s+)/, "")
|
30
30
|
end
|
31
31
|
|
32
32
|
# Check if the +comment+ is indented two spaces below the
|
@@ -36,7 +36,7 @@ module SmartTodo
|
|
36
36
|
# @param comment [String]
|
37
37
|
# @return [true, false]
|
38
38
|
def indented_comment?(comment)
|
39
|
-
comment.match(/^#(\s
|
39
|
+
comment.match(/^#(\s*)/)[1].size - @start == DEFAULT_RUBY_INDENTATION
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "cgi"
|
4
|
+
require "net/http"
|
5
|
+
require "json"
|
5
6
|
|
6
7
|
module SmartTodo
|
7
8
|
# A simple client around the Slack API.
|
@@ -16,7 +17,7 @@ module SmartTodo
|
|
16
17
|
|
17
18
|
# @param response_body [Hash] the parsed response body from Slack
|
18
19
|
def initialize(response_body)
|
19
|
-
@error_code = response_body[
|
20
|
+
@error_code = response_body["error"]
|
20
21
|
|
21
22
|
super("Response body: #{response_body}")
|
22
23
|
end
|
@@ -25,7 +26,7 @@ module SmartTodo
|
|
25
26
|
# @param slack_token [String]
|
26
27
|
def initialize(slack_token)
|
27
28
|
@slack_token = slack_token
|
28
|
-
@client = Net::HTTP.new(
|
29
|
+
@client = Net::HTTP.new("slack.com", Net::HTTP.https_default_port).tap do |client|
|
29
30
|
client.use_ssl = true
|
30
31
|
client.read_timeout = 30
|
31
32
|
client.ssl_timeout = 15
|
@@ -37,14 +38,14 @@ module SmartTodo
|
|
37
38
|
# @param email [String]
|
38
39
|
# @return [Hash]
|
39
40
|
#
|
40
|
-
# @raise [Net::HTTPError] in case the
|
41
|
-
# @raise [SlackClient::Error] in case Slack
|
41
|
+
# @raise [Net::HTTPError] in case the request to Slack failed
|
42
|
+
# @raise [SlackClient::Error] in case Slack returns a { ok: false } in the body
|
42
43
|
#
|
43
44
|
# @see https://api.slack.com/methods/users.lookupByEmail
|
44
45
|
def lookup_user_by_email(email)
|
45
|
-
headers = {
|
46
|
+
headers = { "Content-Type" => "application/x-www-form-urlencoded" }
|
46
47
|
|
47
|
-
request(:get, "/api/users.lookupByEmail?email=#{email}", nil, headers)
|
48
|
+
request(:get, "/api/users.lookupByEmail?email=#{CGI.escape(email)}", nil, headers)
|
48
49
|
end
|
49
50
|
|
50
51
|
# Send a message to a Slack channel or to a user
|
@@ -53,12 +54,12 @@ module SmartTodo
|
|
53
54
|
# @param text [String] The message to send
|
54
55
|
# @return [Hash]
|
55
56
|
#
|
56
|
-
# @raise [Net::HTTPError] in case the
|
57
|
-
# @raise [SlackClient::Error] in case Slack
|
57
|
+
# @raise [Net::HTTPError] in case the request to Slack failed
|
58
|
+
# @raise [SlackClient::Error] in case Slack returns a { ok: false } in the body
|
58
59
|
#
|
59
60
|
# @see https://api.slack.com/methods/chat.postMessage
|
60
61
|
def post_message(channel, text)
|
61
|
-
request(:post,
|
62
|
+
request(:post, "/api/chat.postMessage", JSON.dump(channel: channel, text: text))
|
62
63
|
end
|
63
64
|
|
64
65
|
private
|
@@ -68,8 +69,8 @@ module SmartTodo
|
|
68
69
|
# @param data [String] JSON encoded data when making a POST request
|
69
70
|
# @param headers [Hash]
|
70
71
|
#
|
71
|
-
# @raise [Net::HTTPError] in case the
|
72
|
-
# @raise [SlackClient::Error] in case Slack
|
72
|
+
# @raise [Net::HTTPError] in case the request to Slack failed
|
73
|
+
# @raise [SlackClient::Error] in case Slack returns a { ok: false } in the body
|
73
74
|
def request(method, endpoint, data = nil, headers = {})
|
74
75
|
response = case method
|
75
76
|
when :post, :patch
|
@@ -87,13 +88,13 @@ module SmartTodo
|
|
87
88
|
# (Net::HTTPOK, Net::HTTPNotFound ...)
|
88
89
|
# @return [Hash]
|
89
90
|
#
|
90
|
-
# @raise [Net::HTTPError] in case the
|
91
|
-
# @raise [SlackClient::Error] in case Slack
|
91
|
+
# @raise [Net::HTTPError] in case the request to Slack failed
|
92
|
+
# @raise [SlackClient::Error] in case Slack returns a { ok: false } in the body
|
92
93
|
def slack_response!(response)
|
93
|
-
raise(Net::HTTPError.new(
|
94
|
+
raise(Net::HTTPError.new("Request to slack failed", response)) unless response.code_type < Net::HTTPSuccess
|
94
95
|
body = JSON.parse(response.body)
|
95
96
|
|
96
|
-
if body[
|
97
|
+
if body["ok"]
|
97
98
|
body
|
98
99
|
else
|
99
100
|
raise(Error, body)
|
@@ -105,8 +106,8 @@ module SmartTodo
|
|
105
106
|
# @return [Hash]
|
106
107
|
def default_headers
|
107
108
|
{
|
108
|
-
|
109
|
-
|
109
|
+
"Content-Type" => "application/json; charset=utf8",
|
110
|
+
"Authorization" => "Bearer #{@slack_token}",
|
110
111
|
}
|
111
112
|
end
|
112
113
|
end
|
data/lib/smart_todo/version.rb
CHANGED
data/lib/smart_todo.rb
CHANGED
@@ -4,19 +4,25 @@ require "smart_todo/version"
|
|
4
4
|
require "smart_todo/events"
|
5
5
|
|
6
6
|
module SmartTodo
|
7
|
-
autoload :SlackClient,
|
8
|
-
autoload :CLI,
|
9
|
-
autoload :Dispatcher, 'smart_todo/dispatcher'
|
7
|
+
autoload :SlackClient, "smart_todo/slack_client"
|
8
|
+
autoload :CLI, "smart_todo/cli"
|
10
9
|
|
11
10
|
module Parser
|
12
|
-
autoload :CommentParser,
|
13
|
-
autoload :TodoNode,
|
14
|
-
autoload :MetadataParser,
|
11
|
+
autoload :CommentParser, "smart_todo/parser/comment_parser"
|
12
|
+
autoload :TodoNode, "smart_todo/parser/todo_node"
|
13
|
+
autoload :MetadataParser, "smart_todo/parser/metadata_parser"
|
15
14
|
end
|
16
15
|
|
17
16
|
module Events
|
18
|
-
autoload :Date,
|
19
|
-
autoload :
|
20
|
-
autoload :
|
17
|
+
autoload :Date, "smart_todo/events/date"
|
18
|
+
autoload :GemBump, "smart_todo/events/gem_bump"
|
19
|
+
autoload :GemRelease, "smart_todo/events/gem_release"
|
20
|
+
autoload :IssueClose, "smart_todo/events/issue_close"
|
21
|
+
end
|
22
|
+
|
23
|
+
module Dispatchers
|
24
|
+
autoload :Base, "smart_todo/dispatchers/base"
|
25
|
+
autoload :Slack, "smart_todo/dispatchers/slack"
|
26
|
+
autoload :Output, "smart_todo/dispatchers/output"
|
21
27
|
end
|
22
28
|
end
|
data/lib/smart_todo_cop.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "smart_todo/parser/metadata_parser"
|
4
4
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
11
11
|
# @see https://rubocop.readthedocs.io/en/latest/extensions/#loading-extensions
|
12
12
|
class SmartTodoCop < Cop
|
13
13
|
MSG = "Don't write regular TODO comments. Write SmartTodo compatible syntax comments." \
|
14
|
-
|
14
|
+
"For more info please look at https://github.com/shopify/smart_todo"
|
15
15
|
|
16
16
|
# @param processed_source [RuboCop::ProcessedSource]
|
17
17
|
# @return [void]
|
@@ -27,9 +27,11 @@ module RuboCop
|
|
27
27
|
# @param comment [String]
|
28
28
|
# @return [true, false]
|
29
29
|
def smart_todo?(comment)
|
30
|
-
metadata = ::SmartTodo::Parser::MetadataParser.parse(comment.gsub(/^#/,
|
30
|
+
metadata = ::SmartTodo::Parser::MetadataParser.parse(comment.gsub(/^#/, ""))
|
31
31
|
|
32
|
-
metadata.events.any? &&
|
32
|
+
metadata.events.any? &&
|
33
|
+
metadata.events.all? { |event| event.is_a?(::SmartTodo::Parser::MethodNode) } &&
|
34
|
+
metadata.assignees.any?
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
data/service.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
classification: library
|
data/smart_todo.gemspec
CHANGED
@@ -21,18 +21,19 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.metadata["homepage_uri"] = spec.homepage
|
23
23
|
spec.metadata["source_code_uri"] = spec.homepage
|
24
|
-
spec.metadata["changelog_uri"] = spec.homepage + "/
|
24
|
+
spec.metadata["changelog_uri"] = spec.homepage + "/releases"
|
25
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
25
26
|
|
26
|
-
spec.files = Dir.chdir(File.expand_path(
|
27
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
27
28
|
%x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
28
29
|
end
|
29
30
|
spec.bindir = "exe"
|
30
|
-
spec.executables = [
|
31
|
+
spec.executables = ["smart_todo"]
|
31
32
|
spec.require_paths = ["lib"]
|
32
33
|
|
33
|
-
spec.
|
34
|
-
spec.add_development_dependency("
|
34
|
+
spec.add_runtime_dependency("rexml")
|
35
|
+
spec.add_development_dependency("bundler", ">= 1.17")
|
35
36
|
spec.add_development_dependency("minitest", "~> 5.0")
|
37
|
+
spec.add_development_dependency("rake", ">= 10.0")
|
36
38
|
spec.add_development_dependency("webmock")
|
37
|
-
spec.add_development_dependency("rubocop")
|
38
39
|
end
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_todo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rexml
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.17'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.17'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,21 +53,21 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '10.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '10.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: webmock
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -91,11 +91,10 @@ executables:
|
|
91
91
|
extensions: []
|
92
92
|
extra_rdoc_files: []
|
93
93
|
files:
|
94
|
+
- ".github/workflows/build.yml"
|
95
|
+
- ".github/workflows/rubocop.yml"
|
94
96
|
- ".gitignore"
|
95
|
-
- ".rubocop-http---shopify-github-io-ruby-style-guide-rubocop-yml"
|
96
97
|
- ".rubocop.yml"
|
97
|
-
- ".travis.yml"
|
98
|
-
- CHANGELOG.md
|
99
98
|
- CODE_OF_CONDUCT.md
|
100
99
|
- Gemfile
|
101
100
|
- Gemfile.lock
|
@@ -109,9 +108,12 @@ files:
|
|
109
108
|
- exe/smart_todo
|
110
109
|
- lib/smart_todo.rb
|
111
110
|
- lib/smart_todo/cli.rb
|
112
|
-
- lib/smart_todo/
|
111
|
+
- lib/smart_todo/dispatchers/base.rb
|
112
|
+
- lib/smart_todo/dispatchers/output.rb
|
113
|
+
- lib/smart_todo/dispatchers/slack.rb
|
113
114
|
- lib/smart_todo/events.rb
|
114
115
|
- lib/smart_todo/events/date.rb
|
116
|
+
- lib/smart_todo/events/gem_bump.rb
|
115
117
|
- lib/smart_todo/events/gem_release.rb
|
116
118
|
- lib/smart_todo/events/issue_close.rb
|
117
119
|
- lib/smart_todo/parser/comment_parser.rb
|
@@ -120,6 +122,7 @@ files:
|
|
120
122
|
- lib/smart_todo/slack_client.rb
|
121
123
|
- lib/smart_todo/version.rb
|
122
124
|
- lib/smart_todo_cop.rb
|
125
|
+
- service.yml
|
123
126
|
- shipit.rubygems.yml
|
124
127
|
- smart_todo.gemspec
|
125
128
|
homepage: https://github.com/shopify/smart_todo
|
@@ -128,7 +131,8 @@ licenses:
|
|
128
131
|
metadata:
|
129
132
|
homepage_uri: https://github.com/shopify/smart_todo
|
130
133
|
source_code_uri: https://github.com/shopify/smart_todo
|
131
|
-
changelog_uri: https://github.com/shopify/smart_todo/
|
134
|
+
changelog_uri: https://github.com/shopify/smart_todo/releases
|
135
|
+
allowed_push_host: https://rubygems.org
|
132
136
|
post_install_message:
|
133
137
|
rdoc_options: []
|
134
138
|
require_paths:
|
@@ -144,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
148
|
- !ruby/object:Gem::Version
|
145
149
|
version: '0'
|
146
150
|
requirements: []
|
147
|
-
rubygems_version: 3.
|
151
|
+
rubygems_version: 3.2.20
|
148
152
|
signing_key:
|
149
153
|
specification_version: 4
|
150
154
|
summary: Enhance todo's comments in your codebase.
|