Skip to content

Commit

Permalink
Merge pull request #1 from Aeliot-Tm/detector_implementaion
Browse files Browse the repository at this point in the history
Base implementation
  • Loading branch information
Aeliot-Tm authored Jun 13, 2024
2 parents de8f3ed + 810fdd3 commit a1a5a3c
Show file tree
Hide file tree
Showing 52 changed files with 5,172 additions and 3 deletions.
21 changes: 20 additions & 1 deletion .docker/php/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,37 @@ ENV DOCKER_PHP_DEPS \
libxml2-dev \
libzip-dev \
unzip
ENV XDEBUG_VERSION 3.2.1

RUN set -xe; \
apt-get --allow-releaseinfo-change update && \
apt-get install -y -qq ${DOCKER_PHP_DEPS} --no-install-suggests --no-install-recommends && \
docker-php-ext-install -j$(nproc) xml && \
docker-php-ext-install -j$(nproc) zip
docker-php-ext-install -j$(nproc) zip && \
pecl install xdebug-${XDEBUG_VERSION} && docker-php-ext-enable xdebug

RUN rm -rf /var/lib/apt/lists/* && \
apt-get clean

# Copy php configs
COPY .docker/php/conf.d/*.ini /usr/local/etc/php/conf.d/

# Install composer
RUN set -xe; \
curl -sS https://getcomposer.org/installer | php -- --filename=composer --install-dir=/usr/local/bin --version=${COMPOSER_VERSION} > /dev/null 2>&1 && \
chmod +x /usr/local/bin/composer

WORKDIR /app

COPY composer.* ./

RUN set -xe; \
composer install --no-autoloader --no-dev --no-interaction --no-progress --no-scripts --prefer-dist && \
composer clear-cache && \
rm -rf ./vendor/*/*/tests

COPY . ./
RUN chmod +x ./docker-entrypoint.sh && \
rm -rf ./.docker

RUN composer dump-autoload --optimize
10 changes: 10 additions & 0 deletions .docker/php/conf.d/docker-php-ext-xdebug.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[xdebug]
zend_extension=xdebug.so

xdebug.mode=debug,coverage
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.start_with_request=yes
xdebug.idekey=PHPSTORM
xdebug.log_level=0
xdebug.log=/app/var/xdebug.log
48 changes: 48 additions & 0 deletions .github/workflows/automated_testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Automated Testing

on:
push:

permissions:
contents: read

jobs:
composer:
name: Validate composer files
runs-on: ubuntu-latest

steps:
- uses: shivammathur/setup-php@v2
with:
php-version: 8.2

- uses: actions/checkout@v4

- name: Validate composer.json and composer.lock
run: composer validate --strict

phpunit:
name: 'Tests: Unit'
runs-on: ubuntu-latest

steps:
- uses: shivammathur/setup-php@v2
with:
php-version: 8.2

- uses: actions/checkout@v4

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v4
with:
path: vendor
key: "${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}"
restore-keys: |
${{ runner.os }}-php-
- name: Install dependencies
uses: ramsey/composer-install@v3

- name: 'Run all PHPUnit tests'
run: composer run phpunit
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.idea
.phpunit
/var
/vendor
26 changes: 26 additions & 0 deletions .todo-registrar.dist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

use Aeliot\TodoRegistrar\Config;
use Aeliot\TodoRegistrar\Enum\RegistrarType;
use Aeliot\TodoRegistrar\Service\File\Finder;

return (new Config())
->setFinder((new Finder())->in(__DIR__))
->setRegistrar(RegistrarType::JIRA, [
'issue' => [
'addTagToLabels' => true,
'components' => ['Component-1', 'Component-2'],
'labels' => ['Label-1', 'Label-2'],
'tagPrefix' => 'tag-',
'type' => 'Bug',
],
'projectKey' => 'Todo',
'service' => [
'host' => $_ENV['JIRA_HOST'] ?? 'localhost',
'personalAccessToken' => $_ENV['JIRA_PERSONAL_ACCESS_TOKEN'] ?? null,
'tokenBasedAuth' => true,
]
])
->setTags(['todo', 'fixme', 'a_custom_tag']);
112 changes: 112 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# TODO Registrar

Package responsible for registration of issues in Issue Trackers.

## Installation

1. Require package via Composer:
```shell
composer require --dev aeliot/todo-registrar
```
2. Create configuration file. It expects ".todo-registrar.php" or ".todo-registrar.dist.php" at the root of the project.

## Using

1. Call script:
```shell
vendor/bin/todo-registrar
```
You may pass option with it `--config=/custom/path/to/config`. Otherwise, it tries to use one of default files.
2. Commit updated files. You may config your pipeline/job on CI which commits updates.

## Configuration file

Config file is php-file which returns instance of class `\Aeliot\TodoRegistrar\Config`. See [example](.todo-registrar.dist.php).

It has setters:
1. `setFinder` - accepts instance of configured finder of php-files.
2. `setRegistrar` - responsible for configuration of registrar factory. It accepts as type of registrar with its config
as instance of custom registrar factory.
3. `setTags` - array of detected tags. It supports "todo" and "fixme" by default.
You don't need to configure it when you want to use only this tags. Nevertheless, you have to set them
when you want to use them together with your custom tags.

### Supported patters of comments (examples):

It detects TODO-tags in single-line comments started with both `//` and `#` symbols
and multiple-line comments `/* ... */` and phpDoc `/** ... **/`.

