#feature: add AI log analysis & some bugfix
This commit is contained in:
@@ -66,12 +66,17 @@ class GitMonitorService
|
||||
}
|
||||
|
||||
try {
|
||||
$version = $this->jiraService->getUpcomingReleaseVersion($projectKey);
|
||||
// 先从 master 分支获取当前版本号
|
||||
$currentVersion = $this->getMasterVersion($repoKey, $repoConfig);
|
||||
|
||||
// 根据当前版本号获取下一个版本
|
||||
$version = $this->jiraService->getUpcomingReleaseVersion($projectKey, $currentVersion);
|
||||
if ($version) {
|
||||
$payload['repositories'][$repoKey] = [
|
||||
'version' => $version['version'],
|
||||
'release_date' => $version['release_date'],
|
||||
'branch' => 'release/' . $version['version'],
|
||||
'current_version' => $currentVersion,
|
||||
];
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
@@ -181,16 +186,23 @@ class GitMonitorService
|
||||
];
|
||||
|
||||
foreach ($commits as $commit) {
|
||||
if ($this->isDevelopMerge($path, $commit)) {
|
||||
$isMerge = $this->isMergeCommit($path, $commit);
|
||||
$isConflictResolution = $this->isConflictResolution($path, $commit);
|
||||
|
||||
// 只检测直接从 develop 合并的情况
|
||||
if ($isMerge && $this->isDevelopMerge($path, $commit)) {
|
||||
$issues['develop_merges'][] = $this->getCommitMetadata($path, $commit);
|
||||
}
|
||||
|
||||
$missingFunctions = $this->detectMissingFunctions($path, $commit);
|
||||
if (!empty($missingFunctions)) {
|
||||
$issues['missing_functions'][] = [
|
||||
'commit' => $this->getCommitMetadata($path, $commit),
|
||||
'details' => $missingFunctions,
|
||||
];
|
||||
// 只在 merge 提交或冲突解决提交中检测缺失函数
|
||||
if ($isMerge || $isConflictResolution) {
|
||||
$missingFunctions = $this->detectMissingFunctions($path, $commit);
|
||||
if (!empty($missingFunctions)) {
|
||||
$issues['missing_functions'][] = [
|
||||
'commit' => $this->getCommitMetadata($path, $commit),
|
||||
'details' => $missingFunctions,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,34 +251,52 @@ class GitMonitorService
|
||||
return array_values(array_filter(array_map('trim', explode("\n", $output))));
|
||||
}
|
||||
|
||||
private function isDevelopMerge(string $repoPath, string $commit): bool
|
||||
/**
|
||||
* 判断是否为 merge 提交(有多个父提交)
|
||||
*/
|
||||
private function isMergeCommit(string $repoPath, string $commit): bool
|
||||
{
|
||||
$parents = trim($this->runGit($repoPath, ['git', 'show', '-s', '--pretty=%P', $commit]));
|
||||
$parentShas = array_values(array_filter(explode(' ', $parents)));
|
||||
|
||||
if (count($parentShas) < 2) {
|
||||
return false;
|
||||
return count($parentShas) >= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为冲突解决提交
|
||||
* 通过检查 commit message 是否包含冲突相关关键词
|
||||
*/
|
||||
private function isConflictResolution(string $repoPath, string $commit): bool
|
||||
{
|
||||
$message = strtolower($this->runGit($repoPath, ['git', 'show', '-s', '--pretty=%s', $commit]));
|
||||
|
||||
$conflictKeywords = ['conflict', 'resolve', '冲突', '解决冲突'];
|
||||
foreach ($conflictKeywords as $keyword) {
|
||||
if (str_contains($message, $keyword)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为直接从 develop 分支合并到 release 的提交
|
||||
* 只检测 commit message 明确包含 "merge.*develop" 或 "develop.*into" 的情况
|
||||
*/
|
||||
private function isDevelopMerge(string $repoPath, string $commit): bool
|
||||
{
|
||||
$message = strtolower($this->runGit($repoPath, ['git', 'show', '-s', '--pretty=%s', $commit]));
|
||||
if (str_contains($message, self::DEVELOP_BRANCH)) {
|
||||
|
||||
// 检测 "Merge branch 'develop'" 或 "merge develop into" 等模式
|
||||
// 排除 feature/xxx、hotfix/xxx 等分支的合并
|
||||
if (preg_match("/merge\s+(branch\s+)?['\"]?develop['\"]?(\s+into)?/i", $message)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$target = 'origin/' . self::DEVELOP_BRANCH;
|
||||
|
||||
foreach ($parentShas as $parent) {
|
||||
$branches = $this->runGit($repoPath, ['git', 'branch', '-r', '--contains', $parent]);
|
||||
foreach (preg_split('/\R/', $branches) as $branchLine) {
|
||||
$branchLine = trim(str_replace('*', '', $branchLine));
|
||||
if (empty($branchLine)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($branchLine === $target || str_ends_with($branchLine, '/' . self::DEVELOP_BRANCH)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 检测 "develop into release" 模式
|
||||
if (preg_match("/develop\s+into\s+['\"]?release/i", $message)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -331,11 +361,15 @@ class GitMonitorService
|
||||
private function extractFunctionName(string $line): ?string
|
||||
{
|
||||
$trimmed = trim($line);
|
||||
if (str_starts_with($trimmed, '//') || str_starts_with($trimmed, '#') || str_starts_with($trimmed, '*')) {
|
||||
|
||||
// 跳过注释行
|
||||
if (str_starts_with($trimmed, '//') || str_starts_with($trimmed, '#') || str_starts_with($trimmed, '*') || str_starts_with($trimmed, '/*')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match('/function\s+([A-Za-z0-9_]+)\s*\(/', $trimmed, $matches)) {
|
||||
// 只匹配真正的函数定义,必须以 function 关键字开头,或者以访问修饰符开头
|
||||
// 匹配: function foo(, public function foo(, private static function foo( 等
|
||||
if (preg_match('/^(?:(?:public|protected|private)\s+)?(?:static\s+)?function\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/', $trimmed, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
@@ -495,4 +529,29 @@ class GitMonitorService
|
||||
$directory = $repoConfig['directory'] ?? $repoKey;
|
||||
return $this->projectsPath . '/' . ltrim($directory, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 master 分支读取 version.txt 获取当前版本号
|
||||
*/
|
||||
public function getMasterVersion(string $repoKey, array $repoConfig): ?string
|
||||
{
|
||||
$path = $this->resolveProjectPath($repoKey, $repoConfig);
|
||||
|
||||
if (!is_dir($path) || !is_dir($path . DIRECTORY_SEPARATOR . '.git')) {
|
||||
Log::warning('Invalid git repository path', ['repository' => $repoKey, 'path' => $path]);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->runGit($path, ['git', 'fetch', 'origin', 'master']);
|
||||
$version = $this->runGit($path, ['git', 'show', 'origin/master:version.txt']);
|
||||
return trim($version) ?: null;
|
||||
} catch (ProcessFailedException $e) {
|
||||
Log::warning('Failed to read version.txt from master branch', [
|
||||
'repository' => $repoKey,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user