Merge branch 'trunk'
This commit is contained in:
commit
65772aeb1d
16 changed files with 556 additions and 11 deletions
260
app/Console/Commands/UpdateGitlabDatas.php
Normal file
260
app/Console/Commands/UpdateGitlabDatas.php
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\GitlabIssues;
|
||||
use App\Models\GitlabLabels;
|
||||
use App\Models\GitlabMilestones;
|
||||
use App\Models\GitlabProjects;
|
||||
use Carbon\Carbon;
|
||||
use GrahamCampbell\GitLab\Facades\GitLab;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class UpdateGitlabDatas extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'app:update-gitlab-datas {--is-cron}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fetch some Gitlab datas';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$isCron = $this->option('is-cron');
|
||||
|
||||
$groupId = 23;
|
||||
|
||||
$this->updateProjectsByGroup($groupId);
|
||||
|
||||
$this->updateLabelsByGroup($groupId);
|
||||
|
||||
$projects = GitlabProjects::all();
|
||||
|
||||
foreach ($projects as $project) {
|
||||
$this->updateMilestonesByProject($project);
|
||||
$this->updateIssuesByProject($project, $isCron);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* updateProjectsByGroup function
|
||||
*
|
||||
* @param integer $groupId
|
||||
* @return void
|
||||
*/
|
||||
private function updateProjectsByGroup(int $groupId): void
|
||||
{
|
||||
$allProjects = [];
|
||||
$page = 1;
|
||||
do {
|
||||
$projects = GitLab::groups()->projects($groupId, [
|
||||
'order_by' => 'created_at',
|
||||
'sort' => 'asc',
|
||||
'per_page' => 100,
|
||||
'page' => $page,
|
||||
'include_subgroups' => true
|
||||
]);
|
||||
$allProjects = array_merge($allProjects, $projects);
|
||||
$page++;
|
||||
} while (!empty($projects));
|
||||
|
||||
$this->info(sprintf(
|
||||
"Fetched %d projects in group %d.",
|
||||
count($allProjects),
|
||||
$groupId
|
||||
));
|
||||
|
||||
foreach ($allProjects as $project) {
|
||||
GitlabProjects::upsert(
|
||||
[
|
||||
'name' => $project['name'],
|
||||
'url' => $project['web_url'],
|
||||
'is_archived' => $project['archived'],
|
||||
'gitlab_id' => $project['id']
|
||||
],
|
||||
['gitlab_id']
|
||||
);
|
||||
}
|
||||
|
||||
$this->info("Gitlab Projects upsert complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
* updateLabelsByGroup function
|
||||
*
|
||||
* @param integer $groupId
|
||||
* @return void
|
||||
*/
|
||||
private function updateLabelsByGroup(int $groupId): void
|
||||
{
|
||||
$allLabels = [];
|
||||
$page = 1;
|
||||
do {
|
||||
$labels = GitLab::groups()->labels($groupId, [
|
||||
'per_page' => 100,
|
||||
'page' => $page,
|
||||
]);
|
||||
$allLabels = array_merge($allLabels, $labels);
|
||||
$page++;
|
||||
} while (!empty($labels));
|
||||
|
||||
$this->info(sprintf(
|
||||
"Fetched %d labels in group %d.",
|
||||
count($allLabels),
|
||||
$groupId
|
||||
));
|
||||
|
||||
foreach ($allLabels as $project) {
|
||||
GitlabLabels::upsert(
|
||||
[
|
||||
'name' => $project['name'],
|
||||
'gitlab_id' => $project['id']
|
||||
],
|
||||
['gitlab_id']
|
||||
);
|
||||
}
|
||||
|
||||
$this->info("Gitlab labels upsert complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
* updateIssuesByProject function
|
||||
*
|
||||
* @param GitlabProjects $project
|
||||
* @param boolean $isCron
|
||||
* @return void
|
||||
*/
|
||||
private function updateIssuesByProject(GitlabProjects $project, bool $isCron = false): void
|
||||
{
|
||||
$projectId = $project->gitlab_id;
|
||||
$allIssues = [];
|
||||
$page = 1;
|
||||
|
||||
do {
|
||||
$params = [
|
||||
'order_by' => 'created_at',
|
||||
'sort' => 'asc',
|
||||
'per_page' => 100,
|
||||
'page' => $page,
|
||||
'state' => 'all',
|
||||
];
|
||||
if ($isCron) {
|
||||
$params = array_merge($params, ['updated_after' => now()->subDay()]);
|
||||
}
|
||||
$issues = GitLab::projects()->issues($projectId, $params);
|
||||
$allIssues = array_merge($allIssues, $issues);
|
||||
$page++;
|
||||
} while (!empty($issues));
|
||||
|
||||
$this->info(sprintf(
|
||||
"Fetched %d issues in project %d.",
|
||||
count($allIssues),
|
||||
$projectId
|
||||
));
|
||||
|
||||
foreach ($allIssues as $issue) {
|
||||
GitlabIssues::upsert(
|
||||
[
|
||||
'title' => $issue['title'],
|
||||
'url' => $issue['web_url'],
|
||||
'estimate_time' => $issue['time_stats']['time_estimate'] ?? 0,
|
||||
'spent_time' => $issue['time_stats']['total_time_spent'] ?? 0,
|
||||
'is_closed' => $issue['state'] === 'closed',
|
||||
'gitlab_id' => $issue['id'],
|
||||
'gitlab_iid' => $issue['iid'],
|
||||
'milestone_iid' => $issue['milestone']['iid'] ?? null,
|
||||
'gitlab_project_id' => $projectId,
|
||||
'g_created_at' => Carbon::parse($issue['created_at'])->format('Y-m-d'),
|
||||
'g_updated_at' => Carbon::parse($issue['updated_at'])->format('Y-m-d'),
|
||||
'g_closed_at' => !is_null($issue['closed_at'])
|
||||
? Carbon::parse($issue['closed_at'])->format('Y-m-d')
|
||||
: null,
|
||||
'g_due_date' => !is_null($issue['due_date'])
|
||||
? Carbon::parse($issue['due_date'])->format('Y-m-d')
|
||||
: null
|
||||
],
|
||||
['gitlab_id']
|
||||
);
|
||||
|
||||
$issueModel = GitlabIssues::where('gitlab_id', $issue['id'])->firstOrFail();
|
||||
|
||||
foreach ($issue['labels'] as $labelName) {
|
||||
$label = Cache::remember("gitlab_label_{$labelName}", 300, function () use ($labelName) {
|
||||
return GitlabLabels::where('name', $labelName)->first();
|
||||
});
|
||||
|
||||
if ($label) {
|
||||
$issueModel->gitlabLabels()->syncWithoutDetaching($label);
|
||||
}
|
||||
}
|
||||
}//end foreach
|
||||
|
||||
$this->info("Gitlab issues upsert complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
* updateMilestonesByProject function
|
||||
*
|
||||
* @param GitlabProjects $project
|
||||
* @return void
|
||||
*/
|
||||
private function updateMilestonesByProject(GitlabProjects $project): void
|
||||
{
|
||||
$projectId = $project->gitlab_id;
|
||||
$allMilestones = [];
|
||||
$page = 1;
|
||||
|
||||
do {
|
||||
$milestones = GitLab::milestones()->all($projectId, [
|
||||
'per_page' => 100,
|
||||
'page' => $page
|
||||
]);
|
||||
$allMilestones = array_merge($allMilestones, $milestones);
|
||||
$page++;
|
||||
} while (!empty($milestones));
|
||||
|
||||
$this->info(sprintf(
|
||||
"Fetched %d milestones in project %d.",
|
||||
count($allMilestones),
|
||||
$projectId
|
||||
));
|
||||
|
||||
foreach ($allMilestones as $milestone) {
|
||||
GitlabMilestones::upsert(
|
||||
[
|
||||
'title' => $milestone['title'],
|
||||
'url' => $milestone['web_url'],
|
||||
'is_closed' => $milestone['state'] === 'closed',
|
||||
'gitlab_id' => $milestone['id'],
|
||||
'gitlab_iid' => $milestone['iid'],
|
||||
'gitlab_project_id' => $projectId,
|
||||
'g_created_at' => Carbon::parse($milestone['created_at'])->format('Y-m-d'),
|
||||
'g_updated_at' => Carbon::parse($milestone['updated_at'])->format('Y-m-d'),
|
||||
'g_start_date' => !is_null($milestone['start_date'])
|
||||
? Carbon::parse($milestone['start_date'])->format('Y-m-d')
|
||||
: null,
|
||||
'g_due_date' => !is_null($milestone['due_date'])
|
||||
? Carbon::parse($milestone['due_date'])->format('Y-m-d')
|
||||
: null
|
||||
],
|
||||
['gitlab_id']
|
||||
);
|
||||
}//end foreach
|
||||
|
||||
$this->info("Gitlab milestones upsert complete.");
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ class Kernel extends ConsoleKernel
|
|||
$schedule->job(ExportTicketsState::class)->weekly()->mondays()->at('07:00');
|
||||
$schedule->job(AutoCloseOldTickets::class)->dailyAt('08:00');
|
||||
$schedule->job(WarnBeforeAutoCloseTicket::class)->dailyAt('08:05');
|
||||
$schedule->command('app:update-gitlab-datas --is-cron')->twiceDaily(1, 13);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ enum TicketTypeEnum: int
|
|||
case qrcode = 5;
|
||||
case advice = 6;
|
||||
case complaints = 7;
|
||||
case mailing = 8;
|
||||
case mailing = 8;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
|
|
|
|||
|
|
@ -881,12 +881,12 @@ class TicketController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Update ticket priority.
|
||||
*
|
||||
* @param UpdateTicketPriorityRequest $request
|
||||
* @param Ticket $ticket
|
||||
* @return void
|
||||
*/
|
||||
* Update ticket priority.
|
||||
*
|
||||
* @param UpdateTicketPriorityRequest $request
|
||||
* @param Ticket $ticket
|
||||
* @return void
|
||||
*/
|
||||
public function changePriority(UpdateTicketPriorityRequest $request, Ticket $ticket)
|
||||
{
|
||||
$newPriority = $request->validated('priority');
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class UpdateTicketPriorityRequest extends FormRequest
|
|||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->ticket = $this->route('ticket');
|
||||
$max = Ticket::query()->where('site_id', $this->ticket->site_id)->max('order');
|
||||
$max = Ticket::query()->where('site_id', $this->ticket->site_id)->max('order');
|
||||
|
||||
$this->merge([
|
||||
'priority' => min($this->integer('priority'), $max)
|
||||
|
|
|
|||
40
app/Models/GitlabIssues.php
Normal file
40
app/Models/GitlabIssues.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class GitlabIssues extends Model
|
||||
{
|
||||
/**
|
||||
* Fillable array model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'url',
|
||||
'estimate_time',
|
||||
'spent_time',
|
||||
'is_closed',
|
||||
'gitlab_id',
|
||||
'gitlab_iid',
|
||||
'milestone_iid',
|
||||
'gitlab_project_id',
|
||||
'g_created_at',
|
||||
'g_updated_at',
|
||||
'g_closed_at',
|
||||
'g_due_date'
|
||||
];
|
||||
|
||||
/**
|
||||
* Gitlab Labels relationship
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function gitlabLabels()
|
||||
{
|
||||
return $this->belongsToMany(GitlabLabels::class, 'gitlab_issues_labels', 'issue_id', 'label_id')
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
||||
29
app/Models/GitlabLabels.php
Normal file
29
app/Models/GitlabLabels.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class GitlabLabels extends Model
|
||||
{
|
||||
/**
|
||||
* Fillable array model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'gitlab_id'
|
||||
];
|
||||
|
||||
/**
|
||||
* Gitlab Issues relationship
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function issues()
|
||||
{
|
||||
return $this->belongsToMany(GitlabIssues::class, 'gitlab_issues_labels', 'label_id', 'issue_id')
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
||||
26
app/Models/GitlabMilestones.php
Normal file
26
app/Models/GitlabMilestones.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class GitlabMilestones extends Model
|
||||
{
|
||||
/**
|
||||
* Fillable array model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'url',
|
||||
'is_closed',
|
||||
'gitlab_id',
|
||||
'gitlab_iid',
|
||||
'gitlab_project_id',
|
||||
'g_created_at',
|
||||
'g_updated_at',
|
||||
'g_start_date',
|
||||
'g_due_date'
|
||||
];
|
||||
}
|
||||
20
app/Models/GitlabProjects.php
Normal file
20
app/Models/GitlabProjects.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class GitlabProjects extends Model
|
||||
{
|
||||
/**
|
||||
* Fillable array model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'url',
|
||||
'is_archived',
|
||||
'gitlab_id'
|
||||
];
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
"codegreencreative/laravel-samlidp": "^5.2",
|
||||
"diglactic/laravel-breadcrumbs": "^9.0",
|
||||
"doctrine/dbal": "^3.1",
|
||||
"graham-campbell/gitlab": "^7.0",
|
||||
"graham-campbell/gitlab": "^7.6",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"laravel/framework": "^11.0",
|
||||
"laravel/tinker": "^2.8",
|
||||
|
|
|
|||
4
composer.lock
generated
4
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7c22201effe7a464dcc8e3048d370b4f",
|
||||
"content-hash": "e7bf9833354cd32d54b40e311c64f916",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
|
|
@ -12600,5 +12600,5 @@
|
|||
"php": "^8.3"
|
||||
},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_projects', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment("Gitlab project name");
|
||||
$table->string('url')->comment("Gitlab URL");
|
||||
$table->boolean('is_archived')->comment("Gitlab archive status");
|
||||
$table->integer('gitlab_id')->unique()->comment("Gitlab unique ID");
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_projects');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_issues', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title')->comment("Gitlab issue title");
|
||||
$table->string('url')->comment("Gitlab URL");
|
||||
$table->integer('estimate_time')->default(0)->comment("Gitlab issue estimate time in seconds");
|
||||
$table->integer('spent_time')->default(0)->comment("Gitlab issue spent time in seconds");
|
||||
$table->boolean('is_closed')->comment("Gitlab issue status");
|
||||
$table->integer('gitlab_id')->comment("Gitlab issue id");
|
||||
$table->integer('gitlab_iid')->comment("Gitlab issue iid in project");
|
||||
$table->integer('milestone_iid')->nullable()->comment("Gitlab issue linked milestone iid in project");
|
||||
$table->integer('gitlab_project_id')->comment("Gitlab project id");
|
||||
$table->date('g_created_at')->comment("Gitlab issue created at");
|
||||
$table->date('g_updated_at')->comment("Gitlab issue updated at");
|
||||
$table->date('g_closed_at')->nullable()->comment("Gitlab issue closed at");
|
||||
$table->date('g_due_date')->nullable()->comment("Gitlab issue due date");
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_issues');
|
||||
}
|
||||
};
|
||||
|
||||
//"labels" : ["foo", "bar"],
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_labels', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->unique()->comment("Label name");
|
||||
$table->integer('gitlab_id')->comment("Label Gitlab id");
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_labels');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_milestones', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title')->comment("Milestone title");
|
||||
$table->string('url')->comment("Gitlab URL");
|
||||
$table->boolean('is_closed')->comment("Gitlab milestone status");
|
||||
$table->integer('gitlab_id')->comment("Gitlab milestone id");
|
||||
$table->integer('gitlab_iid')->comment("Gitlab milestone iid in project");
|
||||
$table->integer('gitlab_project_id')->comment("Gitlab project id");
|
||||
$table->date('g_created_at')->comment("Gitlab milestone created at");
|
||||
$table->date('g_updated_at')->comment("Gitlab milestone updated at");
|
||||
$table->date('g_start_date')->nullable()->comment("Gitlab milestone start date");
|
||||
$table->date('g_due_date')->nullable()->comment("Gitlab milestone due date");
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_milestones');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_issues_labels', function (Blueprint $table) {
|
||||
$table->foreignId('issue_id')->constrained('gitlab_issues')->cascadeOnDelete();
|
||||
$table->foreignId('label_id')->constrained('gitlab_labels')->cascadeOnDelete();
|
||||
$table->timestamps();
|
||||
|
||||
$table->primary(['issue_id', 'label_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_issues_labels');
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue