fix: stabilise staging sync
This commit is contained in:
@@ -57,7 +57,9 @@ services:
|
|||||||
[ -f /run/secrets/GIT_TOKEN ] && export GIT_TOKEN="$(cat /run/secrets/GIT_TOKEN)" || true
|
[ -f /run/secrets/GIT_TOKEN ] && export GIT_TOKEN="$(cat /run/secrets/GIT_TOKEN)" || true
|
||||||
|
|
||||||
# Fix Git ownership issue
|
# Fix Git ownership issue
|
||||||
|
# Ensure Git treats the mounted repository as safe regardless of owner
|
||||||
git config --global --add safe.directory /var/www/html 2>/dev/null || true
|
git config --global --add safe.directory /var/www/html 2>/dev/null || true
|
||||||
|
git config --system --add safe.directory /var/www/html 2>/dev/null || true
|
||||||
|
|
||||||
# Git Clone/Pull functionality
|
# Git Clone/Pull functionality
|
||||||
if [ -n "$GIT_REPOSITORY_URL" ]; then
|
if [ -n "$GIT_REPOSITORY_URL" ]; then
|
||||||
@@ -84,7 +86,7 @@ services:
|
|||||||
fi
|
fi
|
||||||
TEMP_CLONE="${GIT_TARGET_DIR}.tmp"
|
TEMP_CLONE="${GIT_TARGET_DIR}.tmp"
|
||||||
rm -rf "$TEMP_CLONE" 2>/dev/null || true
|
rm -rf "$TEMP_CLONE" 2>/dev/null || true
|
||||||
if git clone --branch "$GIT_BRANCH" --depth 1 "$GIT_URL_WITH_AUTH" "$TEMP_CLONE"; then
|
if git -c safe.directory=/var/www/html clone --branch "$GIT_BRANCH" --depth 1 "$GIT_URL_WITH_AUTH" "$TEMP_CLONE"; then
|
||||||
find "$GIT_TARGET_DIR" -mindepth 1 -maxdepth 1 ! -name "storage" -exec rm -rf {} \; 2>/dev/null || true
|
find "$GIT_TARGET_DIR" -mindepth 1 -maxdepth 1 ! -name "storage" -exec rm -rf {} \; 2>/dev/null || true
|
||||||
find "$TEMP_CLONE" -mindepth 1 -maxdepth 1 ! -name "." ! -name ".." -exec mv {} "$GIT_TARGET_DIR/" \; 2>/dev/null || true
|
find "$TEMP_CLONE" -mindepth 1 -maxdepth 1 ! -name "." ! -name ".." -exec mv {} "$GIT_TARGET_DIR/" \; 2>/dev/null || true
|
||||||
rm -rf "$TEMP_CLONE" 2>/dev/null || true
|
rm -rf "$TEMP_CLONE" 2>/dev/null || true
|
||||||
@@ -93,9 +95,9 @@ services:
|
|||||||
else
|
else
|
||||||
echo "🔄 Pulling latest changes from $GIT_BRANCH..."
|
echo "🔄 Pulling latest changes from $GIT_BRANCH..."
|
||||||
cd "$GIT_TARGET_DIR"
|
cd "$GIT_TARGET_DIR"
|
||||||
git fetch origin "$GIT_BRANCH" || echo "⚠️ Git fetch failed"
|
git -c safe.directory=/var/www/html fetch origin "$GIT_BRANCH" || echo "⚠️ Git fetch failed"
|
||||||
git reset --hard "origin/$GIT_BRANCH" || echo "⚠️ Git reset failed"
|
git -c safe.directory=/var/www/html reset --hard "origin/$GIT_BRANCH" || echo "⚠️ Git reset failed"
|
||||||
git clean -fd || true
|
git -c safe.directory=/var/www/html clean -fd || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use App\Framework\Logging\ValueObjects\LogContext;
|
|||||||
name: 'detect:n-plus-one',
|
name: 'detect:n-plus-one',
|
||||||
description: 'Detect N+1 query problems and generate optimization recommendations'
|
description: 'Detect N+1 query problems and generate optimization recommendations'
|
||||||
)]
|
)]
|
||||||
final readonly class DetectN+1Command
|
final readonly class DetectNPlusOneCommand
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private NPlusOneDetectionService $detectionService,
|
private NPlusOneDetectionService $detectionService,
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Framework\Discovery\Processing;
|
|
||||||
|
|
||||||
use App\Framework\Core\ValueObjects\ClassName;
|
|
||||||
use App\Framework\Filesystem\File;
|
|
||||||
use App\Framework\Filesystem\FileSystemService;
|
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts class information from PHP files efficiently
|
|
||||||
*/
|
|
||||||
final readonly class ClassExtractor
|
|
||||||
{
|
|
||||||
private const PATTERNS = [
|
|
||||||
'namespace' => '/^\s*namespace\s+([^;]+);/m',
|
|
||||||
'class' => '/^\s*(?:final\s+)?(?:abstract\s+)?(?:readonly\s+)?class\s+([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/mi',
|
|
||||||
'interface' => '/^\s*interface\s+([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/mi',
|
|
||||||
'trait' => '/^\s*trait\s+([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/mi',
|
|
||||||
'enum' => '/^\s*enum\s+([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/mi',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
private FileSystemService $fileSystemService
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract class names from a file
|
|
||||||
* @return array<ClassName>
|
|
||||||
*/
|
|
||||||
public function extractFromFile(File $file): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Read file content once
|
|
||||||
$content = $this->fileSystemService->readFile($file);
|
|
||||||
|
|
||||||
// Extract namespace
|
|
||||||
$namespace = $this->extractNamespace($content);
|
|
||||||
|
|
||||||
// Extract all class-like declarations
|
|
||||||
$classNames = [];
|
|
||||||
|
|
||||||
foreach (['class', 'interface', 'trait', 'enum'] as $type) {
|
|
||||||
$names = $this->extractDeclarations($content, $type, $namespace);
|
|
||||||
foreach ($names as $name) {
|
|
||||||
$classNames[] = $name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->deduplicateClassNames($classNames);
|
|
||||||
|
|
||||||
} catch (Throwable) {
|
|
||||||
// Silently fail for files that can't be processed
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract namespace from content
|
|
||||||
*/
|
|
||||||
private function extractNamespace(string $content): string
|
|
||||||
{
|
|
||||||
if (preg_match(self::PATTERNS['namespace'], $content, $matches)) {
|
|
||||||
return trim($matches[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract declarations of a specific type
|
|
||||||
* @return array<ClassName>
|
|
||||||
*/
|
|
||||||
private function extractDeclarations(string $content, string $type, string $namespace): array
|
|
||||||
{
|
|
||||||
$pattern = self::PATTERNS[$type] ?? null;
|
|
||||||
if (! $pattern) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$classNames = [];
|
|
||||||
if (preg_match_all($pattern, $content, $matches)) {
|
|
||||||
foreach ($matches[1] as $name) {
|
|
||||||
$fullName = $namespace ? $namespace . '\\' . $name : $name;
|
|
||||||
$classNames[] = ClassName::create($fullName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $classNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove duplicate class names
|
|
||||||
* @param array<ClassName> $classNames
|
|
||||||
* @return array<ClassName>
|
|
||||||
*/
|
|
||||||
private function deduplicateClassNames(array $classNames): array
|
|
||||||
{
|
|
||||||
$seen = [];
|
|
||||||
$unique = [];
|
|
||||||
|
|
||||||
foreach ($classNames as $className) {
|
|
||||||
$fqn = $className->getFullyQualified();
|
|
||||||
if (! isset($seen[$fqn])) {
|
|
||||||
$seen[$fqn] = true;
|
|
||||||
$unique[] = $className;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $unique;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Quick check if content likely contains PHP classes
|
|
||||||
*/
|
|
||||||
public function likelyContainsClasses(string $content): bool
|
|
||||||
{
|
|
||||||
// Quick checks to avoid regex on files that definitely don't have classes
|
|
||||||
if (strlen($content) < 10) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must have PHP opening tag
|
|
||||||
if (! str_contains($content, '<?php')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for class-like keywords
|
|
||||||
$keywords = ['class ', 'interface ', 'trait ', 'enum '];
|
|
||||||
foreach ($keywords as $keyword) {
|
|
||||||
if (str_contains($content, $keyword)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user