git_trello_post_commit 0.1.1 → 0.2.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 +4 -4
- data/Gemfile +1 -0
- data/README.md +24 -5
- data/git_trello_post_commit.gemspec +1 -0
- data/lib/git_trello_post_commit/version.rb +1 -1
- data/lib/git_trello_post_commit.rb +98 -31
- data/spec/message_parser_spec.rb +72 -0
- metadata +32 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83151148c861df200b9f55ce1d2c435b06166ae8
|
4
|
+
data.tar.gz: 2a62f11e42798ed4a432a4cdbc398d554abd72c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddcdb7dadd6bc97e2b15c7de0c25835a0cd7d2f9fb87fc7ddf570733a9e0642153020c3186a3854d2cdbe45ea0338b7746833dbea3a2cb0e394c4e43f064dc07
|
7
|
+
data.tar.gz: f615d024ba608c5c4286b21067c907cdc6d03863663d33e0d504abac1dfb5b42771ac6b97b8a94d73f4052a1e532148432b74970f8a63c630d81e9fd2e15a317
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -62,15 +62,34 @@ If you omit the parameter, a link won't be added.
|
|
62
62
|
|
63
63
|
## Usage
|
64
64
|
|
65
|
-
The
|
65
|
+
The commit-message parser looks for the following keywords:
|
66
66
|
|
67
|
-
|
67
|
+
* DONE_KEYWORDS:
|
68
|
+
* close
|
69
|
+
* fix
|
70
|
+
* IN_PROGRESS_KEYWORDS:
|
71
|
+
* ref
|
72
|
+
* reference
|
73
|
+
* case
|
74
|
+
* issue
|
75
|
+
* card
|
68
76
|
|
69
|
-
|
77
|
+
For DONE_KEYWORDS, the card is moved to the list with id `LIST_ID_DONE`, while for IN_PROGRESS_KEYWORDS it is moved to the list with id `LIST_ID_IN_PROGRESS`.
|
70
78
|
|
71
|
-
|
79
|
+
After it has found a keyword, the parser then looks for space, comma or semi-colon separated lists of (hash-prefixed) ids, e.g.:
|
80
|
+
|
81
|
+
closes #1
|
82
|
+
closes #1 #2 #3
|
83
|
+
closes #1, #2, #3
|
84
|
+
closes #1, #2 and #3
|
85
|
+
closes #1, #2, and #3
|
86
|
+
closes #1, #2 & #3
|
87
|
+
closes #1, #2, & #3
|
88
|
+
|
89
|
+
So a typical commit message might be:
|
90
|
+
|
91
|
+
Added that awesome feature, refs #42 and closes #1, #2 and #3.
|
72
92
|
|
73
|
-
For the 'case' and 'card' keywords, the card is moved to the list with id `LIST_ID_IN_PROGRESS`, while for keywords 'close' and 'fix', the card is moved to the list with id `LIST_ID_DONE` .
|
74
93
|
|
75
94
|
## Contributing
|
76
95
|
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
23
24
|
|
24
25
|
spec.add_runtime_dependency 'json'
|
25
26
|
spec.add_runtime_dependency "git", "~> 1.2"
|
@@ -5,6 +5,73 @@ require "git"
|
|
5
5
|
|
6
6
|
module GitTrelloPostCommit
|
7
7
|
|
8
|
+
DONE_KEYWORDS = [:close, :fix]
|
9
|
+
IN_PROGRESS_KEYWORDS = [:ref, :case, :issue, :card]
|
10
|
+
|
11
|
+
KEYWORD_REGEX = /((ref)(?:erence)?s?|(case)s?|(issue)s?|(card)s?|(close)s?|(fix)(?:es)?)/i
|
12
|
+
ID_REGEX = /\#(?:\d+)/
|
13
|
+
ID_LIST_REGEX = /\s*((?:#{ID_REGEX}(?:[,;]?\s+(?:and|\&)|[,;])?\s*)+)/i
|
14
|
+
REF_REGEX = /#{KEYWORD_REGEX}\s+#{ID_LIST_REGEX}/
|
15
|
+
|
16
|
+
ID_CAPTURE_REGEX = /\#(\d+)/
|
17
|
+
|
18
|
+
class MessageParser
|
19
|
+
|
20
|
+
def initialize(message)
|
21
|
+
@message = message
|
22
|
+
end
|
23
|
+
|
24
|
+
def instructions
|
25
|
+
@instructions ||= parse_instructions
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_instructions
|
29
|
+
raw_matches = get_raw_matches
|
30
|
+
matches = extract_instructions(raw_matches)
|
31
|
+
normalize_matches(matches)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_raw_matches
|
35
|
+
@message.scan(REF_REGEX).map do |match|
|
36
|
+
match.compact[1..-1]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def categorize_keyword(keyword)
|
41
|
+
if DONE_KEYWORDS.include?(keyword) then :done
|
42
|
+
elsif IN_PROGRESS_KEYWORDS.include?(keyword) then :in_progress
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def extract_instructions(raw_matches)
|
47
|
+
raw_matches.reduce(Hash.new { |hash, key| hash[key] = [] }) do |matches, raw_match|
|
48
|
+
keyword = raw_match.first.downcase.to_sym
|
49
|
+
id_list = raw_match.last
|
50
|
+
if keyword and id_list
|
51
|
+
ids = id_list.scan(ID_CAPTURE_REGEX).flatten.map(&:to_i).select { |n| n>0 }
|
52
|
+
ids.each do |id|
|
53
|
+
matches[id] << keyword
|
54
|
+
end
|
55
|
+
end
|
56
|
+
matches
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def normalize_matches(matches)
|
61
|
+
matches.reduce({}) do |norm_matches, (card_id, keywords)|
|
62
|
+
keywords.uniq!
|
63
|
+
categories = keywords.map { |kw| categorize_keyword(kw) }.compact.uniq
|
64
|
+
if categories.length > 1 and categories.include?(:done)
|
65
|
+
norm_matches[card_id] = :done
|
66
|
+
elsif categories.length == 1
|
67
|
+
norm_matches[card_id] = categories.first
|
68
|
+
end
|
69
|
+
norm_matches
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
8
75
|
class Hook
|
9
76
|
|
10
77
|
def initialize(config)
|
@@ -26,41 +93,41 @@ module GitTrelloPostCommit
|
|
26
93
|
commit = @repo.gcommit('HEAD')
|
27
94
|
new_sha = commit.sha
|
28
95
|
|
29
|
-
|
30
|
-
match = commit.message.match(/((case|card|close|fix)e?s? \D?([0-9]+))/i)
|
31
|
-
return unless match and match[3].to_i > 0
|
96
|
+
parser = MessageParser.new(commit.message)
|
32
97
|
|
33
|
-
|
98
|
+
parser.instructions.each do |card_id, action|
|
34
99
|
|
35
|
-
|
36
|
-
unless results
|
37
|
-
puts "Trello: Cannot find card matching ID #{match[3]}"
|
38
|
-
return
|
39
|
-
end
|
40
|
-
results = JSON.parse(results)
|
100
|
+
puts "Trello: Commenting on card ##{card_id}"
|
41
101
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
102
|
+
results = @http.get_card(@board_id, card_id)
|
103
|
+
unless results
|
104
|
+
puts "Trello: Cannot find card matching ID #{card_id}"
|
105
|
+
next
|
106
|
+
end
|
107
|
+
results = JSON.parse(results)
|
108
|
+
|
109
|
+
# Determine the action to take
|
110
|
+
target_list_id = case action
|
111
|
+
when :in_progress then @list_id_in_progress
|
112
|
+
when :done then @list_id_done
|
113
|
+
end
|
114
|
+
|
115
|
+
# Add the commit comment
|
116
|
+
message = "#{commit.author.name}:\n#{commit.message}"
|
117
|
+
message << "\n\n#{@commit_url_prefix}#{new_sha}" unless @commit_url_prefix.nil?
|
118
|
+
message.gsub!(/\(\)$/, "")
|
119
|
+
message.gsub!(/Signed-off-by: (.*) <(.*)>/,"")
|
120
|
+
@http.add_comment(results["id"], message)
|
121
|
+
|
122
|
+
if target_list_id
|
123
|
+
to_update = {}
|
124
|
+
unless results["idList"] == target_list_id
|
125
|
+
puts "Trello: Moving card ##{card_id} to list #{target_list_id}"
|
126
|
+
to_update[:idList] = target_list_id
|
127
|
+
@http.update_card(results["id"], to_update)
|
128
|
+
end
|
63
129
|
end
|
130
|
+
|
64
131
|
end
|
65
132
|
|
66
133
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'pry'
|
3
|
+
require 'git_trello_post_commit'
|
4
|
+
|
5
|
+
module GitTrelloPostCommit
|
6
|
+
|
7
|
+
describe MessageParser do
|
8
|
+
it "parses single instructions at the end of the message" do
|
9
|
+
parser = MessageParser.new("fixed that thing, closes #99")
|
10
|
+
expect(parser.instructions).to eq({99 => :done})
|
11
|
+
end
|
12
|
+
|
13
|
+
it "parses single instructions in the middle of a message" do
|
14
|
+
parser = MessageParser.new("fixed that thing, closes #99, blah, blah, blah")
|
15
|
+
expect(parser.instructions).to eq({99 => :done})
|
16
|
+
end
|
17
|
+
|
18
|
+
it "parses multiple distinct references" do
|
19
|
+
parser = MessageParser.new("fixed that thing, closes #99, refs #100")
|
20
|
+
expect(parser.instructions).to eq({99 => :done, 100 => :in_progress})
|
21
|
+
end
|
22
|
+
|
23
|
+
it "parses a space separated list of ids for a single action keyword" do
|
24
|
+
parser = MessageParser.new("fixed that thing, closes #99 #100 #101")
|
25
|
+
expect(parser.instructions).to eq({99 => :done, 100 => :done, 101 => :done})
|
26
|
+
end
|
27
|
+
|
28
|
+
it "parses a csv list of ids for a single action keyword" do
|
29
|
+
parser = MessageParser.new("fixed that thing, closes #99, #100, #101")
|
30
|
+
expect(parser.instructions).to eq({99 => :done, 100 => :done, 101 => :done})
|
31
|
+
end
|
32
|
+
|
33
|
+
it "parses a csv list of ids (ending with an 'and') for a single action keyword" do
|
34
|
+
parser = MessageParser.new("fixed that thing, closes #99, #100 and #101")
|
35
|
+
expect(parser.instructions).to eq({99 => :done, 100 => :done, 101 => :done})
|
36
|
+
end
|
37
|
+
|
38
|
+
it "parses a csv list of ids (ending with an '&') for a single action keyword" do
|
39
|
+
parser = MessageParser.new("fixed that thing, closes #99, #100 & #101")
|
40
|
+
expect(parser.instructions).to eq({99 => :done, 100 => :done, 101 => :done})
|
41
|
+
end
|
42
|
+
|
43
|
+
it "parses a csv list of ids (ending with an ', and') for a single action keyword" do
|
44
|
+
parser = MessageParser.new("fixed that thing, closes #99, #100, and #101")
|
45
|
+
expect(parser.instructions).to eq({99 => :done, 100 => :done, 101 => :done})
|
46
|
+
end
|
47
|
+
|
48
|
+
it "parses multiple lists of ids for a single action keyword" do
|
49
|
+
parser = MessageParser.new("fixed that thing, closes #99, #100 & #101 and refs #1 & #2")
|
50
|
+
expect(parser.instructions).to eq({
|
51
|
+
99 => :done, 100 => :done, 101 => :done,
|
52
|
+
1 => :in_progress, 2 => :in_progress
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
it "ignores duplicate instructions" do
|
57
|
+
parser = MessageParser.new("fixed that thing on card #99, refs #99")
|
58
|
+
expect(parser.instructions).to eq({99 => :in_progress})
|
59
|
+
end
|
60
|
+
|
61
|
+
it "ignores duplicate instructions give in a list" do
|
62
|
+
parser = MessageParser.new("fixed the things on cards #99 and #100, refs #99, #100")
|
63
|
+
expect(parser.instructions).to eq({99 => :in_progress, 100 => :in_progress})
|
64
|
+
end
|
65
|
+
|
66
|
+
it "ignores conflicting instructions, favouring :done over :in_progress" do
|
67
|
+
parser = MessageParser.new("fixed that thing on card #99, closes #99")
|
68
|
+
expect(parser.instructions).to eq({99 => :done})
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
metadata
CHANGED
@@ -1,69 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git_trello_post_commit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jmchambers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: json
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- -
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '0'
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- -
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: git
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - ~>
|
73
|
+
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: '1.2'
|
62
76
|
type: :runtime
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - ~>
|
80
|
+
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '1.2'
|
69
83
|
description: 'This gem can be used in a post-commit hook in any Git repository to
|
@@ -76,7 +90,7 @@ executables: []
|
|
76
90
|
extensions: []
|
77
91
|
extra_rdoc_files: []
|
78
92
|
files:
|
79
|
-
- .gitignore
|
93
|
+
- ".gitignore"
|
80
94
|
- Gemfile
|
81
95
|
- LICENSE.txt
|
82
96
|
- README.md
|
@@ -85,6 +99,7 @@ files:
|
|
85
99
|
- lib/git_trello_post_commit.rb
|
86
100
|
- lib/git_trello_post_commit/trello-http.rb
|
87
101
|
- lib/git_trello_post_commit/version.rb
|
102
|
+
- spec/message_parser_spec.rb
|
88
103
|
homepage: ''
|
89
104
|
licenses:
|
90
105
|
- MIT
|
@@ -95,18 +110,20 @@ require_paths:
|
|
95
110
|
- lib
|
96
111
|
required_ruby_version: !ruby/object:Gem::Requirement
|
97
112
|
requirements:
|
98
|
-
- -
|
113
|
+
- - ">="
|
99
114
|
- !ruby/object:Gem::Version
|
100
115
|
version: '0'
|
101
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
117
|
requirements:
|
103
|
-
- -
|
118
|
+
- - ">="
|
104
119
|
- !ruby/object:Gem::Version
|
105
120
|
version: '0'
|
106
121
|
requirements: []
|
107
122
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.
|
123
|
+
rubygems_version: 2.2.2
|
109
124
|
signing_key:
|
110
125
|
specification_version: 4
|
111
126
|
summary: Update Trello cards with git commit messages.
|
112
|
-
test_files:
|
127
|
+
test_files:
|
128
|
+
- spec/message_parser_spec.rb
|
129
|
+
has_rdoc:
|