#feature: add project&cronjob management

This commit is contained in:
2026-01-16 12:14:43 +08:00
parent bbe68839e3
commit 381d5e6e49
19 changed files with 2157 additions and 84 deletions

View File

@@ -0,0 +1,47 @@
<?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('projects', function (Blueprint $table) {
$table->id();
$table->string('slug', 100)->unique()->comment('项目唯一标识,如 portal-be');
$table->string('name', 255)->comment('显示名称');
$table->string('directory', 255)->nullable()->comment('相对于 projects_path 的目录名');
$table->string('absolute_path', 500)->nullable()->comment('绝对路径覆盖(可选)');
$table->string('jira_project_code', 50)->nullable()->comment('JIRA 项目代码');
// Git 监控相关
$table->boolean('git_monitor_enabled')->default(false)->comment('是否启用 Git 监控');
$table->string('git_last_checked_commit', 64)->nullable()->comment('最后检查的 commit SHA');
$table->string('git_current_version', 50)->nullable()->comment('当前版本号');
$table->string('git_release_branch', 255)->nullable()->comment('Release 分支名');
$table->timestamp('git_version_cached_at')->nullable()->comment('版本缓存时间');
// 日志分析相关
$table->json('log_app_names')->nullable()->comment('关联的 App 名称列表');
$table->string('log_env', 50)->default('production')->comment('日志分析环境');
$table->timestamps();
$table->index('jira_project_code', 'idx_jira_project_code');
$table->index('git_monitor_enabled', 'idx_git_monitor_enabled');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('projects');
}
};

View File

@@ -0,0 +1,103 @@
<?php
use App\Models\Config;
use App\Models\Project;
use Carbon\Carbon;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
if (!Schema::hasTable('projects') || !Schema::hasTable('configs')) {
return;
}
// 1. 读取现有配置
$repositories = Config::query()->where('key', 'workspace.repositories')->first()?->value ?? [];
$lastChecked = Config::query()->where('key', 'git_monitor.last_checked_commits')->first()?->value ?? [];
$currentVersions = Config::query()->where('key', 'git_monitor.current_versions')->first()?->value ?? [];
$appEnvMap = Config::query()->where('key', 'log_analysis.app_env_map')->first()?->value ?? [];
$enabledProjects = config('git-monitor.enabled_projects', []);
// 2. 为每个仓库创建 Project 记录
foreach ($repositories as $slug => $repo) {
if (!is_string($slug) || $slug === '') {
continue;
}
// 检查是否已存在
if (Project::query()->where('slug', $slug)->exists()) {
continue;
}
Project::query()->create([
'slug' => $slug,
'name' => $repo['display'] ?? ucfirst(str_replace('-', ' ', $slug)),
'directory' => $repo['directory'] ?? $slug,
'absolute_path' => $repo['path'] ?? null,
'jira_project_code' => $repo['jira_project'] ?? null,
'git_monitor_enabled' => in_array($slug, $enabledProjects, true),
'git_last_checked_commit' => $lastChecked[$slug] ?? null,
'git_current_version' => $currentVersions['repositories'][$slug]['current_version'] ?? null,
'git_release_branch' => $currentVersions['repositories'][$slug]['branch'] ?? null,
'git_version_cached_at' => isset($currentVersions['cached_at'])
? Carbon::parse($currentVersions['cached_at'])
: null,
'log_app_names' => $this->findAppNamesForProject($appEnvMap, $slug),
'log_env' => $this->findEnvForProject($appEnvMap, $slug),
]);
}
// 3. 删除旧配置
Config::query()->whereIn('key', [
'workspace.repositories',
'git_monitor.current_versions',
'git_monitor.last_checked_commits',
'log_analysis.app_env_map',
])->delete();
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// 不支持回滚,因为数据结构已经改变
// 如需回滚,请手动恢复数据
}
/**
* appEnvMap 中找出映射到指定项目的所有 app 名称
*/
private function findAppNamesForProject(array $appEnvMap, string $projectSlug): ?array
{
$appNames = [];
foreach ($appEnvMap as $appName => $mapping) {
if (isset($mapping['project']) && $mapping['project'] === $projectSlug) {
$appNames[] = $appName;
}
}
return empty($appNames) ? null : $appNames;
}
/**
* appEnvMap 中找出指定项目的环境
*/
private function findEnvForProject(array $appEnvMap, string $projectSlug): string
{
foreach ($appEnvMap as $mapping) {
if (isset($mapping['project']) && $mapping['project'] === $projectSlug) {
return $mapping['env'] ?? 'production';
}
}
return 'production';
}
};

View File

@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('projects', function (Blueprint $table) {
$table->boolean('is_important')->default(false)->after('git_monitor_enabled')->comment('是否为重要项目');
});
}
public function down(): void
{
Schema::table('projects', function (Blueprint $table) {
$table->dropColumn('is_important');
});
}
};

View File

@@ -0,0 +1,28 @@
<?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::table('projects', function (Blueprint $table) {
$table->boolean('auto_create_release_branch')->default(false)->after('git_monitor_enabled');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('projects', function (Blueprint $table) {
$table->dropColumn('auto_create_release_branch');
});
}
};