fix: coderabbit changes + compose improvements

This commit is contained in:
Aditya Tripathi 2026-02-21 20:27:28 +00:00
parent 2e7c6fc0eb
commit 6b87705b77
10 changed files with 114 additions and 10 deletions

View file

@ -242,9 +242,17 @@ class GithubPrivateRepository extends Component
$application_init['health_check_enabled'] = false;
}
if ($this->build_pack === 'dockerfile' && $this->selectedDockerfile) {
if (! empty($this->detectedDockerfiles) && ! in_array($this->selectedDockerfile, $this->detectedDockerfiles, true)) {
$this->selectedDockerfile = $this->detectedDockerfiles[0];
}
$application_init['dockerfile_location'] = $this->selectedDockerfile;
}
if ($this->build_pack === 'dockercompose') {
if (! empty($this->detectedDockerComposeFiles) && $this->selectedDockerComposeFile
&& ! in_array($this->selectedDockerComposeFile, $this->detectedDockerComposeFiles, true)) {
$this->selectedDockerComposeFile = $this->detectedDockerComposeFiles[0];
$this->docker_compose_location = '/'.$this->selectedDockerComposeFile;
}
$application_init['docker_compose_location'] = $this->docker_compose_location;
}

View file

@ -219,9 +219,17 @@ class GithubPrivateRepositoryDeployKey extends Component
$application_init['health_check_enabled'] = false;
}
if ($this->build_pack === 'dockerfile' && $this->selectedDockerfile) {
if (! empty($this->detectedDockerfiles) && ! in_array($this->selectedDockerfile, $this->detectedDockerfiles, true)) {
$this->selectedDockerfile = $this->detectedDockerfiles[0];
}
$application_init['dockerfile_location'] = $this->selectedDockerfile;
}
if ($this->build_pack === 'dockercompose') {
if (! empty($this->detectedDockerComposeFiles) && $this->selectedDockerComposeFile
&& ! in_array($this->selectedDockerComposeFile, $this->detectedDockerComposeFiles, true)) {
$this->selectedDockerComposeFile = $this->detectedDockerComposeFiles[0];
$this->docker_compose_location = '/'.$this->selectedDockerComposeFile;
}
$application_init['docker_compose_location'] = $this->docker_compose_location;
$application_init['base_directory'] = $this->base_directory;
}

View file

@ -204,7 +204,9 @@ class PublicGitRepository extends Component
$this->detectRepository();
}
} catch (\Throwable $e) {
return handleError($e, $this);
// Both main and master failed — still run detection
// with clone fallback to the repo's default branch
$this->detectRepository();
}
} else {
return handleError($e, $this);
@ -396,9 +398,17 @@ class PublicGitRepository extends Component
$application_init['health_check_enabled'] = false;
}
if ($this->build_pack === 'dockerfile' && $this->selectedDockerfile) {
if (! empty($this->detectedDockerfiles) && ! in_array($this->selectedDockerfile, $this->detectedDockerfiles, true)) {
$this->selectedDockerfile = $this->detectedDockerfiles[0];
}
$application_init['dockerfile_location'] = $this->selectedDockerfile;
}
if ($this->build_pack === 'dockercompose') {
if (! empty($this->detectedDockerComposeFiles) && $this->selectedDockerComposeFile
&& ! in_array($this->selectedDockerComposeFile, $this->detectedDockerComposeFiles, true)) {
$this->selectedDockerComposeFile = $this->detectedDockerComposeFiles[0];
$this->docker_compose_location = '/'.$this->selectedDockerComposeFile;
}
$application_init['docker_compose_location'] = $this->docker_compose_location;
$application_init['base_directory'] = $this->base_directory;
}

View file