1. Tag and comment separated by semicolon
```php
// TODO: comment summary
```
2. Tag and comment does not separated by semicolon
```php
// TODO comment summary
```
3. Tag with assignee and comment separated by semicolon
```php
// TODO@assigne: comment summary
```
4. Tag with assignee and comment does not separated by semicolon
```php
// TODO@assigne comment summary
```
5. Multiline comment with complex description. All lines after the first one with tag MUST have indentation
same to the text of the first line. So, all af them will be detected af part of description of TODO.
Multiple line comments may have assignee and semicolon same as single-line comments/.
```php
/**
* TODO: comment summary
* and some complex description
* which must have indentation same as end of one presented:
* - semicolon
* - assignee
* - tag
* So, all this text will be passed to registrar as description
* without not meaning indentations (" * " in this case).
* This line (and all after) will not be detected as part (description) of "TODO"
* case they don't have expected indentation.
*/
```

As a result of processing of such comments, ID of ISSUE will be injected before comment summary
and after semicolon and assignee when they are presented. For example:
1. Tag and comment separated by semicolon
```php
// TODO: XX-001 comment summary
```
2. Tag and comment does not separated by semicolon
```php
// TODO XX-001 comment summary
```
3. Tag with assignee and comment separated by semicolon
```php
// TODO@assigne: XX-001 comment summary
```
4. Tag with assignee and comment does not separated by semicolon
```php
// TODO@assigne XX-001 comment summary
```
5. Multiline comment with complex description. All lines after the first one with tag MUST have indentation
same to the text of the first line. So, all af them will be detected af part of description of TODO.
Multiple line comments may have assignee and semicolon same as single-line comments/.
```php
/**
* TODO: XX-001 comment summary
* and some complex description
*/
```

### Assignee-part

It is some "username" which separated of tag by symbol "@". It sticks to pattern `/[a-z0-9._-]+/i`.
System pass it in payload to registrar with aim to be used as "identifier" of assignee in issue tracker.

## Supported Issue Trackers

Currently, todo-registrar supports the following issue trackers:

| Issue Tracker | Description |
|-------------------------------------------------|--------------------------|
| [Jira](https://www.atlassian.com/software/jira) | Supported via API tokens |
83 changes: 83 additions & 0 deletions bin/todo-registrar
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env php
<?php

use Aeliot\TodoRegistrar\ApplicationFactory;
use Aeliot\TodoRegistrar\Config;

$autoloaderPath = (static function (): string {
$paths = [
__DIR__ . '/vendor/autoload.php',
__DIR__ . '/../vendor/autoload.php',
__DIR__ . '/../../vendor/autoload.php',
__DIR__ . '/../../../vendor/autoload.php',
__DIR__ . '/../../../../vendor/autoload.php',
];

foreach ($paths as $path) {
if (file_exists($path)) {
return realpath($path);
}
}

throw new RuntimeException('Cannot find autoloader');
})();

require_once $autoloaderPath;

$projectPath = dirname($autoloaderPath, 2);

$absolutePathMaker = static function (string $path) use ($projectPath): string {
if (preg_match('#^(?:[[:alpha:]]:[/\\\\]|/)#', $path)) {
return $path;
}

return $projectPath . '/' . $path;
};

$configGuess = static function () use ($absolutePathMaker): string {
$candidates = [
'.todo-registrar.php',
'.todo-registrar.dist.php',
];
foreach ($candidates as $candidate) {
$path = $absolutePathMaker($candidate);
if (file_exists($path)) {
return $path;
}
}

throw new \DomainException('Cannot detect default config file');
};

$options = (static function () use ($absolutePathMaker, $configGuess): array {
$values = [];
$options = getopt('c:', ['config']);
$defaults = [
'config' => ['c', null],
];

foreach ($defaults as $long => [$short, $default]) {
if (isset($options[$short], $options[$long])) {
throw new InvalidArgumentException(sprintf('Option %s is duplicated', $long));
}
$values[$long] = $options[$short] ?? $options[$long] ?? $default;
}

if (!isset($values['config'])) {
$values['config'] = $configGuess();
}

return $values;
})();

if (!file_exists($options['config'])) {
throw new RuntimeException(sprintf('Config file "%s" does not exist', $options['config']));
}

/** @var Config $config */
$config = require $options['config'];
if (!$config instanceof Config) {
throw new RuntimeException(sprintf('Config file "%s" does not return instance of config', $options['config']));
}

(new ApplicationFactory())->create($config)->run();
34 changes: 32 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,47 @@
{
"name": "aeliot/todo-registrar",
"type": "library",
"type": "application",
"description": "Register TODOs from source code in issue tracker",
"license": "MIT",
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Aeliot\\TodoRegistrar\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Aeliot\\TodoRegistrar\\Test\\": "tests/"
}
},
"bin": [
"bin/todo-registrar"
],
"config": {
"allow-plugins": {
"composer/*": true
},
"sort-packages": true
},
"require": {
"php": "^8.2"
"php": "^8.2",
"ext-tokenizer": "*",
"lesstif/php-jira-rest-client": "^5.8",
"symfony/finder": "^5.4|^6.0|^7.0"
},
"require-dev": {
"dg/bypass-finals": "^1.7",
"phpunit/phpunit": "^11.1",
"roave/security-advisories": "dev-latest"
},
"scripts": {
"phpunit": "vendor/bin/phpunit"
},
"suggest": {
"staabm/phpstan-todo-by": "For the monitoring of outdated comments when ticket closed and TODO-comment should be removed"
},
"support": {
"issues": "https://github.com/Aeliot-Tm/todo-registrar/issues"
}
}
Loading

0 comments on commit a1a5a3c

Please sign in to comment.