diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml new file mode 100644 index 0000000..b20f3b6 --- /dev/null +++ b/.github/workflows/update-changelog.yml @@ -0,0 +1,28 @@ +name: "Update Changelog" + +on: + release: + types: [released] + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: main + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + latest-version: ${{ github.event.release.name }} + release-notes: ${{ github.event.release.body }} + + - name: Commit updated CHANGELOG + uses: stefanzweifel/git-auto-commit-action@v4 + with: + branch: main + commit_message: Update CHANGELOG + file_pattern: CHANGELOG.md diff --git a/README-contr.md b/README-contr.md index 258cd57..349508a 100644 --- a/README-contr.md +++ b/README-contr.md @@ -1 +1,10 @@ todo + + + +```shell +composer analyse +composer test +composer test-coverage +composer format +``` diff --git a/README-todo.md b/README-todo.md new file mode 100644 index 0000000..25ce28b --- /dev/null +++ b/README-todo.md @@ -0,0 +1,7 @@ + - contract + - service + - trait + - config dosyası, status'ler, permissionlar, permiissoon policychecker + - publishler + - yetki konteolleri + - board diff --git a/config/aissue.php b/config/aissue.php index b14e74c..0beb691 100644 --- a/config/aissue.php +++ b/config/aissue.php @@ -1,6 +1,14 @@ fn ($permission): bool => true, + 'issueTypes' => [ + 'task' => [ + 'todo' => ['sort' => 1, 'permission' => 'todo_perm'], + 'in_progress' => ['sort' => 2, 'permission' => 'in_progress_perm'], + 'done' => ['sort' => 3, 'permission' => 'done_perm'], + ], + ], ]; diff --git a/database/migrations/create_aissue_tables.php b/database/migrations/create_aissue_tables.php index 103dfd2..7332285 100644 --- a/database/migrations/create_aissue_tables.php +++ b/database/migrations/create_aissue_tables.php @@ -6,40 +6,29 @@ return new class extends Migration { - public function up() + public function up(): void { Schema::create('aissue_issues', function (Blueprint $table) { $table->bigIncrements('id'); - $table->string('code')->nullable(); $table->string('model_type'); - $table->bigIncrements('model_id'); - $table->bigIncrements('assignee_id'); - $table->bigIncrements('creater_id'); - $table->bigIncrements('issue_type_id'); + $table->bigInteger('model_id'); + $table->bigInteger('assignee_id'); + $table->bigInteger('creater_id'); + $table->string('issue_type'); $table->string('summary'); - $table->string('description'); - $table->bigIncrements('priority'); + $table->string('description')->nullable(); + $table->bigInteger('priority')->default(1); $table->string('status'); - $table->dateTime('duedate'); - $table->boolean('archived'); - $table->bigIncrements('archived_by'); - $table->dateTime('archived_at'); + $table->dateTime('duedate')->nullable(); + $table->boolean('archived')->default(false); + $table->bigInteger('archived_by')->nullable(); + $table->dateTime('archived_at')->nullable(); $table->timestamps(); }); - - Schema::create('aissue_issue_types', function (Blueprint $table) { - $table->bigIncrements('id'); - $table->string('workflow'); - $table->string('name'); - $table->string('description'); - $table->timestamps(); - }); - } - public function down(){ + public function down(): void + { Schema::dropIfExists('aissue_issues'); - Schema::dropIfExists('aissue_issue_types'); } - }; diff --git a/docker-compose.yml b/docker-compose.yml index 68369dd..4b4e486 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ services: ports: - "33062:3306" volumes: - - ~/apps/mariadb-aissue:/var/lib/mysql + - ~/apps/mariadb-aissue2:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=aissue - MYSQL_PASSWORD=aissue @@ -17,4 +17,4 @@ networks: driver: bridge ipam: config: - - subnet: 172.16.57.0/24 + - subnet: 172.16.54.0/24 diff --git a/phpstan.neon.dist b/phpstan.neon.dist index a91953b..32a2dd0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,7 +2,7 @@ includes: - phpstan-baseline.neon parameters: - level: 4 + level: 8 paths: - src - config diff --git a/src/AIssue.php b/src/AIssue.php index 63c819f..4abcd38 100755 --- a/src/AIssue.php +++ b/src/AIssue.php @@ -2,6 +2,64 @@ namespace AuroraWebSoftware\AIssue; +use AuroraWebSoftware\AIssue\Exceptions\TransitionPermissionException; + class AIssue { + /** + * @param array $data + * @return Models\AIssue + */ + public function createIssue(array $data): Models\AIssue + { + return Models\AIssue::create($data); + } + + /** + * @param Models\AIssue $issue + * @param string $status + * @return bool + */ + public function canMakeTransition(Models\AIssue $issue, string $status): bool + { + $permission = config('aissue')['issueTypes'][$issue->getIssueType()][$status]['permission']; + if (config('aissue')['policyMethod']($permission)) { + return true; + } + + return false; + } + + /** + * @param Models\AIssue $issue + * @param string $status + * @return Models\AIssue + * + * @throws TransitionPermissionException + */ + public function makeTransition(Models\AIssue $issue, string $status): Models\AIssue + { + if ($this->canMakeTransition($issue, $status)) { + $issue->status = $status; + $issue->save(); + } + + throw new TransitionPermissionException(); + } + + /** + * @param Models\AIssue $issue + * @return array + */ + public function getTransitionableStatuses(Models\AIssue $issue): array + { + $statuses = []; + foreach (config('aissue')['issueTypes'][$issue->getIssueType()] as $index => $item) { + if ($this->canMakeTransition($issue, $index)) { + $statuses[] = $index; + } + } + + return $statuses; + } } diff --git a/src/AIssueServiceProvider.php b/src/AIssueServiceProvider.php index 6a98958..7694069 100644 --- a/src/AIssueServiceProvider.php +++ b/src/AIssueServiceProvider.php @@ -23,12 +23,14 @@ public function configurePackage(Package $package): void // ->hasCommand(AIssueCommand::class); } - public function boot() + public function boot(): void { parent::boot(); - // load packages migrations - $this->loadMigrationsFrom(__DIR__ . '/../database/migrations'); + $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); + $this->publishes([ + __DIR__.'/../config' => config_path(), + ], 'aissue-config'); } } diff --git a/src/Contracts/AIssueModelContract.php b/src/Contracts/AIssueModelContract.php new file mode 100644 index 0000000..0f0db58 --- /dev/null +++ b/src/Contracts/AIssueModelContract.php @@ -0,0 +1,25 @@ +issue_type; + } + + /** + * @param string $status + * @return bool + */ + public function canMakeTransition(string $status): bool + { + return \AuroraWebSoftware\AIssue\Facades\AIssue::canMakeTransition($this, $status); + } + + /** + * @param string $status + * @return AIssue + */ + public function makeTransition(string $status): AIssue + { + return \AuroraWebSoftware\AIssue\Facades\AIssue::makeTransition($this, $status); + } + + /** + * @param AIssue $issue + * @return array + */ + public function getTransitionableStatuses(AIssue $issue): array + { + return \AuroraWebSoftware\AIssue\Facades\AIssue::getTransitionableStatuses($this); + } +} diff --git a/src/Traits/AIssueModelTrait.php b/src/Traits/AIssueModelTrait.php new file mode 100644 index 0000000..6c936f9 --- /dev/null +++ b/src/Traits/AIssueModelTrait.php @@ -0,0 +1,47 @@ + static::getAIssueModelType(), + 'model_id' => $this->getAIssueModelId(), + 'assignee_id' => $assigneeId, + 'creater_id' => $createrId, + 'issue_type' => $issueType, + 'summary' => $summary, + 'description' => $description, + 'priority' => $priority, + 'status' => static::getAIssueDefaultStatus($issueType), + 'duedate' => $duedate, + ]; + + return AIssue::createIssue($data); + } +} diff --git a/tests/Models/Issueable.php b/tests/Models/Issueable.php new file mode 100644 index 0000000..eb747f5 --- /dev/null +++ b/tests/Models/Issueable.php @@ -0,0 +1,42 @@ +id; + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 3b6c9bb..40ce6f6 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -26,7 +26,8 @@ protected function getPackageProviders($app) public function getEnvironmentSetUp($app) { - config()->set('database.default', 'testing'); + //config()->set('database.default', 'testing'); + config()->set('database.default', 'mysql'); /* $migration = include __DIR__.'/../database/migrations/create_aissue_table.php.stub'; diff --git a/tests/Unit/AIssueTest.php b/tests/Unit/AIssueTest.php index 52348d8..e28469e 100644 --- a/tests/Unit/AIssueTest.php +++ b/tests/Unit/AIssueTest.php @@ -1,10 +1,92 @@ assertTrue(true); +use AuroraWebSoftware\AIssue\Models\AIssue; +use AuroraWebSoftware\AIssue\Tests\Models\Issueable; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Facades\Config; +use Illuminate\Support\Facades\Schema; + +beforeEach(function () { + Artisan::call('migrate:fresh'); + + Schema::create('issueables', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->timestamps(); + }); + + $mockPolicyFunction = function ($permission): bool { + if ($permission == 'todo_perm' || $permission == 'in_progress_perm') { + return true; + } + + return false; + }; + + Config::set('aissue.policyMethod', $mockPolicyFunction); }); +test('can read aissue config', function () { + $this->assertNotNull(config('aissue')); +}); -test('passOrAbort', function () { +test('can access policy method', function () { + $this->assertTrue(config('aissue')['policyMethod'] instanceof \Closure); +}); + +test('can access policy method works for todo', function () { + $this->assertTrue(config('aissue')['policyMethod']('todo_perm')); +}); + +test('can get one specified issue', function () { + //AAuth::organizationNodes(); + // todo expect(1)->toBeTruthy(); }); + +test('can create aissue for a model', function () { + $createdModel = Issueable::create( + ['name' => 'test isuable model 1'] + ); + + $createdIssueModel = $createdModel->createIssue(1, 1, 'task', 'test isssue 1.1', 'asdasd', 1, \Illuminate\Support\Carbon::now()); + + $this->assertEquals( + AIssue::where('id', '=', $createdIssueModel->id)->first()->summary, + $createdIssueModel->summary + ); +}); + +test('can check make transition for todo', function () { + $createdModel = Issueable::create( + ['name' => 'test isuable model 2'] + ); + + /** @var AIssue $createdIssueModel */ + $createdIssueModel = $createdModel->createIssue(1, 1, 'task', 'test isssue 2.1', 'asdasd', 1, \Illuminate\Support\Carbon::now()); + + $this->assertTrue($createdIssueModel->canMakeTransition('todo')); +}); + +test('can check make transition for in_progress', function () { + $createdModel = Issueable::create( + ['name' => 'test isuable model 3'] + ); + + /** @var AIssue $createdIssueModel */ + $createdIssueModel = $createdModel->createIssue(1, 1, 'task', 'test isssue 2.1', 'asdasd', 1, \Illuminate\Support\Carbon::now()); + + $this->assertTrue($createdIssueModel->canMakeTransition('in_progress')); +}); + +test('can check make transition for done', function () { + $createdModel = Issueable::create( + ['name' => 'test isuable model 4'] + ); + + /** @var AIssue $createdIssueModel */ + $createdIssueModel = $createdModel->createIssue(1, 1, 'task', 'test isssue 2.1', 'asdasd', 1, \Illuminate\Support\Carbon::now()); + + $this->assertFalse($createdIssueModel->canMakeTransition('done')); +});