2026-02-23 15:32:54 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use App\Models\Application;
|
|
|
|
|
use App\Models\ApplicationSetting;
|
|
|
|
|
|
|
|
|
|
describe('Application Rollback', function () {
|
2026-02-27 22:26:31 +00:00
|
|
|
beforeEach(function () {
|
2026-03-03 08:50:05 +00:00
|
|
|
$this->application = new Application;
|
|
|
|
|
$this->application->forceFill([
|
|
|
|
|
'uuid' => 'test-app-uuid',
|
2026-02-23 15:32:54 +00:00
|
|
|
'git_commit_sha' => 'HEAD',
|
|
|
|
|
]);
|
2026-03-03 08:50:05 +00:00
|
|
|
|
|
|
|
|
$settings = new ApplicationSetting;
|
|
|
|
|
$settings->is_git_shallow_clone_enabled = false;
|
|
|
|
|
$settings->is_git_submodules_enabled = false;
|
|
|
|
|
$settings->is_git_lfs_enabled = false;
|
|
|
|
|
$this->application->setRelation('settings', $settings);
|
2026-02-27 22:26:31 +00:00
|
|
|
});
|
2026-02-23 15:32:54 +00:00
|
|
|
|
2026-02-27 22:26:31 +00:00
|
|
|
test('setGitImportSettings uses passed commit instead of application git_commit_sha', function () {
|
2026-03-02 12:31:48 +00:00
|
|
|
$rollbackCommit = 'abc123def456abc123def456abc123def456abc1';
|
2026-02-23 15:32:54 +00:00
|
|
|
|
2026-02-27 22:26:31 +00:00
|
|
|
$result = $this->application->setGitImportSettings(
|
2026-02-23 15:32:54 +00:00
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
public: true,
|
|
|
|
|
commit: $rollbackCommit
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect($result)->toContain($rollbackCommit);
|
|
|
|
|
});
|
2026-02-27 22:26:31 +00:00
|
|
|
|
|
|
|
|
test('setGitImportSettings with shallow clone fetches specific commit', function () {
|
2026-03-03 08:50:05 +00:00
|
|
|
$this->application->settings->is_git_shallow_clone_enabled = true;
|
2026-02-27 22:26:31 +00:00
|
|
|
|
2026-03-02 12:31:48 +00:00
|
|
|
$rollbackCommit = 'abc123def456abc123def456abc123def456abc1';
|
2026-02-27 22:26:31 +00:00
|
|
|
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
public: true,
|
|
|
|
|
commit: $rollbackCommit
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect($result)
|
|
|
|
|
->toContain('git fetch --depth=1 origin')
|
|
|
|
|
->toContain($rollbackCommit);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('setGitImportSettings falls back to git_commit_sha when no commit passed', function () {
|
2026-03-03 08:50:05 +00:00
|
|
|
$this->application->git_commit_sha = 'def789abc012def789abc012def789abc012def7';
|
2026-02-27 22:26:31 +00:00
|
|
|
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
public: true,
|
|
|
|
|
);
|
|
|
|
|
|
2026-03-02 12:31:48 +00:00
|
|
|
expect($result)->toContain('def789abc012def789abc012def789abc012def7');
|
2026-02-27 22:26:31 +00:00
|
|
|
});
|
|
|
|
|
|
2026-03-03 08:05:01 +00:00
|
|
|
test('setGitImportSettings escapes shell metacharacters in commit parameter', function () {
|
|
|
|
|
$maliciousCommit = 'abc123; rm -rf /';
|
|
|
|
|
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
public: true,
|
|
|
|
|
commit: $maliciousCommit
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// escapeshellarg wraps the value in single quotes, neutralizing metacharacters
|
|
|
|
|
expect($result)
|
|
|
|
|
->toContain("checkout 'abc123; rm -rf /'")
|
|
|
|
|
->not->toContain('checkout abc123; rm -rf /');
|
|
|
|
|
});
|
|
|
|
|
|
2026-02-27 22:26:31 +00:00
|
|
|
test('setGitImportSettings does not append checkout when commit is HEAD', function () {
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
public: true,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect($result)->not->toContain('advice.detachedHead=false checkout');
|
|
|
|
|
});
|
2026-03-12 12:32:43 +00:00
|
|
|
|
|
|
|
|
test('setGitImportSettings uses provided git_ssh_command for fetch', function () {
|
|
|
|
|
$this->application->settings->is_git_shallow_clone_enabled = true;
|
|
|
|
|
$rollbackCommit = 'abc123def456abc123def456abc123def456abc1';
|
|
|
|
|
$sshCommand = 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22222 -o Port=22222 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa"';
|
|
|
|
|
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
commit: $rollbackCommit,
|
|
|
|
|
git_ssh_command: $sshCommand,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect($result)
|
|
|
|
|
->toContain('-i /root/.ssh/id_rsa" git fetch --depth=1 origin')
|
|
|
|
|
->toContain($rollbackCommit);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('setGitImportSettings uses provided git_ssh_command for submodule update', function () {
|
|
|
|
|
$this->application->settings->is_git_submodules_enabled = true;
|
|
|
|
|
$sshCommand = '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"';
|
|
|
|
|
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
git_ssh_command: $sshCommand,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect($result)
|
|
|
|
|
->toContain('-i /root/.ssh/id_rsa" git submodule update --init --recursive');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('setGitImportSettings uses provided git_ssh_command for lfs pull', function () {
|
|
|
|
|
$this->application->settings->is_git_lfs_enabled = true;
|
|
|
|
|
$sshCommand = '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"';
|
|
|
|
|
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
git_ssh_command: $sshCommand,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect($result)->toContain('-i /root/.ssh/id_rsa" git lfs pull');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('setGitImportSettings uses default ssh command when git_ssh_command not provided', function () {
|
|
|
|
|
$this->application->settings->is_git_lfs_enabled = true;
|
|
|
|
|
|
|
|
|
|
$result = $this->application->setGitImportSettings(
|
|
|
|
|
deployment_uuid: 'test-uuid',
|
|
|
|
|
git_clone_command: 'git clone',
|
|
|
|
|
public: true,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect($result)
|
|
|
|
|
->toContain('GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" git lfs pull')
|
|
|
|
|
->not->toContain('-i /root/.ssh/id_rsa');
|
|
|
|
|
});
|
2026-02-23 15:32:54 +00:00
|
|
|
});
|