fix(deploy): preserve private key command metadata (#10795)
This commit is contained in:
commit
fe9b43be7c
7 changed files with 335 additions and 159 deletions
|
|
@ -2367,12 +2367,7 @@ private function clone_repository()
|
|||
if ($this->pull_request_id !== 0) {
|
||||
$this->application_deployment_queue->addLogEntry("Checking out tag pull/{$this->pull_request_id}/head.");
|
||||
}
|
||||
$this->execute_remote_command(
|
||||
[
|
||||
$importCommands,
|
||||
'hidden' => true,
|
||||
]
|
||||
);
|
||||
$this->execute_remote_command(...$this->gitCommandDefinitions($importCommands));
|
||||
$this->create_workdir();
|
||||
$this->execute_remote_command(
|
||||
[
|
||||
|
|
@ -2402,6 +2397,39 @@ private function generate_git_import_commands()
|
|||
return $commands;
|
||||
}
|
||||
|
||||
private function gitCommandDefinitions(Collection|array|string $commands): array
|
||||
{
|
||||
if (is_string($commands)) {
|
||||
return [
|
||||
[
|
||||
$commands,
|
||||
'hidden' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return collect($commands)
|
||||
->map(function ($command): array {
|
||||
if (is_string($command)) {
|
||||
return [
|
||||
$command,
|
||||
'hidden' => true,
|
||||
];
|
||||
}
|
||||
|
||||
if (is_array($command)) {
|
||||
return $command + ['hidden' => true];
|
||||
}
|
||||
|
||||
return [
|
||||
'command' => $command,
|
||||
'hidden' => true,
|
||||
];
|
||||
})
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
private function cleanup_git()
|
||||
{
|
||||
$this->execute_remote_command(
|
||||
|
|
|
|||
|
|
@ -1338,7 +1338,7 @@ public function getGitRemoteStatus(string $deployment_uuid)
|
|||
{
|
||||
try {
|
||||
['commands' => $lsRemoteCommand] = $this->generateGitLsRemoteCommands(deployment_uuid: $deployment_uuid, exec_in_docker: false);
|
||||
instant_remote_process([$lsRemoteCommand], $this->destination->server, true);
|
||||
instant_remote_process([$this->gitCommandsAsShellCommand($lsRemoteCommand)], $this->destination->server, true);
|
||||
|
||||
return [
|
||||
'is_accessible' => true,
|
||||
|
|
@ -1390,13 +1390,13 @@ public function generateGitLsRemoteCommands(string $deployment_uuid, bool $exec_
|
|||
}
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));
|
||||
} else {
|
||||
$commands->push($base_command);
|
||||
$commands->push($this->gitCommand($base_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $this->gitCommandsAsShellCommand($commands),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1413,29 +1413,16 @@ public function generateGitLsRemoteCommands(string $deployment_uuid, bool $exec_
|
|||
$escapedCustomRepository = str_replace("'", "'\\''", $customRepository);
|
||||
$base_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$gitlabPort} -o Port={$gitlabPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {$customSshKeyLocation} -o IdentitiesOnly=yes\" {$base_command} '{$escapedCustomRepository}'";
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands = collect([
|
||||
executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||
executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null"),
|
||||
executeInDocker($deployment_uuid, "chmod 600 {$customSshKeyLocation}"),
|
||||
]);
|
||||
} else {
|
||||
$commands = collect([
|
||||
"trap 'rm -f {$customSshKeyLocation}' EXIT",
|
||||
'mkdir -p /root/.ssh',
|
||||
"echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null",
|
||||
"chmod 600 {$customSshKeyLocation}",
|
||||
]);
|
||||
}
|
||||
$commands = $this->gitSshKeySetupCommands($deployment_uuid, $private_key, $exec_in_docker);
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));
|
||||
} else {
|
||||
$commands->push($base_command);
|
||||
$commands->push($this->gitCommand($base_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $commands,
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1447,13 +1434,13 @@ public function generateGitLsRemoteCommands(string $deployment_uuid, bool $exec_
|
|||
$base_command = "{$base_command} {$escapedCustomRepository}";
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));
|
||||
} else {
|
||||
$commands->push($base_command);
|
||||
$commands->push($this->gitCommand($base_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $this->gitCommandsAsShellCommand($commands),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1472,29 +1459,16 @@ public function generateGitLsRemoteCommands(string $deployment_uuid, bool $exec_
|
|||
$escapedCustomRepository = str_replace("'", "'\\''", $customRepository);
|
||||
$base_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {$customSshKeyLocation} -o IdentitiesOnly=yes\" {$base_command} '{$escapedCustomRepository}'";
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands = collect([
|
||||
executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||
executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null"),
|
||||
executeInDocker($deployment_uuid, "chmod 600 {$customSshKeyLocation}"),
|
||||
]);
|
||||
} else {
|
||||
$commands = collect([
|
||||
"trap 'rm -f {$customSshKeyLocation}' EXIT",
|
||||
'mkdir -p /root/.ssh',
|
||||
"echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null",
|
||||
"chmod 600 {$customSshKeyLocation}",
|
||||
]);
|
||||
}
|
||||
$commands = $this->gitSshKeySetupCommands($deployment_uuid, $private_key, $exec_in_docker);
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));
|
||||
} else {
|
||||
$commands->push($base_command);
|
||||
$commands->push($this->gitCommand($base_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $commands,
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1506,19 +1480,60 @@ public function generateGitLsRemoteCommands(string $deployment_uuid, bool $exec_
|
|||
$base_command = "{$base_command} {$escapedCustomRepository}";
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));
|
||||
} else {
|
||||
$commands->push($base_command);
|
||||
$commands->push($this->gitCommand($base_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $this->gitCommandsAsShellCommand($commands),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function gitCommand(string $command): array
|
||||
{
|
||||
return [
|
||||
'command' => $command,
|
||||
'hidden' => true,
|
||||
];
|
||||
}
|
||||
|
||||
private function gitCommandsAsShellCommand(Collection|array|string $commands): string
|
||||
{
|
||||
if (is_string($commands)) {
|
||||
return $commands;
|
||||
}
|
||||
|
||||
return collect($commands)
|
||||
->map(fn ($command) => data_get($command, 'command') ?? $command[0] ?? $command)
|
||||
->implode(' && ');
|
||||
}
|
||||
|
||||
private function gitSshKeySetupCommands(string $deploymentUuid, string $privateKey, bool $execInDocker): Collection
|
||||
{
|
||||
$customSshKeyLocation = "/root/.ssh/id_rsa_coolify_{$deploymentUuid}";
|
||||
$commands = collect([]);
|
||||
|
||||
if (! $execInDocker) {
|
||||
$commands->push($this->gitCommand("trap 'rm -f {$customSshKeyLocation}' EXIT"));
|
||||
}
|
||||
|
||||
$commands->push($this->gitCommand($execInDocker ? executeInDocker($deploymentUuid, 'mkdir -p /root/.ssh') : 'mkdir -p /root/.ssh'));
|
||||
$commands->push([
|
||||
'command' => $execInDocker
|
||||
? executeInDocker($deploymentUuid, "echo '{$privateKey}' | base64 -d | tee {$customSshKeyLocation} > /dev/null")
|
||||
: "echo '{$privateKey}' | base64 -d | tee {$customSshKeyLocation} > /dev/null",
|
||||
'hidden' => true,
|
||||
'skip_command_log' => true,
|
||||
]);
|
||||
$commands->push($this->gitCommand($execInDocker ? executeInDocker($deploymentUuid, "chmod 600 {$customSshKeyLocation}") : "chmod 600 {$customSshKeyLocation}"));
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
private function withGitHttpTransportConfig(?string $gitConfigOptions = null): string
|
||||
{
|
||||
return trim(($gitConfigOptions ? "{$gitConfigOptions} " : '').'-c http.version=HTTP/1.1');
|
||||
|
|
@ -1590,9 +1605,9 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true, commit: $commit, gitConfigOptions: $gitConfigOptions);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $git_clone_command)));
|
||||
} else {
|
||||
$commands->push($git_clone_command);
|
||||
$commands->push($this->gitCommand($git_clone_command));
|
||||
}
|
||||
} else {
|
||||
$github_access_token = generateGithubInstallationToken($this->source);
|
||||
|
|
@ -1619,9 +1634,9 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: false, commit: $commit, gitConfigOptions: $gitConfigOptions);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $git_clone_command)));
|
||||
} else {
|
||||
$commands->push($git_clone_command);
|
||||
$commands->push($this->gitCommand($git_clone_command));
|
||||
}
|
||||
}
|
||||
if ($pull_request_id !== 0) {
|
||||
|
|
@ -1631,14 +1646,14 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
$gitCommand = isset($gitConfigOptions) ? "git {$gitConfigOptions}" : 'git';
|
||||
$escapedPrBranch = escapeshellarg($branch);
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "cd {$escapedBaseDir} && {$gitCommand} fetch origin {$escapedPrBranch} && $git_checkout_command"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "cd {$escapedBaseDir} && {$gitCommand} fetch origin {$escapedPrBranch} && $git_checkout_command")));
|
||||
} else {
|
||||
$commands->push("cd {$escapedBaseDir} && {$gitCommand} fetch origin {$escapedPrBranch} && $git_checkout_command");
|
||||
$commands->push($this->gitCommand("cd {$escapedBaseDir} && {$gitCommand} fetch origin {$escapedPrBranch} && $git_checkout_command"));
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $this->gitCommandsAsShellCommand($commands),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1661,39 +1676,26 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
} else {
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit, gitSshCommand: $gitlabSshCommand);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
$commands = collect([
|
||||
executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||
executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null"),
|
||||
executeInDocker($deployment_uuid, "chmod 600 {$customSshKeyLocation}"),
|
||||
]);
|
||||
} else {
|
||||
$commands = collect([
|
||||
"trap 'rm -f {$customSshKeyLocation}' EXIT",
|
||||
'mkdir -p /root/.ssh',
|
||||
"echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null",
|
||||
"chmod 600 {$customSshKeyLocation}",
|
||||
]);
|
||||
}
|
||||
$commands = $this->gitSshKeySetupCommands($deployment_uuid, $private_key, $exec_in_docker);
|
||||
|
||||
if ($pull_request_id !== 0) {
|
||||
$branch = "merge-requests/{$pull_request_id}/head:$pr_branch_name";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
$commands->push($this->gitCommand("echo 'Checking out $branch'"));
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$gitlabGitSshCommand} git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name, $gitlabSshCommand);
|
||||
}
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $git_clone_command)));
|
||||
} else {
|
||||
$commands->push($git_clone_command);
|
||||
$commands->push($this->gitCommand($git_clone_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $commands,
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1710,13 +1712,13 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true, commit: $commit, gitConfigOptions: $gitConfigOptions);
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $git_clone_command)));
|
||||
} else {
|
||||
$commands->push($git_clone_command);
|
||||
$commands->push($this->gitCommand($git_clone_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $this->gitCommandsAsShellCommand($commands),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1738,55 +1740,42 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
} else {
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit, gitSshCommand: $deployKeySshCommand);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
$commands = collect([
|
||||
executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||
executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null"),
|
||||
executeInDocker($deployment_uuid, "chmod 600 {$customSshKeyLocation}"),
|
||||
]);
|
||||
} else {
|
||||
$commands = collect([
|
||||
"trap 'rm -f {$customSshKeyLocation}' EXIT",
|
||||
'mkdir -p /root/.ssh',
|
||||
"echo '{$private_key}' | base64 -d | tee {$customSshKeyLocation} > /dev/null",
|
||||
"chmod 600 {$customSshKeyLocation}",
|
||||
]);
|
||||
}
|
||||
$commands = $this->gitSshKeySetupCommands($deployment_uuid, $private_key, $exec_in_docker);
|
||||
if ($pull_request_id !== 0) {
|
||||
if ($git_type === 'gitlab') {
|
||||
$branch = "merge-requests/{$pull_request_id}/head:$pr_branch_name";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
$commands->push($this->gitCommand("echo 'Checking out $branch'"));
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$deployKeyGitSshCommand} git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name, $deployKeySshCommand);
|
||||
} elseif ($git_type === 'github' || $git_type === 'gitea') {
|
||||
$branch = "pull/{$pull_request_id}/head:$pr_branch_name";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
$commands->push($this->gitCommand("echo 'Checking out $branch'"));
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$deployKeyGitSshCommand} git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name, $deployKeySshCommand);
|
||||
} elseif ($git_type === 'bitbucket') {
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
$commands->push($this->gitCommand("echo 'Checking out $branch'"));
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$deployKeyGitSshCommand} ".$this->buildGitCheckoutCommand($commit, $deployKeySshCommand);
|
||||
}
|
||||
}
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $git_clone_command)));
|
||||
} else {
|
||||
$commands->push($git_clone_command);
|
||||
$commands->push($this->gitCommand($git_clone_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $commands,
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1807,37 +1796,37 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
if ($git_type === 'gitlab') {
|
||||
$branch = "merge-requests/{$pull_request_id}/head:$pr_branch_name";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
$commands->push($this->gitCommand("echo 'Checking out $branch'"));
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"{$otherSshCommand}\" {$gitCommand} fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name, $otherSshCommand, $gitConfigOptions);
|
||||
} elseif ($git_type === 'github' || $git_type === 'gitea') {
|
||||
$branch = "pull/{$pull_request_id}/head:$pr_branch_name";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
$commands->push($this->gitCommand("echo 'Checking out $branch'"));
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"{$otherSshCommand}\" {$gitCommand} fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name, $otherSshCommand, $gitConfigOptions);
|
||||
} elseif ($git_type === 'bitbucket') {
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
$commands->push($this->gitCommand("echo 'Checking out $branch'"));
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"{$otherSshCommand}\" ".$this->buildGitCheckoutCommand($commit, $otherSshCommand, $gitConfigOptions);
|
||||
}
|
||||
}
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
$commands->push($this->gitCommand(executeInDocker($deployment_uuid, $git_clone_command)));
|
||||
} else {
|
||||
$commands->push($git_clone_command);
|
||||
$commands->push($this->gitCommand($git_clone_command));
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'commands' => $this->gitCommandsAsShellCommand($commands),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
|
|
@ -1926,6 +1915,7 @@ public function loadComposeFile($isInit = false, ?string $restoreBaseDirectory =
|
|||
}
|
||||
$uuid = new_public_id();
|
||||
['commands' => $cloneCommand] = $this->generateGitImportCommands(deployment_uuid: $uuid, only_checkout: true, exec_in_docker: false, custom_base_dir: 'checkout');
|
||||
$cloneCommand = $this->gitCommandsAsShellCommand($cloneCommand);
|
||||
$cloneCommand = str_replace(' clone ', ' clone --quiet ', $cloneCommand);
|
||||
$workdir = rtrim($this->base_directory, '/');
|
||||
$composeFile = $this->docker_compose_location;
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ private function executeCommandWithProcess($command, $hidden, $customType, $appe
|
|||
}
|
||||
|
||||
$remote_command = SshMultiplexingHelper::generateSshCommand($this->server, $command);
|
||||
$process = Process::timeout(config('constants.ssh.command_timeout'))->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden, $customType, $append, $command_hidden) {
|
||||
$process = Process::timeout(config('constants.ssh.command_timeout'))->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden, $customType, $append, $command_hidden, $skip_command_log) {
|
||||
$output = str($output)->trim();
|
||||
if ($output->startsWith('╔')) {
|
||||
$output = "\n".$output;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
use App\Models\Application;
|
||||
use App\Models\Environment;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\GitlabApp;
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
|
|
@ -360,6 +361,36 @@ public static function examples(): array
|
|||
'ports_exposes' => '3000',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-github-deploy-key',
|
||||
'name' => 'Railpack GitHub Deploy Key Example',
|
||||
'git_repository' => 'git@github.com:coollabsio/coolify-examples-deploy-key.git',
|
||||
'git_branch' => 'main',
|
||||
'ports_exposes' => '80',
|
||||
'private_key_id' => 1,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-gitlab-deploy-key',
|
||||
'name' => 'Railpack GitLab Deploy Key Example',
|
||||
'git_repository' => 'git@gitlab.com:coollabsio/php-example.git',
|
||||
'git_branch' => 'main',
|
||||
'ports_exposes' => '80',
|
||||
'source_id' => 1,
|
||||
'source_type' => GitlabApp::class,
|
||||
'private_key_id' => 1,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-gitlab-public-example',
|
||||
'name' => 'Railpack GitLab Public Example',
|
||||
'git_repository' => 'https://gitlab.com/andrasbacsai/coolify-examples.git',
|
||||
'git_branch' => 'main',
|
||||
'base_directory' => '/astro/static',
|
||||
'publish_directory' => '/dist',
|
||||
'ports_exposes' => '80',
|
||||
'source_id' => 1,
|
||||
'source_type' => GitlabApp::class,
|
||||
'is_static' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -420,6 +451,7 @@ private function ensureDevelopmentPrerequisitesExist(): void
|
|||
);
|
||||
|
||||
$this->ensurePublicGithubSourceExists();
|
||||
$this->ensurePublicGitlabSourceExists();
|
||||
}
|
||||
|
||||
private function ensurePublicGithubSourceExists(): void
|
||||
|
|
@ -437,6 +469,21 @@ private function ensurePublicGithubSourceExists(): void
|
|||
);
|
||||
}
|
||||
|
||||
private function ensurePublicGitlabSourceExists(): void
|
||||
{
|
||||
GitlabApp::query()->firstOrCreate(
|
||||
['id' => 1],
|
||||
[
|
||||
'uuid' => 'gitlab-public',
|
||||
'name' => 'Public GitLab',
|
||||
'api_url' => 'https://gitlab.com/api/v4',
|
||||
'html_url' => 'https://gitlab.com',
|
||||
'is_public' => true,
|
||||
'team_id' => 0,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
private function isDevelopmentEnvironment(): bool
|
||||
{
|
||||
return in_array(config('app.env'), ['local', 'development', 'dev'], true);
|
||||
|
|
@ -479,12 +526,12 @@ private function upsertApplication(Environment $environment, StandaloneDocker $d
|
|||
'name' => $example['name'],
|
||||
'description' => $example['name'],
|
||||
'fqdn' => "http://{$example['uuid']}.127.0.0.1.sslip.io",
|
||||
'repository_project_id' => self::REPOSITORY_PROJECT_ID,
|
||||
'git_repository' => self::GIT_REPOSITORY,
|
||||
'repository_project_id' => $example['repository_project_id'] ?? self::REPOSITORY_PROJECT_ID,
|
||||
'git_repository' => $example['git_repository'] ?? self::GIT_REPOSITORY,
|
||||
'git_branch' => $example['git_branch'] ?? self::GIT_BRANCH,
|
||||
'build_pack' => 'railpack',
|
||||
'ports_exposes' => $example['ports_exposes'],
|
||||
'base_directory' => $example['base_directory'],
|
||||
'base_directory' => $example['base_directory'] ?? '/',
|
||||
'publish_directory' => $example['publish_directory'] ?? null,
|
||||
'static_image' => 'nginx:alpine',
|
||||
'install_command' => $example['install_command'] ?? null,
|
||||
|
|
@ -493,8 +540,9 @@ private function upsertApplication(Environment $environment, StandaloneDocker $d
|
|||
'environment_id' => $environment->id,
|
||||
'destination_id' => $destination->id,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
'source_id' => 0,
|
||||
'source_type' => GithubApp::class,
|
||||
'source_id' => $example['source_id'] ?? 0,
|
||||
'source_type' => $example['source_type'] ?? GithubApp::class,
|
||||
'private_key_id' => $example['private_key_id'] ?? null,
|
||||
]);
|
||||
$application->save();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use App\Models\Application;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\GitlabApp;
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
|
|
@ -42,6 +43,7 @@ function seedRailpackExamplePrerequisites(): void
|
|||
expect(Server::query()->find(0))->not->toBeNull();
|
||||
expect(StandaloneDocker::query()->find(0))->not->toBeNull();
|
||||
expect(GithubApp::query()->find(0))->not->toBeNull();
|
||||
expect(GitlabApp::query()->find(1))->not->toBeNull();
|
||||
expect(Project::query()->where('uuid', DevelopmentRailpackExamplesSeeder::PROJECT_UUID)->exists())->toBeTrue();
|
||||
expect(Application::query()->count())->toBe(count(DevelopmentRailpackExamplesSeeder::examples()));
|
||||
});
|
||||
|
|
@ -66,9 +68,10 @@ function seedRailpackExamplePrerequisites(): void
|
|||
|
||||
expect($applications)->toHaveCount(count(DevelopmentRailpackExamplesSeeder::examples()));
|
||||
expect($applications->every(fn (Application $application) => $application->build_pack === 'railpack'))->toBeTrue();
|
||||
expect($applications->every(fn (Application $application) => $application->git_repository === DevelopmentRailpackExamplesSeeder::GIT_REPOSITORY))->toBeTrue();
|
||||
|
||||
$examples = collect(DevelopmentRailpackExamplesSeeder::examples())->keyBy('uuid');
|
||||
expect($applications->every(
|
||||
fn (Application $application) => $application->git_repository === ($examples->get($application->uuid)['git_repository'] ?? DevelopmentRailpackExamplesSeeder::GIT_REPOSITORY)
|
||||
))->toBeTrue();
|
||||
expect($applications->every(
|
||||
fn (Application $application) => $application->git_branch === ($examples->get($application->uuid)['git_branch'] ?? DevelopmentRailpackExamplesSeeder::GIT_BRANCH)
|
||||
))->toBeTrue();
|
||||
|
|
@ -79,6 +82,9 @@ function seedRailpackExamplePrerequisites(): void
|
|||
$pythonFlask = $applications->firstWhere('uuid', 'railpack-python-flask');
|
||||
$goGin = $applications->firstWhere('uuid', 'railpack-go-gin');
|
||||
$rust = $applications->firstWhere('uuid', 'railpack-rust');
|
||||
$githubDeployKey = $applications->firstWhere('uuid', 'railpack-github-deploy-key');
|
||||
$gitlabDeployKey = $applications->firstWhere('uuid', 'railpack-gitlab-deploy-key');
|
||||
$gitlabPublic = $applications->firstWhere('uuid', 'railpack-gitlab-public-example');
|
||||
|
||||
expect($nestjs)
|
||||
->not->toBeNull()
|
||||
|
|
@ -113,6 +119,33 @@ function seedRailpackExamplePrerequisites(): void
|
|||
expect($rust)
|
||||
->not->toBeNull()
|
||||
->and($rust->ports_exposes)->toBe('8000');
|
||||
|
||||
expect($githubDeployKey)
|
||||
->not->toBeNull()
|
||||
->and($githubDeployKey->git_repository)->toBe('git@github.com:coollabsio/coolify-examples-deploy-key.git')
|
||||
->and($githubDeployKey->git_branch)->toBe('main')
|
||||
->and($githubDeployKey->build_pack)->toBe('railpack')
|
||||
->and($githubDeployKey->private_key_id)->toBe(1)
|
||||
->and($githubDeployKey->source_type)->toBe(GithubApp::class)
|
||||
->and($githubDeployKey->source_id)->toBe(0);
|
||||
|
||||
expect($gitlabDeployKey)
|
||||
->not->toBeNull()
|
||||
->and($gitlabDeployKey->git_repository)->toBe('git@gitlab.com:coollabsio/php-example.git')
|
||||
->and($gitlabDeployKey->git_branch)->toBe('main')
|
||||
->and($gitlabDeployKey->build_pack)->toBe('railpack')
|
||||
->and($gitlabDeployKey->private_key_id)->toBe(1)
|
||||
->and($gitlabDeployKey->source_type)->toBe(GitlabApp::class)
|
||||
->and($gitlabDeployKey->source_id)->toBe(1);
|
||||
|
||||
expect($gitlabPublic)
|
||||
->not->toBeNull()
|
||||
->and($gitlabPublic->git_repository)->toBe('https://gitlab.com/andrasbacsai/coolify-examples.git')
|
||||
->and($gitlabPublic->base_directory)->toBe('/astro/static')
|
||||
->and($gitlabPublic->publish_directory)->toBe('/dist')
|
||||
->and($gitlabPublic->build_pack)->toBe('railpack')
|
||||
->and($gitlabPublic->source_type)->toBe(GitlabApp::class)
|
||||
->and($gitlabPublic->settings->is_static)->toBeTrue();
|
||||
});
|
||||
|
||||
it('skips the railpack examples outside development mode', function () {
|
||||
|
|
|
|||
|
|
@ -4,11 +4,50 @@
|
|||
use App\Models\ApplicationSetting;
|
||||
use App\Models\GitlabApp;
|
||||
use App\Models\PrivateKey;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
afterEach(function () {
|
||||
Mockery::close();
|
||||
});
|
||||
|
||||
function commandStrings(array|Collection|string $commands): Collection
|
||||
{
|
||||
if (is_string($commands)) {
|
||||
return collect([$commands]);
|
||||
}
|
||||
|
||||
return collect($commands)->map(fn ($command) => data_get($command, 'command') ?? $command[0] ?? $command);
|
||||
}
|
||||
|
||||
function privateKeyMaterializationCommands(array|Collection|string $commands): Collection
|
||||
{
|
||||
if (is_string($commands)) {
|
||||
$commands = [$commands];
|
||||
}
|
||||
|
||||
return collect($commands)->filter(fn ($command) => str(commandStrings([$command])->first())->contains('base64 -d | tee /root/.ssh/id_rsa_coolify_'));
|
||||
}
|
||||
|
||||
function expectCommandListToContain(array|Collection|string $commands, string $expected): void
|
||||
{
|
||||
expect(commandStrings($commands)->implode(' && '))->toContain($expected);
|
||||
}
|
||||
|
||||
function expectCommandListNotToContain(array|Collection|string $commands, string $expected): void
|
||||
{
|
||||
expect(commandStrings($commands)->implode(' && '))->not->toContain($expected);
|
||||
}
|
||||
|
||||
function expectPrivateKeyMaterializationCommandsSkipLogging(array|Collection|string $commands): void
|
||||
{
|
||||
$keyCommands = privateKeyMaterializationCommands($commands);
|
||||
|
||||
expect($keyCommands)->not->toBeEmpty();
|
||||
$keyCommands->each(function ($command): void {
|
||||
expect(data_get($command, 'skip_command_log'))->toBeTrue();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Git operations authenticate with the SSH key assigned in the UI. Coolify writes that key to a
|
||||
* per-deployment path (/root/.ssh/id_rsa_coolify_<deployment_uuid>) instead of the shared
|
||||
|
|
@ -33,6 +72,7 @@
|
|||
expect($source)
|
||||
->toContain('$skip_command_log = data_get($single_command, \'skip_command_log\', false);')
|
||||
->toContain('if ($command_hidden && ! $skip_command_log && isset($this->application_deployment_queue))')
|
||||
->toContain('use ($command, $hidden, $customType, $append, $command_hidden, $skip_command_log)')
|
||||
->toContain('\'command\' => $skip_command_log || $command_hidden ? null : $this->redact_sensitive_info($command),');
|
||||
});
|
||||
|
||||
|
|
@ -48,11 +88,11 @@
|
|||
|
||||
$result = $application->generateGitLsRemoteCommands('test-deployment-uuid', false);
|
||||
|
||||
expect($result['commands'])
|
||||
->toContain("tee {$keyPath}")
|
||||
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
|
||||
->toContain("trap 'rm -f {$keyPath}' EXIT") // removed when the shell exits
|
||||
->not->toContain('tee /root/.ssh/id_rsa >'); // never overwrites the host root's own key
|
||||
expectCommandListToContain($result['commands'], "tee {$keyPath}");
|
||||
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
|
||||
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT"); // removed when the shell exits
|
||||
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >'); // never overwrites the host root's own key
|
||||
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
|
||||
});
|
||||
|
||||
it('writes a deploy key to a per-deployment path for ls-remote inside docker without a trap', function () use ($keyPath) {
|
||||
|
|
@ -67,11 +107,11 @@
|
|||
|
||||
$result = $application->generateGitLsRemoteCommands('test-deployment-uuid', true);
|
||||
|
||||
expect($result['commands'])
|
||||
->toContain("tee {$keyPath}")
|
||||
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
|
||||
->not->toContain('trap ') // ephemeral container, no cleanup needed
|
||||
->not->toContain('tee /root/.ssh/id_rsa >');
|
||||
expectCommandListToContain($result['commands'], "tee {$keyPath}");
|
||||
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
|
||||
expectCommandListNotToContain($result['commands'], 'trap '); // ephemeral container, no cleanup needed
|
||||
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
|
||||
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
|
||||
});
|
||||
|
||||
it('writes a GitLab source private key to a per-deployment path with cleanup on the host', function () use ($keyPath) {
|
||||
|
|
@ -94,11 +134,11 @@
|
|||
|
||||
$result = $application->generateGitLsRemoteCommands('test-deployment-uuid', false);
|
||||
|
||||
expect($result['commands'])
|
||||
->toContain("tee {$keyPath}")
|
||||
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
|
||||
->toContain("trap 'rm -f {$keyPath}' EXIT")
|
||||
->not->toContain('tee /root/.ssh/id_rsa >');
|
||||
expectCommandListToContain($result['commands'], "tee {$keyPath}");
|
||||
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
|
||||
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT");
|
||||
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
|
||||
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
|
||||
});
|
||||
|
||||
it('writes a deploy key to a per-deployment path and cleans it up when cloning on the host', function () use ($keyPath) {
|
||||
|
|
@ -121,11 +161,11 @@
|
|||
// exec_in_docker = false → the loadComposeFile / host clone path
|
||||
$result = $application->generateGitImportCommands('test-deployment-uuid', 0, null, false);
|
||||
|
||||
expect($result['commands'])
|
||||
->toContain("tee {$keyPath}")
|
||||
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
|
||||
->toContain("trap 'rm -f {$keyPath}' EXIT")
|
||||
->not->toContain('tee /root/.ssh/id_rsa >');
|
||||
expectCommandListToContain($result['commands'], "tee {$keyPath}");
|
||||
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
|
||||
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT");
|
||||
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
|
||||
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
|
||||
});
|
||||
|
||||
it('writes a GitLab source private key to a per-deployment path and cleans it up when cloning on the host', function () use ($keyPath) {
|
||||
|
|
@ -154,11 +194,11 @@
|
|||
|
||||
$result = $application->generateGitImportCommands('test-deployment-uuid', 0, null, false);
|
||||
|
||||
expect($result['commands'])
|
||||
->toContain("tee {$keyPath}")
|
||||
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
|
||||
->toContain("trap 'rm -f {$keyPath}' EXIT")
|
||||
->not->toContain('tee /root/.ssh/id_rsa >');
|
||||
expectCommandListToContain($result['commands'], "tee {$keyPath}");
|
||||
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
|
||||
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT");
|
||||
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
|
||||
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
|
||||
});
|
||||
|
||||
it('uses the per-deployment deploy key for pull request fetches', function () use ($keyPath) {
|
||||
|
|
@ -180,9 +220,9 @@
|
|||
|
||||
$result = $application->generateGitImportCommands('test-deployment-uuid', 123, 'github', false);
|
||||
|
||||
expect($result['commands'])
|
||||
->toContain("GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {$keyPath} -o IdentitiesOnly=yes\" git fetch origin pull/123/head:pr-123-coolify")
|
||||
->not->toContain('GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify');
|
||||
expectCommandListToContain($result['commands'], "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {$keyPath} -o IdentitiesOnly=yes\" git fetch origin pull/123/head:pr-123-coolify");
|
||||
expectCommandListNotToContain($result['commands'], 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify');
|
||||
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
|
||||
});
|
||||
|
||||
it('does not force a missing per-deployment key for other repository pull request fetches', function () use ($keyPath) {
|
||||
|
|
@ -200,7 +240,6 @@
|
|||
|
||||
$result = $application->generateGitImportCommands('test-deployment-uuid', 123, 'github', false);
|
||||
|
||||
expect($result['commands'])
|
||||
->toContain('GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify')
|
||||
->not->toContain($keyPath);
|
||||
expectCommandListToContain($result['commands'], 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify');
|
||||
expectCommandListNotToContain($result['commands'], $keyPath);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,11 +3,45 @@
|
|||
use App\Models\Application;
|
||||
use App\Models\GitlabApp;
|
||||
use App\Models\PrivateKey;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
afterEach(function () {
|
||||
Mockery::close();
|
||||
});
|
||||
|
||||
function gitlabCommandStrings(array|Collection|string $commands): Collection
|
||||
{
|
||||
if (is_string($commands)) {
|
||||
return collect([$commands]);
|
||||
}
|
||||
|
||||
return collect($commands)->map(fn ($command) => data_get($command, 'command') ?? $command[0] ?? $command);
|
||||
}
|
||||
|
||||
function expectGitlabCommandListToContain(array|Collection|string $commands, string $expected): void
|
||||
{
|
||||
expect(gitlabCommandStrings($commands)->implode(' && '))->toContain($expected);
|
||||
}
|
||||
|
||||
function expectGitlabCommandListNotToContain(array|Collection|string $commands, string $expected): void
|
||||
{
|
||||
expect(gitlabCommandStrings($commands)->implode(' && '))->not->toContain($expected);
|
||||
}
|
||||
|
||||
function expectGitlabPrivateKeyMaterializationCommandsSkipLogging(array|Collection|string $commands): void
|
||||
{
|
||||
if (is_string($commands)) {
|
||||
$commands = [$commands];
|
||||
}
|
||||
|
||||
$keyCommands = collect($commands)->filter(fn ($command) => str(data_get($command, 'command') ?? $command[0] ?? $command)->contains('base64 -d | tee /root/.ssh/id_rsa_coolify_'));
|
||||
|
||||
expect($keyCommands)->not->toBeEmpty();
|
||||
$keyCommands->each(function ($command): void {
|
||||
expect(data_get($command, 'skip_command_log'))->toBeTrue();
|
||||
});
|
||||
}
|
||||
|
||||
it('generates ls-remote commands for GitLab source with private key', function () {
|
||||
$deploymentUuid = 'test-deployment-uuid';
|
||||
|
||||
|
|
@ -15,7 +49,8 @@
|
|||
$privateKey->shouldReceive('getAttribute')->with('private_key')->andReturn('fake-private-key');
|
||||
|
||||
$gitlabSource = Mockery::mock(GitlabApp::class)->makePartial();
|
||||
$gitlabSource->shouldReceive('getMorphClass')->andReturn(\App\Models\GitlabApp::class);
|
||||
$gitlabSource->shouldReceive('getMorphClass')->andReturn(GitlabApp::class);
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('html_url')->andReturn('https://gitlab.com');
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('privateKey')->andReturn($privateKey);
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('private_key_id')->andReturn(1);
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('custom_port')->andReturn(22);
|
||||
|
|
@ -34,16 +69,18 @@
|
|||
|
||||
expect($result)->toBeArray();
|
||||
expect($result)->toHaveKey('commands');
|
||||
expect($result['commands'])->toContain('git ls-remote');
|
||||
expect($result['commands'])->toContain('id_rsa');
|
||||
expect($result['commands'])->toContain('mkdir -p /root/.ssh');
|
||||
expectGitlabCommandListToContain($result['commands'], 'git ls-remote');
|
||||
expectGitlabCommandListToContain($result['commands'], 'id_rsa');
|
||||
expectGitlabCommandListToContain($result['commands'], 'mkdir -p /root/.ssh');
|
||||
expectGitlabPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
|
||||
});
|
||||
|
||||
it('generates ls-remote commands for GitLab source without private key', function () {
|
||||
$deploymentUuid = 'test-deployment-uuid';
|
||||
|
||||
$gitlabSource = Mockery::mock(GitlabApp::class)->makePartial();
|
||||
$gitlabSource->shouldReceive('getMorphClass')->andReturn(\App\Models\GitlabApp::class);
|
||||
$gitlabSource->shouldReceive('getMorphClass')->andReturn(GitlabApp::class);
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('html_url')->andReturn('https://gitlab.com');
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('privateKey')->andReturn(null);
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('private_key_id')->andReturn(null);
|
||||
|
||||
|
|
@ -61,17 +98,18 @@
|
|||
|
||||
expect($result)->toBeArray();
|
||||
expect($result)->toHaveKey('commands');
|
||||
expect($result['commands'])->toContain('git ls-remote');
|
||||
expect($result['commands'])->toContain('https://gitlab.com/user/repo.git');
|
||||
expectGitlabCommandListToContain($result['commands'], 'git ls-remote');
|
||||
expectGitlabCommandListToContain($result['commands'], 'https://gitlab.com/user/repo.git');
|
||||
// Should NOT contain SSH key setup
|
||||
expect($result['commands'])->not->toContain('id_rsa');
|
||||
expectGitlabCommandListNotToContain($result['commands'], 'id_rsa');
|
||||
});
|
||||
|
||||
it('does not return null for GitLab source type', function () {
|
||||
$deploymentUuid = 'test-deployment-uuid';
|
||||
|
||||
$gitlabSource = Mockery::mock(GitlabApp::class)->makePartial();
|
||||
$gitlabSource->shouldReceive('getMorphClass')->andReturn(\App\Models\GitlabApp::class);
|
||||
$gitlabSource->shouldReceive('getMorphClass')->andReturn(GitlabApp::class);
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('html_url')->andReturn('https://gitlab.com');
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('privateKey')->andReturn(null);
|
||||
$gitlabSource->shouldReceive('getAttribute')->with('private_key_id')->andReturn(null);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue