Skip to content

Commit 182080b

Browse files
committed
Merge pull request #3 from webmozart/fix-edge-cases
Made status matching stricter to reject false matches
2 parents 712f669 + 39a7bf9 commit 182080b

File tree

3 files changed

+66
-55
lines changed

3 files changed

+66
-55
lines changed

src/AppBundle/GitHub/StatusManager.php

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ class StatusManager
1010
const STATUS_REVIEWED = 'reviewed';
1111

1212
private static $triggerWords = [
13-
self::STATUS_NEEDS_REVIEW => 'needs review',
14-
self::STATUS_NEEDS_WORK => 'needs work',
15-
self::STATUS_WORKS_FOR_ME => 'works for me',
16-
self::STATUS_REVIEWED => 'reviewed',
13+
'needs review' => self::STATUS_NEEDS_REVIEW,
14+
'needs work' => self::STATUS_NEEDS_WORK,
15+
'works for me' => self::STATUS_WORKS_FOR_ME,
16+
'reviewed' => self::STATUS_REVIEWED,
1717
];
1818

1919
private static $labels = [
@@ -35,19 +35,19 @@ class StatusManager
3535
*/
3636
public function getStatusChangeFromComment($comment)
3737
{
38-
// 1) Find the last "status:"
39-
$statusPosition = $this->findStatusPosition($comment);
38+
$triggerWord = implode('|', array_keys(self::$triggerWords));
39+
$formatting = '[\\s\\*]*';
4040

41-
if ($statusPosition === false) {
42-
return null;
43-
}
41+
// Match first character after "status:"
42+
// Case insensitive ("i"), ignores formatting with "*" before or after the ":"
43+
$pattern = "~(?=\n|^)${formatting}status${formatting}:${formatting}[\"']?($triggerWord)[\"']?${formatting}[.!]?${formatting}(?<=\r\n|\n|$)~i";
4444

45-
foreach (self::$triggerWords as $status => $triggerWord) {
46-
// status should be right at the beginning of the string
47-
if ($triggerWord === strtolower(substr($comment, $statusPosition, strlen($triggerWord)))) {
48-
return $status;
49-
}
45+
if (preg_match_all($pattern, $comment, $matches)) {
46+
// Second subpattern = first status character
47+
return self::$triggerWords[strtolower(end($matches[1]))];
5048
}
49+
50+
return null;
5151
}
5252

5353
/**
@@ -72,36 +72,4 @@ public static function getLabelToStatusMap()
7272
{
7373
return array_flip(self::$labels);
7474
}
75-
76-
/**
77-
* Finds the position where the status string will start - e.g.
78-
* for "Status: Needs review", this would return the position
79-
* that points to the "N" in "Needs".
80-
*
81-
* If there are multiple "Status:" in the string, this returns the
82-
* final one.
83-
*
84-
* This takes into account possible formatting (e.g. **Status**: )
85-
*
86-
* Returns the position or false if none was found.
87-
*
88-
* @param string $comment
89-
* @return boolean|integer
90-
*/
91-
private function findStatusPosition($comment)
92-
{
93-
// Match first character after "status:"
94-
// Case insensitive ("i"), ignores formatting with "*" before or after the ":"
95-
$pattern = '~status(\*+:\s*|:[\s\*]*)(\w)~i';
96-
97-
if (preg_match_all($pattern, $comment, $matches, PREG_OFFSET_CAPTURE)) {
98-
// Second subpattern = first status character
99-
$lastMatch = end($matches[2]);
100-
101-
// [matched string, offset]
102-
return $lastMatch[1];
103-
}
104-
105-
return false;
106-
}
10775
}

src/AppBundle/Tests/GitHub/StatusManagerTest.php

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,30 +37,55 @@ public function getCommentsForStatusChange()
3737
'Status: needs work',
3838
StatusManager::STATUS_NEEDS_WORK
3939
);
40+
$tests[] = array(
41+
'Status: reviewed',
42+
StatusManager::STATUS_REVIEWED
43+
);
44+
45+
// accept quotes
46+
$tests[] = array(
47+
'Status: "reviewed"',
48+
StatusManager::STATUS_REVIEWED
49+
);
50+
$tests[] = array(
51+
"Status: 'reviewed'",
52+
StatusManager::STATUS_REVIEWED
53+
);
54+
55+
// accept trailing punctuation
4056
$tests[] = array(
4157
'Status: works for me!',
4258
StatusManager::STATUS_WORKS_FOR_ME
4359
);
4460
$tests[] = array(
45-
'Status: reviewed',
46-
StatusManager::STATUS_REVIEWED
61+
'Status: works for me.',
62+
StatusManager::STATUS_WORKS_FOR_ME
4763
);
4864

4965
// play with different formatting
5066
$tests[] = array(
5167
'STATUS: REVIEWED',
5268
StatusManager::STATUS_REVIEWED
5369
);
54-
5570
$tests[] = array(
5671
'**Status**: reviewed',
5772
StatusManager::STATUS_REVIEWED
5873
);
59-
60-
// missing the colon - so we do NOT read this
6174
$tests[] = array(
62-
'Status reviewed',
63-
null,
75+
'**Status:** reviewed',
76+
StatusManager::STATUS_REVIEWED
77+
);
78+
$tests[] = array(
79+
'**Status: reviewed**',
80+
StatusManager::STATUS_REVIEWED
81+
);
82+
$tests[] = array(
83+
'**Status: reviewed!**',
84+
StatusManager::STATUS_REVIEWED
85+
);
86+
$tests[] = array(
87+
'**Status: reviewed**.',
88+
StatusManager::STATUS_REVIEWED
6489
);
6590
$tests[] = array(
6691
'Status:reviewed',
@@ -71,9 +96,15 @@ public function getCommentsForStatusChange()
7196
StatusManager::STATUS_REVIEWED
7297
);
7398

99+
// reject missing colon
100+
$tests[] = array(
101+
'Status reviewed',
102+
null,
103+
);
104+
74105
// multiple matches - use the last one
75106
$tests[] = array(
76-
"Status: needs review \r\n that is what the issue *was* marked as. Now it should be Status: reviewed",
107+
"Status: needs review \r\n that is what the issue *was* marked as.\r\n Status: reviewed",
77108
StatusManager::STATUS_REVIEWED
78109
);
79110
// "needs review" does not come directly after status: , so there is no status change
@@ -82,6 +113,18 @@ public function getCommentsForStatusChange()
82113
null
83114
);
84115

116+
// reject if the status is not on a line of its own
117+
// use case: someone posts instructions about how to change a status
118+
// in a comment
119+
$tests[] = array(
120+
'You should include e.g. the line `Status: needs review` in your comment',
121+
null
122+
);
123+
$tests[] = array(
124+
'Before the ticket was in state "Status: reviewed", but then the status was changed',
125+
null
126+
);
127+
85128
return $tests;
86129
}
87130
}

src/AppBundle/Tests/webhook_examples/issue_comment.created.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
},
6868
"created_at":"2015-06-28T12:44:21Z",
6969
"updated_at":"2015-06-28T12:44:21Z",
70-
"body":"I'm commenting! Status: Needs Review."
70+
"body":"I'm commenting!\nStatus: Needs Review."
7171
},
7272
"repository":{
7373
"id":21151556,

0 commit comments

Comments
 (0)