Skip to content

Commit ed0ae68

Browse files
authored
Fix label spacing in PR titles (#275)
1 parent 035e724 commit ed0ae68

File tree

2 files changed

+183
-4
lines changed

2 files changed

+183
-4
lines changed

src/Subscriber/AutoUpdateTitleWithLabelSubscriber.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,22 @@ public function onPullRequest(GitHubEvent $event): void
7575
// Clean string from all HTML chars and remove whitespace at the beginning
7676
$prTitle = (string) preg_replace('@^[\h\s]+@u', '', html_entity_decode($prTitle));
7777

78-
// Add back labels
79-
$prTitle = trim($prPrefix.' '.trim($prTitle));
78+
// Extract any bracketed text at the beginning of the title
79+
$leadingBrackets = '';
80+
$remainingTitle = $prTitle;
81+
82+
// Match all consecutive bracketed items at the start of the title
83+
while (preg_match('/^\[([^]]+)]\s*/', $remainingTitle, $matches)) {
84+
$leadingBrackets .= '['.$matches[1].']';
85+
$remainingTitle = substr($remainingTitle, strlen($matches[0]));
86+
}
87+
88+
// Combine: valid labels + any unrecognized brackets + remaining title
89+
if ('' !== trim($remainingTitle)) {
90+
$prTitle = $prPrefix.$leadingBrackets.' '.trim($remainingTitle);
91+
} else {
92+
$prTitle = $prPrefix.$leadingBrackets;
93+
}
8094
if ($originalTitle === $prTitle) {
8195
return;
8296
}

tests/Subscriber/AutoUpdateTitleWithLabelSubscriberTest.php

Lines changed: 167 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function testOnPullRequestLabeled()
5959

6060
$this->assertCount(2, $responseData);
6161
$this->assertSame(1234, $responseData['pull_request']);
62-
$this->assertSame('[Console][FrameworkBundle] [bar] Foo', $responseData['new_title']);
62+
$this->assertSame('[Console][FrameworkBundle][bar] Foo', $responseData['new_title']);
6363
}
6464

6565
public function testOnPullRequestLabeledCaseInsensitive()
@@ -110,7 +110,7 @@ public function testRemoveLabel()
110110
$responseData = $event->getResponseData();
111111
$this->assertCount(2, $responseData);
112112
$this->assertSame(1234, $responseData['pull_request']);
113-
$this->assertSame('[Console] [Random] Foo normal title', $responseData['new_title']);
113+
$this->assertSame('[Console][Random] Foo normal title', $responseData['new_title']);
114114
}
115115

116116
public function testExtraBlankSpace()
@@ -129,4 +129,169 @@ public function testExtraBlankSpace()
129129
$this->assertSame(57753, $responseData['pull_request']);
130130
$this->assertSame('[ErrorHandler] restrict the maximum length of the X-Debug-Exception header', $responseData['new_title']);
131131
}
132+
133+
public function testMultipleLabelsWithoutSpaceBetweenBrackets()
134+
{
135+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
136+
$this->pullRequestApi->method('show')->willReturn([
137+
'title' => 'Foo Bar',
138+
'labels' => [
139+
['name' => 'Platform', 'color' => 'dddddd'],
140+
['name' => 'Agent', 'color' => 'dddddd'],
141+
],
142+
]);
143+
144+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
145+
$responseData = $event->getResponseData();
146+
$this->assertCount(2, $responseData);
147+
$this->assertSame(1234, $responseData['pull_request']);
148+
$this->assertSame('[Agent][Platform] Foo Bar', $responseData['new_title']);
149+
}
150+
151+
public function testMultipleLabelsUpdateRemovesSpaceBetweenBrackets()
152+
{
153+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
154+
$this->pullRequestApi->method('show')->willReturn([
155+
'title' => '[Platform] [Agent] Foo Bar', // Title already has labels with space
156+
'labels' => [
157+
['name' => 'Platform', 'color' => 'dddddd'],
158+
['name' => 'Agent', 'color' => 'dddddd'],
159+
],
160+
]);
161+
162+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
163+
$responseData = $event->getResponseData();
164+
$this->assertCount(2, $responseData);
165+
$this->assertSame(1234, $responseData['pull_request']);
166+
$this->assertSame('[Agent][Platform] Foo Bar', $responseData['new_title']);
167+
}
168+
169+
public function testAddingLabelToExistingLabeledTitle()
170+
{
171+
// Simulating when we already have [Platform] and are adding Agent label
172+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
173+
$this->pullRequestApi->method('show')->willReturn([
174+
'title' => '[Platform] Foo Bar', // Title already has one label
175+
'labels' => [
176+
['name' => 'Platform', 'color' => 'dddddd'],
177+
['name' => 'Agent', 'color' => 'dddddd'], // New label added
178+
],
179+
]);
180+
181+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
182+
$responseData = $event->getResponseData();
183+
$this->assertCount(2, $responseData);
184+
$this->assertSame(1234, $responseData['pull_request']);
185+
$this->assertSame('[Agent][Platform] Foo Bar', $responseData['new_title']);
186+
}
187+
188+
public function testLabelsNotRecognizedAsValidLabels()
189+
{
190+
// This test simulates what happens when [Platform] and [Agent] are in the title
191+
// but they're NOT recognized as valid labels (wrong case or not in label list)
192+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
193+
$this->pullRequestApi->method('show')->willReturn([
194+
'title' => '[Platform] [Agent] Foo Bar', // These are in title but not recognized
195+
'labels' => [
196+
['name' => 'Bug', 'color' => 'dddddd'], // Different valid label
197+
],
198+
]);
199+
200+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
201+
$responseData = $event->getResponseData();
202+
$this->assertCount(2, $responseData);
203+
$this->assertSame(1234, $responseData['pull_request']);
204+
// Since Platform and Agent are not recognized labels, they stay in the title without spaces
205+
$this->assertSame('[Bug][Platform][Agent] Foo Bar', $responseData['new_title']);
206+
}
207+
208+
public function testBugWithLabelsNotInRepositoryLabelList()
209+
{
210+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
211+
$this->pullRequestApi->method('show')->willReturn([
212+
'title' => 'Foo Bar',
213+
'labels' => [
214+
// These labels are attached to PR but not in the StaticLabelApi list
215+
['name' => 'Platform', 'color' => 'dddddd'],
216+
['name' => 'Agent', 'color' => 'dddddd'],
217+
],
218+
]);
219+
220+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
221+
$responseData = $event->getResponseData();
222+
223+
$this->assertCount(2, $responseData);
224+
$this->assertSame(1234, $responseData['pull_request']);
225+
$this->assertSame('[Agent][Platform] Foo Bar', $responseData['new_title']);
226+
}
227+
228+
/**
229+
* Test that ensures no spaces are ever added between label brackets.
230+
*/
231+
public function testNoSpacesBetweenLabelBrackets()
232+
{
233+
// Test with empty title after label removal
234+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
235+
$this->pullRequestApi->method('show')->willReturn([
236+
'title' => '[Console] [FrameworkBundle]', // Only labels, no other text
237+
'labels' => [
238+
['name' => 'Console', 'color' => 'dddddd'],
239+
['name' => 'FrameworkBundle', 'color' => 'dddddd'],
240+
],
241+
]);
242+
243+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
244+
$responseData = $event->getResponseData();
245+
246+
// Should produce labels without spaces and no trailing space
247+
$this->assertCount(2, $responseData);
248+
$this->assertSame(1234, $responseData['pull_request']);
249+
$this->assertSame('[Console][FrameworkBundle]', $responseData['new_title']);
250+
}
251+
252+
/**
253+
* Test when title has unrecognized bracketed text like [Foo] that isn't a label.
254+
*/
255+
public function testUnrecognizedBracketedTextWithNewLabel()
256+
{
257+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
258+
$this->pullRequestApi->method('show')->willReturn([
259+
'title' => '[Foo] Bar', // [Foo] is not a recognized label
260+
'labels' => [
261+
['name' => 'Console', 'color' => 'dddddd'], // Adding Console label
262+
],
263+
]);
264+
265+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
266+
$responseData = $event->getResponseData();
267+
268+
// Currently produces: [Console] [Foo] Bar (with space)
269+
// Should produce: [Console][Foo] Bar (no space between brackets)
270+
$this->assertCount(2, $responseData);
271+
$this->assertSame(1234, $responseData['pull_request']);
272+
$this->assertSame('[Console][Foo] Bar', $responseData['new_title']);
273+
}
274+
275+
/**
276+
* Test multiple unrecognized bracketed texts with real labels.
277+
*/
278+
public function testMultipleUnrecognizedBracketsWithRealLabels()
279+
{
280+
$event = new GitHubEvent(['action' => 'labeled', 'number' => 1234, 'pull_request' => []], $this->repository);
281+
$this->pullRequestApi->method('show')->willReturn([
282+
'title' => '[TODO] [WIP] [Foo] Some title', // [TODO], [WIP], [Foo] are not recognized labels
283+
'labels' => [
284+
['name' => 'Console', 'color' => 'dddddd'],
285+
['name' => 'FrameworkBundle', 'color' => 'dddddd'],
286+
],
287+
]);
288+
289+
$this->dispatcher->dispatch($event, GitHubEvents::PULL_REQUEST);
290+
$responseData = $event->getResponseData();
291+
292+
// Should keep unrecognized brackets but without spaces between any brackets
293+
$this->assertCount(2, $responseData);
294+
$this->assertSame(1234, $responseData['pull_request']);
295+
$this->assertSame('[Console][FrameworkBundle][TODO][WIP][Foo] Some title', $responseData['new_title']);
296+
}
132297
}

0 commit comments

Comments
 (0)