mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-28 09:34:36 +08:00
fix(git): skip Git LFS downloads when Git LFS is disabled
Closes #10360 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
af7365ad57
commit
56af27d46f
2 files changed
+107
-2
No files matched your search
@@ -1580,6 +1580,8 @@ class Application extends BaseModel
|
||||
: 'GIT_SSH_COMMAND="'.$resolvedGitSshCommand.'"')
|
||||
: 'GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"';
|
||||
|
||||
$git_clone_command = $this->gitLfsSkipSmudgePrefix($onlyCheckout).$git_clone_command;
|
||||
|
||||
// Use the explicitly passed commit (e.g. from rollback), falling back to the application's git_commit_sha.
|
||||
// Invalid refs will cause the git checkout/fetch command to fail on the remote server.
|
||||
$commitToUse = $commit ?? $this->git_commit_sha;
|
||||
@@ -1809,6 +1811,16 @@ class Application extends BaseModel
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The helper image installs the Git LFS filter system-wide, so every checkout downloads
|
||||
* LFS objects unless the smudge filter is skipped. A checkout that only reads files (the
|
||||
* Compose file) never needs LFS objects.
|
||||
*/
|
||||
private function gitLfsSkipSmudgePrefix(bool $onlyCheckout = false): string
|
||||
{
|
||||
return $this->settings->is_git_lfs_enabled && ! $onlyCheckout ? '' : 'export GIT_LFS_SKIP_SMUDGE=1 && ';
|
||||
}
|
||||
|
||||
private function gitCommandsAsShellCommand(Collection|array|string $commands): string
|
||||
{
|
||||
if (is_string($commands)) {
|
||||
@@ -1922,10 +1934,11 @@ class Application extends BaseModel
|
||||
|
||||
$git_checkout_command = $this->buildGitCheckoutCommand($pr_branch_name, gitConfigOptions: $gitConfigOption ?? null);
|
||||
$escapedPrBranch = escapeshellarg($branch);
|
||||
$git_pr_command = "{$this->gitLfsSkipSmudgePrefix($only_checkout)}cd {$escapedBaseDir} && git fetch origin {$escapedPrBranch} && $git_checkout_command";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "cd {$escapedBaseDir} && git fetch origin {$escapedPrBranch} && $git_checkout_command")));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $git_pr_command)));
|
||||
} else {
|
||||
$commands->push($this->gitCommand("cd {$escapedBaseDir} && git fetch origin {$escapedPrBranch} && $git_checkout_command"));
|
||||
$commands->push($this->gitCommand($git_pr_command));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationSetting;
|
||||
use App\Models\GithubApp;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Tests\TestCase;
|
||||
|
||||
uses(TestCase::class);
|
||||
|
||||
/**
|
||||
* The helper image installs the Git LFS smudge filter system-wide, so a clone downloads every
|
||||
* LFS object unless GIT_LFS_SKIP_SMUDGE is set for the git process. These tests run the
|
||||
* generated commands in bash with a fake `git` that records the value each call sees. The fake
|
||||
* `docker exec` drops the caller's environment, like a real container.
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
function gitCallsWithLfsSkipSmudge(bool $isGitLfsEnabled, int $pullRequestId = 0, bool $onlyCheckout = false, string $commit = 'HEAD'): array
|
||||
{
|
||||
$application = new Application;
|
||||
$application->forceFill([
|
||||
'uuid' => 'test-app-uuid',
|
||||
'git_repository' => 'duilio/bad-lfs-example',
|
||||
'git_branch' => 'main',
|
||||
'git_commit_sha' => $commit,
|
||||
]);
|
||||
|
||||
$settings = new ApplicationSetting;
|
||||
$settings->is_git_shallow_clone_enabled = false;
|
||||
$settings->is_git_submodules_enabled = false;
|
||||
$settings->is_git_lfs_enabled = $isGitLfsEnabled;
|
||||
$application->setRelation('settings', $settings);
|
||||
|
||||
$source = new GithubApp;
|
||||
$source->forceFill(['html_url' => 'https://github.com', 'is_public' => true]);
|
||||
$application->setRelation('source', $source);
|
||||
|
||||
$bin = sys_get_temp_dir().'/coolify-lfs-test-'.uniqid();
|
||||
mkdir("{$bin}/repo", recursive: true);
|
||||
|
||||
['commands' => $commands] = $application->generateGitImportCommands(
|
||||
deployment_uuid: 'test-deployment',
|
||||
pull_request_id: $pullRequestId,
|
||||
only_checkout: $onlyCheckout,
|
||||
custom_base_dir: "{$bin}/repo",
|
||||
);
|
||||
|
||||
file_put_contents("{$bin}/git", "#!/bin/bash\necho \"\${GIT_LFS_SKIP_SMUDGE:-unset} \$*\" >> \"\$GIT_CALL_LOG\"\n");
|
||||
file_put_contents("{$bin}/docker", "#!/bin/bash\nshift 4\nexec env -u GIT_LFS_SKIP_SMUDGE bash -c \"\$1\"\n");
|
||||
chmod("{$bin}/git", 0755);
|
||||
chmod("{$bin}/docker", 0755);
|
||||
|
||||
try {
|
||||
Process::env(['PATH' => "{$bin}:".getenv('PATH'), 'GIT_CALL_LOG' => "{$bin}/calls.log"])
|
||||
->run(['bash', '-ec', $commands])
|
||||
->throw();
|
||||
|
||||
return str_replace($bin, '<tmp>', file("{$bin}/calls.log", FILE_IGNORE_NEW_LINES));
|
||||
} finally {
|
||||
File::deleteDirectory($bin);
|
||||
}
|
||||
}
|
||||
|
||||
it('skips the lfs smudge filter for every git call when git lfs is disabled', function () {
|
||||
$calls = gitCallsWithLfsSkipSmudge(isGitLfsEnabled: false, pullRequestId: 7);
|
||||
|
||||
expect($calls)->toBe([
|
||||
'1 clone -b main https://github.com/duilio/bad-lfs-example <tmp>/repo',
|
||||
'1 fetch origin pull/7/head:pr-7-coolify',
|
||||
'1 checkout pr-7-coolify',
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps the lfs smudge filter and pulls lfs objects when git lfs is enabled', function () {
|
||||
$calls = gitCallsWithLfsSkipSmudge(isGitLfsEnabled: true);
|
||||
|
||||
expect($calls)->toBe([
|
||||
'unset clone -b main https://github.com/duilio/bad-lfs-example <tmp>/repo',
|
||||
'unset lfs ls-files -n',
|
||||
]);
|
||||
});
|
||||
|
||||
it('skips the lfs smudge filter for the compose file checkout of a pinned commit when git lfs is enabled', function () {
|
||||
$calls = gitCallsWithLfsSkipSmudge(isGitLfsEnabled: true, onlyCheckout: true, commit: 'abc123def456abc123def456abc123def456abc1');
|
||||
|
||||
expect($calls)->toBe([
|
||||
'1 clone --no-checkout -b main https://github.com/duilio/bad-lfs-example <tmp>/repo',
|
||||
'1 -c advice.detachedHead=false checkout abc123def456abc123def456abc123def456abc1',
|
||||
]);
|
||||
});
|
||||
Reference in new issue
Block a user