Skip to content

Commit

Permalink
Merge pull request #2 from Aeliot-Tm/improvement
Browse files Browse the repository at this point in the history
Extend JIRA issue configuration
  • Loading branch information
Aeliot-Tm authored Jun 17, 2024
2 parents a1a5a3c + f6669bb commit 2c9c32b
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 33 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ System pass it in payload to registrar with aim to be used as "identifier" of as

Currently, todo-registrar supports the following issue trackers:

| Issue Tracker | Description |
|-------------------------------------------------|--------------------------|
| [Jira](https://www.atlassian.com/software/jira) | Supported via API tokens |
| Issue Tracker | Description |
|-------------------------------------------------|---------------------------------------------------------------------------------------------|
| [Jira](https://www.atlassian.com/software/jira) | Supported via API tokens. See [description of configuration](docs/registrar/jira/config.md) |
29 changes: 29 additions & 0 deletions docs/registrar/jira/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Configuration of JIRA-registrar

Description of keys:
```php
$jiraConfig = [
'issue' => [
'addTagToLabels' => true, // add detected tag into list of issue labels or not
'assignee' => 'string' // identifier of JIRA-user, which will be assigned to ticket
// when "assignee-suffix" was not used with tag.
'components' => ['a-component'], // list of components which will be set to issue
'labels' => ['a-label'], // list of labels which will be set to issue
'priority' => 'string', // priority of issue
'tagPrefix' => 'tag-', // prefix which will be added to tag when "addTagToLabels=true"
'type' => 'Bug', // type of issue
],
'projectKey' => 'string', // key-name of project
'service' => [
'host' => 'string', // host of JIRA-server
'personalAccessToken' => 'string', // personal access-token
'tokenBasedAuth' => true,

// JIRA username and password can be used as alternative for authentication on JIRA-server.
// So, previous option "tokenBasedAuth" must be set to "false".
//
// 'jiraUser' => 'string',
// 'jiraPassword' => 'string',
]
];
```
9 changes: 9 additions & 0 deletions src/Exception/InvalidConfigException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Aeliot\TodoRegistrar\Exception;

final class InvalidConfigException extends \InvalidArgumentException
{
}
64 changes: 57 additions & 7 deletions src/Service/Registrar/JIRA/IssueConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

namespace Aeliot\TodoRegistrar\Service\Registrar\JIRA;

use Aeliot\TodoRegistrar\Exception\InvalidConfigException;

class IssueConfig
{
private bool $addTagToLabels;
private ?string $assignee;
/**
* @var string[]
*/
Expand All @@ -16,6 +19,7 @@ class IssueConfig
* @var string[]
*/
private array $labels;
private ?string $priority;
private string $projectKey;
private string $tagPrefix;

Expand All @@ -24,20 +28,33 @@ class IssueConfig
*/
public function __construct(array $config)
{
$issue = $config['issue'];
$this->addTagToLabels = $issue['addTagToLabels'] ?? false;
$this->components = (array) ($issue['components'] ?? []);
$this->issueType = $issue['type'];
$this->labels = (array) ($issue['labels'] ?? []);
$this->projectKey = $config['projectKey'];
$this->tagPrefix = $issue['tagPrefix'] ?? '';
if (array_key_exists('issueType', $config) && array_key_exists('type', $config)) {
throw new InvalidConfigException(
'Conflicting config. Both properties "issueType" and "type" added to config of issue'
);
}

$config = $this->normalizeConfig($config);
foreach ((new \ReflectionClass($this))->getProperties() as $property) {
$key = $property->getName();
if (!array_key_exists($key, $config)) {
throw new InvalidConfigException("Undefined property of issue config: {$key}");
}

$this->$key = $config[$key];
}
}

public function isAddTagToLabels(): bool
{
return $this->addTagToLabels;
}

public function getAssignee(): ?string
{
return $this->assignee;
}

/**
* @return string[]
*/
Expand All @@ -59,6 +76,11 @@ public function getLabels(): array
return $this->labels;
}

public function getPriority(): ?string
{
return $this->priority;
}

public function getProjectKey(): string
{
return $this->projectKey;
Expand All @@ -68,4 +90,32 @@ public function getTagPrefix(): string
{
return $this->tagPrefix;
}

/**
* @param array<string,mixed> $config
*
* @return array<string,mixed>
*/
public function normalizeConfig(array $config): array
{
$config += [
'addTagToLabels' => false,
'assignee' => null,
'components' => [],
'labels' => [],
'priority' => null,
'tagPrefix' => '',
];

$config['addTagToLabels'] = (bool) $config['addTagToLabels'];
$config['components'] = (array) $config['components'];
$config['labels'] = (array) $config['labels'];

if (array_key_exists('type', $config)) {
$config['issueType'] = $config['type'];
unset($config['type']);
}

return $config;
}
}
7 changes: 6 additions & 1 deletion src/Service/Registrar/JIRA/IssueFieldFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ public function create(Todo $todo): IssueField
->setDescription($todo->getDescription())
->addComponentsAsArray($this->issueConfig->getComponents());

$assignee = $todo->getAssignee();
$assignee = $todo->getAssignee() ?? $this->issueConfig->getAssignee();
if ($assignee) {
$issueField->setAssigneeNameAsString($assignee);
}

$priority = $this->issueConfig->getPriority();
if ($priority) {
$issueField->setPriorityNameAsString($priority);
}

$labels = $this->issueConfig->getLabels();
if ($this->issueConfig->isAddTagToLabels()) {
$labels[] = strtolower(sprintf('%s%s', $this->issueConfig->getTagPrefix(), $todo->getTag()));
Expand Down
3 changes: 2 additions & 1 deletion src/Service/Registrar/JIRA/JiraRegistrarFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ class JiraRegistrarFactory implements RegistrarFactoryInterface
{
public function create(array $config): RegistrarInterface
{
$issueConfig = ($config['issue'] ?? []) + ['projectKey' => $config['projectKey']];
return new JiraRegistrar(
new IssueFieldFactory(new IssueConfig($config)),
new IssueFieldFactory(new IssueConfig($issueConfig)),
$this->createIssueService($config['service']),
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Service/Tag/Detector.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getTagMetadata(string $line): ?TagMetadata
return null;
}

return new TagMetadata(strtoupper($matches[2]), strlen($matches[1]), $matches[3] ?? null);
return new TagMetadata(strtoupper($matches[2]), strlen(rtrim($matches[1])), $matches[3] ?? null);
}
}
8 changes: 6 additions & 2 deletions tests/Unit/Service/Comment/ExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ public static function getDataForTestCountOfParts(): iterable
1,
'// TODO single line comment',
];

yield [
1,
1,
'# TODO single line comment',
];

yield [
1,
1,
<<<CON
<<<CONT
# TODO single line comment
# with some extra part
CON,
CONT,
];

yield [
3,
1,
Expand All @@ -50,6 +53,7 @@ public static function getDataForTestCountOfParts(): iterable
*/
CONT,
];

yield [
3,
1,
Expand Down
74 changes: 67 additions & 7 deletions tests/Unit/Service/Registrar/IssueConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,89 @@

namespace Aeliot\TodoRegistrar\Test\Unit\Service\Registrar;

use Aeliot\TodoRegistrar\Exception\InvalidConfigException;
use Aeliot\TodoRegistrar\Service\Registrar\JIRA\IssueConfig;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

#[CoversClass(IssueConfig::class)]
final class IssueConfigTest extends TestCase
{
public static function getDataForTestIssueTypeAlias(): iterable
{
yield [
[
'projectKey' => 'any string',
'issueType' => 'Bug',
]
];

yield [
[
'projectKey' => 'any string',
'type' => 'Bug',
]
];
}

public static function getDataForTestThrowExceptionWhenMissedRequiredProperty(): iterable
{
$fullConfig = [
'projectKey' => 'any string',
'type' => 'any string',
];

foreach (array_keys($fullConfig) as $key) {
$config = $fullConfig;
unset($config[$key]);
yield [$config];
}
}

#[DataProvider('getDataForTestIssueTypeAlias')]
public function testIssueTypeAlias(array $values): void
{
$config = new IssueConfig($values);
self::assertSame('Bug', $config->getIssueType());
}

public function testThrowExceptionWithIssueTypeDuplicatedByAlias(): void
{
$this->expectException(InvalidConfigException::class);
$values = [
'projectKey' => 'any string',
'type' => 'any string',
'issueType' => 'any string',
];
new IssueConfig($values);

}

#[DataProvider('getDataForTestThrowExceptionWhenMissedRequiredProperty')]
public function testThrowExceptionWhenMissedRequiredProperty(array $values): void
{
$this->expectException(InvalidConfigException::class);
new IssueConfig($values);
}

public function testValueAssigning(): void
{
$values = [
'issue' => [
'addTagToLabels' => true,
'components' => ['Component-1', 'Component-2'],
'labels' => ['Label-1', 'Label-2'],
'tagPrefix' => 'tag-',
'type' => 'Bug',
],
'addTagToLabels' => true,
'components' => ['Component-1', 'Component-2'],
'labels' => ['Label-1', 'Label-2'],
'priority' => 'Low',
'tagPrefix' => 'tag-',
'type' => 'Bug',
// extra key added in factory
'projectKey' => 'Todo',
];
$config = new IssueConfig($values);

self::assertTrue($config->isAddTagToLabels());
self::assertSame('Bug', $config->getIssueType());
self::assertSame('Low', $config->getPriority());
self::assertSame('tag-', $config->getTagPrefix());
self::assertSame(['Component-1', 'Component-2'], $config->getComponents());
self::assertSame(['Label-1', 'Label-2'], $config->getLabels());
Expand Down
Loading

0 comments on commit 2c9c32b

Please sign in to comment.