Skip to content

Commit cd8cc8b

Browse files
authored
[Feature] Add YouTrack issue link rule
* Add HasLinkToYouTrackIssueRule * Add source_branch and target_branch * OnTargetBranchRule * add output example * Update readme.md * update changelog
1 parent dab640a commit cd8cc8b

13 files changed

+197
-8
lines changed

CHANGELOG.MD

+7
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@ v0.1.0
99
v0.1.1
1010
--------------------
1111
* [Feature] Add rule "Has link to Jira task"
12+
13+
v0.1.2
14+
--------------------
15+
* [Feature] Add rule "Has link to YouTrack issue"
16+
* [Feature] Add rule "OnTargetBranchRule"
17+
* Add property "sourceBranch" to MergeRequest object
18+
* Add property "targetBranch" to MergeRequest object

README.MD

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
![PHP Composer](https://github.com/ArtARTs36/php-merge-request-linter/workflows/PHP%20Composer/badge.svg?branch=master)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5-
<a href="https://poser.pugx.org/artarts36/merge-request-linter/d/total.svg">
6-
<img src="https://poser.pugx.org/artarts36/merge-request-linter/d/total.svg" alt="Total Downloads">
7-
</a>
5+
![Latest Version](https://img.shields.io/packagist/v/artarts36/merge-request-linter)
6+
![Total Downloads](https://poser.pugx.org/artarts36/merge-request-linter/d/total.svg)
87

98
This package provides tools for validating merge requests
109

@@ -71,3 +70,7 @@ Add new script into your composer.json (section **scripts**):
7170
| composer lint | Run lint (via PHPCsFixer) |
7271
| composer doc-rules | Build rules doc page |
7372
| composer build | Build PHAR of source |
73+
74+
## Console output example
75+
76+
![Example](docs/output_example.png)

docs/output_example.png

111 KB
Loading

docs/rules.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ Currently is available that rules:
1212
| 5 | ArtARTs36\MergeRequestLinter\Rule\HasAnyLabelsOfRule | Merge Request must have any {labels}. |
1313
| 6 | ArtARTs36\MergeRequestLinter\Rule\HasAnyLabelsRule | Merge Request must have any labels. |
1414
| 7 | ArtARTs36\MergeRequestLinter\Rule\HasLinkToJiraTaskRule | The description must have a link to Jira on a {domain} with {projectCode}. |
15-
| 8 | ArtARTs36\MergeRequestLinter\Rule\TitleMatchesExpressionRule | The title must match the expression: {regex} |
16-
| 9 | ArtARTs36\MergeRequestLinter\Rule\TitleStartsWithAnyPrefixRule | The title must starts with any {prefixes} |
17-
| 10 | ArtARTs36\MergeRequestLinter\Rule\WhenHasLabelMustDescriptionContainsLinkOfAnyDomainsRule | When has label must description contains link of any {domains}. |
18-
| 11 | ArtARTs36\MergeRequestLinter\Rule\WhenHasLabelMustTitleStartsWithRule | When has label must title starts with {prefix}. |
15+
| 8 | ArtARTs36\MergeRequestLinter\Rule\HasLinkToYouTrackIssueRule | The description must have a link to YouTrack issue on a {domain} with {projectCode}. |
16+
| 9 | ArtARTs36\MergeRequestLinter\Rule\OnTargetBranchRule | Apply another rule if the target branch equals {targetBranch}. |
17+
| 10 | ArtARTs36\MergeRequestLinter\Rule\TitleMatchesExpressionRule | The title must match the expression: {regex} |
18+
| 11 | ArtARTs36\MergeRequestLinter\Rule\TitleStartsWithAnyPrefixRule | The title must starts with any {prefixes} |
19+
| 12 | ArtARTs36\MergeRequestLinter\Rule\WhenHasLabelMustDescriptionContainsLinkOfAnyDomainsRule | When has label must description contains link of any {domains}. |
20+
| 13 | ArtARTs36\MergeRequestLinter\Rule\WhenHasLabelMustTitleStartsWithRule | When has label must title starts with {prefix}. |

src/Ci/System/Schema/GithubPullRequestSchema.php

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public function createMergeRequest(array $pullRequest): MergeRequest
1818
'description' => $pullRequest['bodyText'],
1919
'labels' => array_map(fn (array $item) => $item['name'], $pullRequest['labels']['nodes']),
2020
'has_conflicts' => $pullRequest['mergeable'] !== self::MERGEABLE_STATE_CONFLICTING,
21+
'source_branch' => $pullRequest['headRefName'],
22+
'target_branch' => $pullRequest['baseRefName'],
2123
]);
2224
}
2325