@ -30,6 +30,11 @@ class RepositoryDetector
->first();
if (! $server) {
Log::debug('Repository detection skipped: server not found', [
'serverId' => $this->serverId,
'teamId' => $this->teamId,
]);
return RepositoryDetectionResult::none();
}
@ -48,13 +53,16 @@ class RepositoryDetector
$workDir = escapeshellarg("{$tempDir}{$cdBase}");
$envPattern = self::ENV_FILE_PATTERN;
$escapedTempDir = escapeshellarg($tempDir);
$commands = collect([
'rm -rf -- '.escapeshellarg($tempDir),
'git clone --depth 1 -b '.escapeshellarg($this->branch).' '.escapeshellarg($this->repositoryUrl).' '.escapeshellarg($tempDir).' >/dev/null 2>&1',
'rm -rf -- '.$escapedTempDir,
"trap 'rm -rf -- {$escapedTempDir}' EXIT",
'git clone --depth 1 -b '.escapeshellarg($this->branch).' '.escapeshellarg($this->repositoryUrl).' '.escapeshellarg($tempDir).' >/dev/null 2>&1 || git clone --depth 1 '.escapeshellarg($this->repositoryUrl).' '.escapeshellarg($tempDir).' >/dev/null 2>&1',
"cd {$workDir}",
// Collect file lists into shell variables
'df_list=$(git ls-files | grep -i \'dockerfile\' || true)',
'compose_list=$(git ls-files | grep -iE \'^(docker-compose\.(yml|yaml)|compose\.(yml|yaml))$\' || true)',
'df_list=$(git ls-files | grep -iE \'(^|/)Dockerfile(\.[a-zA-Z0-9_-]+)?$\' || true)',
'compose_list=$(git ls-files | grep -iE \'(^|/)(docker-compose\.(yml|yaml)|compose\.(yml|yaml))$\' || true)',
'env_list=$(git ls-files | grep -iE \''.$envPattern.'\' || true)',
// Build env file contents as a JSON object (uses jq to safely encode file content)
'env_json=\'{}\'',
@ -79,7 +87,6 @@ class RepositoryDetector
' --argjson envFiles "$env_json" \\',
' --argjson dockerfilePorts "$port_json" \\',
' \'$ARGS.named\'',
'rm -rf -- '.escapeshellarg($tempDir),
]);
try {
@ -111,7 +118,7 @@ class RepositoryDetector
$dockerfilePorts = [];
foreach ($data['dockerfilePorts'] ?? [] as $file => $port) {
$dockerfilePorts[$file] = is_int($port) ? $port : null;
$dockerfilePorts[$file] = is_numeric($port) ? (int) $port : null;
}
return new RepositoryDetectionResult(

View file

@ -14,6 +14,8 @@ trait HasRepositoryDetection
public ?string $selectedDockerfile = null;
public ?string $selectedDockerComposeFile = null;
public ?int $detectedPort = null;
public array $dockerfilePorts = [];
@ -49,8 +51,9 @@ trait HasRepositoryDetection
}
}
if ($result->hasDockerCompose() && count($result->dockerComposeFiles) === 1) {
$this->docker_compose_location = '/'.$result->dockerComposeFiles[0];
if ($result->hasDockerCompose()) {
$this->selectedDockerComposeFile = $result->dockerComposeFiles[0];
$this->docker_compose_location = '/'.$this->selectedDockerComposeFile;
}
if ($result->hasEnvFiles()) {
@ -68,12 +71,31 @@ trait HasRepositoryDetection
public function updatedSelectedDockerfile(): void
{
if ($this->selectedDockerfile && ! in_array($this->selectedDockerfile, $this->detectedDockerfiles, true)) {
$this->selectedDockerfile = $this->detectedDockerfiles[0] ?? null;
}
if ($this->selectedDockerfile && isset($this->dockerfilePorts[$this->selectedDockerfile])) {
$port = $this->dockerfilePorts[$this->selectedDockerfile];
if ($port) {
$this->port = $port;
$this->detectedPort = $port;
} else {
$this->detectedPort = null;
}
} else {
$this->detectedPort = null;
}
}
public function updatedSelectedDockerComposeFile(): void
{
if ($this->selectedDockerComposeFile && ! in_array($this->selectedDockerComposeFile, $this->detectedDockerComposeFiles, true)) {
$this->selectedDockerComposeFile = $this->detectedDockerComposeFiles[0] ?? null;
}
if ($this->selectedDockerComposeFile) {
$this->docker_compose_location = '/'.$this->selectedDockerComposeFile;
}
}

View file

@ -115,6 +115,14 @@
@endif
@if ($build_pack === 'dockercompose')
@if (count($detectedDockerComposeFiles) > 1)
<x-forms.select wire:model.live="selectedDockerComposeFile" label="Docker Compose File"
helper="Multiple Docker Compose files were detected. Select which one to use.">
@foreach ($detectedDockerComposeFiles as $cf)
<option value="{{ $cf }}">{{ $cf }}</option>
@endforeach
</x-forms.select>
@endif
<div x-data="{
baseDir: '{{ $base_directory }}',
composeLocation: '{{ $docker_compose_location }}',

View file

@ -134,6 +134,14 @@
@endif
@if ($build_pack === 'dockercompose')
@if (count($detectedDockerComposeFiles) > 1)
<x-forms.select wire:model.live="selectedDockerComposeFile" label="Docker Compose File"
helper="Multiple Docker Compose files were detected. Select which one to use.">
@foreach ($detectedDockerComposeFiles as $cf)
<option value="{{ $cf }}">{{ $cf }}</option>
@endforeach
</x-forms.select>
@endif
<div x-data="{
baseDir: '{{ $base_directory }}',
composeLocation: '{{ $docker_compose_location }}',

View file

@ -42,7 +42,7 @@
<div class="flex gap-3 items-center">
<label class="w-1/3 text-sm font-mono truncate dark:text-neutral-400" title="{{ $key }}">{{ $key }}</label>
<input type="text" class="w-2/3 input"
wire:model.defer="envExampleVars.{{ $key }}" />
wire:model="envExampleVars.{{ $key }}" />
</div>
@endforeach
</div>

View file

@ -99,6 +99,14 @@
@endif
@if ($build_pack === 'dockercompose')
@if (count($detectedDockerComposeFiles) > 1)
<x-forms.select wire:model.live="selectedDockerComposeFile" label="Docker Compose File"
helper="Multiple Docker Compose files were detected. Select which one to use.">
@foreach ($detectedDockerComposeFiles as $cf)
<option value="{{ $cf }}">{{ $cf }}</option>
@endforeach
</x-forms.select>
@endif
<div x-data="{
baseDir: '{{ $base_directory }}',
composeLocation: '{{ $docker_compose_location }}',

View file

@ -171,6 +171,31 @@ test('parseOutput handles multiple env files', function () {
->and($result->hasEnvFiles())->toBeTrue();
});
test('parseOutput handles string port values from JSON', function () {
$output = json_encode([
'dockerfiles' => ['Dockerfile'],
'dockerComposeFiles' => [],
'envFiles' => (object) [],
'dockerfilePorts' => ['Dockerfile' => '3000'],
]);
$detector = new RepositoryDetector(
repositoryUrl: 'https://github.com/test/repo',
branch: 'main',
baseDirectory: '/',
serverId: 1,
teamId: 1,
);
$reflection = new ReflectionClass($detector);
$method = $reflection->getMethod('parseOutput');
$result = $method->invoke($detector, $output);
expect($result->dockerfilePorts)->toBe(['Dockerfile' => 3000])
->and($result->dockerfilePorts['Dockerfile'])->toBeInt();
});
test('parseOutput returns none for invalid JSON', function () {
$detector = new RepositoryDetector(
repositoryUrl: 'https://github.com/test/repo',