@@ -29,6 +31,8 @@ public function createGraphqlForPullRequest(string $owner, string $repo, int $re
2931
title
3032
bodyText
3133
mergeable
34+
baseRefName
35+
headRefName
3236
labels(first: 100) {
3337
totalCount
3438
nodes {

src/Request/MergeRequest.php

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class MergeRequest
1313
'description' => 'string',
1414
'labels' => 'array',
1515
'has_conflicts' => 'bool',
16+
'source_branch' => 'string',
17+
'target_branch' => 'string',
1618
];
1719

1820
/**
@@ -23,6 +25,8 @@ public function __construct(
2325
public Str $description,
2426
public Map $labels,
2527
public bool $hasConflicts,
28+
public Str $sourceBranch,
29+
public Str $targetBranch,
2630
) {
2731
//
2832
}
@@ -45,6 +49,8 @@ public static function fromArray(
4549
Str::make($request['description']),
4650
Map::fromList($request['labels']),
4751
(bool) $request['has_conflicts'],
52+
Str::make($request['source_branch']),
53+
Str::make($request['target_branch']),
4854
);
4955
}
5056
}

src/Rule/HasLinkToJiraTaskRule.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class HasLinkToJiraTaskRule extends SimpleRule
1111
{
1212
public function __construct(protected string $domain, protected string $projectCode)
1313
{
14-
parent::__construct('The Description must have a link to jira on '. $this->domain);
14+
parent::__construct('The description must have a link to Jira on '. $this->domain);
1515
}
1616

1717
protected function doLint(MergeRequest $request): bool|array|null
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace ArtARTs36\MergeRequestLinter\Rule;
4+
5+
use ArtARTs36\MergeRequestLinter\Request\MergeRequest;
6+
7+
/**
8+
* The description must have a link to YouTrack issue on a {domain} with {projectCode}.
9+
*/
10+
class HasLinkToYouTrackIssueRule extends SimpleRule
11+
{
12+
public function __construct(protected string $domain, protected string $projectCode)
13+
{
14+
parent::__construct('The description must have a link to YouTrack on ' . $this->domain);
15+
}
16+
17+
protected function doLint(MergeRequest $request): bool|array|null
18+
{
19+
$domain = str_replace(['.'], ['\.'], $this->domain);
20+
21+
return $request->description->match("#$domain\/issue/$this->projectCode-\d#")->isNotEmpty();
22+
}
23+
}

src/Rule/OnTargetBranchRule.php

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace ArtARTs36\MergeRequestLinter\Rule;
4+
5+
use ArtARTs36\MergeRequestLinter\Contracts\Rule;
6+
use ArtARTs36\MergeRequestLinter\Contracts\RuleDefinition;
7+
use ArtARTs36\MergeRequestLinter\Request\MergeRequest;
8+
9+
/**
10+
* Apply another rule if the target branch equals {targetBranch}.
11+
*/
12+
class OnTargetBranchRule implements Rule
13+
{
14+
public function __construct(protected string $targetBranch, protected Rule $decorateRule)
15+
{
16+
//
17+
}
18+
19+
public function lint(MergeRequest $request): array
20+
{
21+
return $request->targetBranch->equals($this->targetBranch) ?
22+
$this->decorateRule->lint($request) :
23+
[];
24+
}
25+
26+
public function getDefinition(): RuleDefinition
27+
{
28+
return new Definition('Apply another rule if the target branch equals: ' . $this->targetBranch);
29+
}
30+
}

tests/Mocks/FailRule.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace ArtARTs36\MergeRequestLinter\Tests\Mocks;
4+
5+
use ArtARTs36\MergeRequestLinter\Contracts\Rule;
6+
use ArtARTs36\MergeRequestLinter\Contracts\RuleDefinition;
7+
use ArtARTs36\MergeRequestLinter\Request\MergeRequest;
8+
use ArtARTs36\MergeRequestLinter\Rule\Definition;
9+
10+
final class FailRule implements Rule
11+
{
12+
public function lint(MergeRequest $request): array
13+
{
14+
return [new EmptyNote()];
15+
}
16+
17+
public function getDefinition(): RuleDefinition
18+
{
19+
return new Definition('');
20+
}
21+
}

tests/TestCase.php

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ protected function makeMergeRequest(array $data = []): MergeRequest
1717
'description' => $data['description'] ?? '',
1818
'labels' => $data['labels'] ?? [],
1919
'has_conflicts' => false,
20+
'source_branch' => $data['source_branch'] ?? '',
21+
'target_branch' => $data['target_branch'] ?? '',
2022
]);
2123
}
2224

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace ArtARTs36\MergeRequestLinter\Tests\Unit\Rule;
4+
5+
use ArtARTs36\MergeRequestLinter\Request\MergeRequest;
6+
use ArtARTs36\MergeRequestLinter\Rule\HasLinkToYouTrackIssueRule;
7+
use ArtARTs36\MergeRequestLinter\Tests\TestCase;
8+
9+
final class HasLinkToYouTrackIssueRuleTest extends TestCase
10+
{
11+
public function providerForTestLint(): array
12+
{
13+
return [
14+
[
15+
$this->makeMergeRequest(),
16+
['yt.my-company.ru', 'MY-PROJECT'],
17+
true,
18+
],
19+
[
20+
$this->makeMergeRequest([
21+
'description' => 'solve yt.my-company.ru/issue/MY-PROJECT-1',
22+
]),
23+
['yt.my-company.ru', 'MY-PROJECT'],
24+
false,
25+
],
26+
];
27+
}
28+
29+
/**
30+
* @dataProvider providerForTestLint
31+
* @covers \ArtARTs36\MergeRequestLinter\Rule\HasLinkToYoutrackIssueRule::lint
32+
*/
33+
public function testLint(MergeRequest $request, array $ruleParams, bool $hasNotes): void
34+
{
35+
self::assertHasNotes($request, new HasLinkToYouTrackIssueRule(...$ruleParams), $hasNotes);
36+
}
37+
}
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace ArtARTs36\MergeRequestLinter\Tests\Unit\Rule;
4+
5+
use ArtARTs36\MergeRequestLinter\Contracts\Rule;
6+
use ArtARTs36\MergeRequestLinter\Request\MergeRequest;
7+
use ArtARTs36\MergeRequestLinter\Rule\OnTargetBranchRule;
8+
use ArtARTs36\MergeRequestLinter\Tests\Mocks\FailRule;
9+
use ArtARTs36\MergeRequestLinter\Tests\Mocks\SuccessRule;
10+
use ArtARTs36\MergeRequestLinter\Tests\TestCase;
11+
12+
final class OnTargetBranchRuleTest extends TestCase
13+
{
14+
public function providerForTestLint(): array
15+
{
16+
return [
17+
[
18+
$this->makeMergeRequest(),
19+
'dev',
20+
new SuccessRule(),
21+
false,
22+
],
23+
[
24+
$this->makeMergeRequest([
25+
'target_branch' => 'dev',
26+
]),
27+
'dev',
28+
new SuccessRule(),
29+
false,
30+
],
31+
[
32+
$this->makeMergeRequest([
33+
'target_branch' => 'dev',
34+
]),
35+
'dev',
36+
new FailRule(),
37+
true,
38+
],
39+
];
40+
}
41+
42+
/**
43+
* @dataProvider providerForTestLint
44+
* @covers \ArtARTs36\MergeRequestLinter\Rule\OnTargetBranchRule::lint
45+
*/
46+
public function testLint(MergeRequest $request, string $targetBranch, Rule $rule, bool $hasNotes): void
47+
{
48+
self::assertHasNotes(
49+
$request,
50+
new OnTargetBranchRule($targetBranch, $rule),
51+
$hasNotes,
52+
);
53+
}
54+
}

0 commit comments

Comments
 (0)