Fix: application rollback uses correct commit sha (#8576)
This commit is contained in:
commit
338fa1b45b
21 changed files with 842 additions and 596 deletions
|
|
@ -1087,19 +1087,24 @@ public function dirOnServer()
|
|||
return application_configuration_dir()."/{$this->uuid}";
|
||||
}
|
||||
|
||||
public function setGitImportSettings(string $deployment_uuid, string $git_clone_command, bool $public = false)
|
||||
public function setGitImportSettings(string $deployment_uuid, string $git_clone_command, bool $public = false, ?string $commit = null)
|
||||
{
|
||||
$baseDir = $this->generateBaseDir($deployment_uuid);
|
||||
$escapedBaseDir = escapeshellarg($baseDir);
|
||||
$isShallowCloneEnabled = $this->settings?->is_git_shallow_clone_enabled ?? false;
|
||||
|
||||
if ($this->git_commit_sha !== 'HEAD') {
|
||||
// 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;
|
||||
|
||||
if ($commitToUse !== 'HEAD') {
|
||||
$escapedCommit = escapeshellarg($commitToUse);
|
||||
// If shallow clone is enabled and we need a specific commit,
|
||||
// we need to fetch that specific commit with depth=1
|
||||
if ($isShallowCloneEnabled) {
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git fetch --depth=1 origin {$this->git_commit_sha} && git -c advice.detachedHead=false checkout {$this->git_commit_sha} >/dev/null 2>&1";
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git fetch --depth=1 origin {$escapedCommit} && git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1";
|
||||
} else {
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git -c advice.detachedHead=false checkout {$this->git_commit_sha} >/dev/null 2>&1";
|
||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1";
|
||||
}
|
||||
}
|
||||
if ($this->settings->is_git_submodules_enabled) {
|
||||
|
|
@ -1287,7 +1292,7 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
$escapedRepoUrl = escapeshellarg("{$this->source->html_url}/{$customRepository}");
|
||||
$git_clone_command = "{$git_clone_command} {$escapedRepoUrl} {$escapedBaseDir}";
|
||||
if (! $only_checkout) {
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true);
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true, commit: $commit);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
|
|
@ -1308,7 +1313,7 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
$fullRepoUrl = $repoUrl;
|
||||
}
|
||||
if (! $only_checkout) {
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: false);
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: false, commit: $commit);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
|
|
@ -1347,7 +1352,7 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
if ($only_checkout) {
|
||||
$git_clone_command = $git_clone_command_base;
|
||||
} else {
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base);
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
$commands = collect([
|
||||
|
|
@ -1405,7 +1410,7 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
|||
$fullRepoUrl = $customRepository;
|
||||
$escapedCustomRepository = escapeshellarg($customRepository);
|
||||
$git_clone_command = "{$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}";
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true);
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true, commit: $commit);
|
||||
|
||||
if ($pull_request_id !== 0) {
|
||||
if ($git_type === 'gitlab') {
|
||||
|
|
@ -1961,7 +1966,6 @@ public function parseHealthcheckFromDockerfile($dockerfile, bool $isInit = false
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public function getLimits(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use App\Traits\ClearsGlobalSearchCache;
|
||||
use App\Traits\HasSafeStringAttribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
#[OA\Schema(
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
class Environment extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache;
|
||||
use HasFactory;
|
||||
use HasSafeStringAttribute;
|
||||
|
||||
protected $guarded = [];
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use App\Traits\ClearsGlobalSearchCache;
|
||||
use App\Traits\HasSafeStringAttribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
class Project extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache;
|
||||
use HasFactory;
|
||||
use HasSafeStringAttribute;
|
||||
|
||||
protected $guarded = [];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Traits\HasSafeStringAttribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
|
@ -25,6 +26,7 @@
|
|||
)]
|
||||
class ScheduledTask extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
use HasSafeStringAttribute;
|
||||
|
||||
protected $guarded = [];
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@
|
|||
|
||||
use App\Jobs\ConnectProxyToNetworksJob;
|
||||
use App\Traits\HasSafeStringAttribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class StandaloneDocker extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
use HasSafeStringAttribute;
|
||||
|
||||
protected $guarded = [];
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
"stevebauman/purify": "^6.3.1",
|
||||
"stripe/stripe-php": "^16.6.0",
|
||||
"symfony/yaml": "^7.4.1",
|
||||
"visus/cuid2": "^4.1.0",
|
||||
"visus/cuid2": "^6.0.0",
|
||||
"yosymfony/toml": "^1.0.4",
|
||||
"zircote/swagger-php": "^5.8.0"
|
||||
},
|
||||
|
|
|
|||
1195
composer.lock
generated
1195
composer.lock
generated
File diff suppressed because it is too large
Load diff
16
database/factories/EnvironmentFactory.php
Normal file
16
database/factories/EnvironmentFactory.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class EnvironmentFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => fake()->unique()->word(),
|
||||
'project_id' => 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
16
database/factories/ProjectFactory.php
Normal file
16
database/factories/ProjectFactory.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class ProjectFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => fake()->unique()->company(),
|
||||
'team_id' => 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
19
database/factories/ServiceFactory.php
Normal file
19
database/factories/ServiceFactory.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class ServiceFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => fake()->unique()->word(),
|
||||
'destination_type' => \App\Models\StandaloneDocker::class,
|
||||
'destination_id' => 1,
|
||||
'environment_id' => 1,
|
||||
'docker_compose_raw' => 'version: "3"',
|
||||
];
|
||||
}
|
||||
}
|
||||
18
database/factories/StandaloneDockerFactory.php
Normal file
18
database/factories/StandaloneDockerFactory.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class StandaloneDockerFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'uuid' => fake()->uuid(),
|
||||
'name' => fake()->unique()->word(),
|
||||
'network' => 'coolify',
|
||||
'server_id' => 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
88
tests/Feature/ApplicationRollbackTest.php
Normal file
88
tests/Feature/ApplicationRollbackTest.php
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationSetting;
|
||||
|
||||
describe('Application Rollback', function () {
|
||||
beforeEach(function () {
|
||||
$this->application = new Application;
|
||||
$this->application->forceFill([
|
||||
'uuid' => 'test-app-uuid',
|
||||
'git_commit_sha' => 'HEAD',
|
||||
]);
|
||||
|
||||
$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);
|
||||
});
|
||||
|
||||
test('setGitImportSettings uses passed commit instead of application git_commit_sha', function () {
|
||||
$rollbackCommit = 'abc123def456abc123def456abc123def456abc1';
|
||||
|
||||
$result = $this->application->setGitImportSettings(
|
||||
deployment_uuid: 'test-uuid',
|
||||
git_clone_command: 'git clone',
|
||||
public: true,
|
||||
commit: $rollbackCommit
|
||||
);
|
||||
|
||||
expect($result)->toContain($rollbackCommit);
|
||||
});
|
||||
|
||||
test('setGitImportSettings with shallow clone fetches specific commit', function () {
|
||||
$this->application->settings->is_git_shallow_clone_enabled = true;
|
||||
|
||||
$rollbackCommit = 'abc123def456abc123def456abc123def456abc1';
|
||||
|
||||
$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 () {
|
||||
$this->application->git_commit_sha = 'def789abc012def789abc012def789abc012def7';
|
||||
|
||||
$result = $this->application->setGitImportSettings(
|
||||
deployment_uuid: 'test-uuid',
|
||||
git_clone_command: 'git clone',
|
||||
public: true,
|
||||
);
|
||||
|
||||
expect($result)->toContain('def789abc012def789abc012def789abc012def7');
|
||||
});
|
||||
|
||||
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 /');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use App\Models\Application;
|
||||
use App\Models\Environment;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Project;
|
||||
use App\Models\ScheduledTask;
|
||||
use App\Models\ScheduledTaskExecution;
|
||||
|
|
@ -15,6 +16,9 @@
|
|||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
// ApiAllowed middleware requires InstanceSettings with id=0
|
||||
InstanceSettings::create(['id' => 0, 'is_api_enabled' => true]);
|
||||
|
||||
$this->team = Team::factory()->create();
|
||||
$this->user = User::factory()->create();
|
||||
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
|
||||
|
|
@ -25,12 +29,14 @@
|
|||
$this->bearerToken = $this->token->plainTextToken;
|
||||
|
||||
$this->server = Server::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->destination = StandaloneDocker::factory()->create(['server_id' => $this->server->id]);
|
||||
// Server::booted() auto-creates a StandaloneDocker, reuse it
|
||||
$this->destination = StandaloneDocker::where('server_id', $this->server->id)->first();
|
||||
// Project::booted() auto-creates a 'production' Environment, reuse it
|
||||
$this->project = Project::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
||||
$this->environment = $this->project->environments()->first();
|
||||
});
|
||||
|
||||
function authHeaders($bearerToken): array
|
||||
function scheduledTaskAuthHeaders($bearerToken): array
|
||||
{
|
||||
return [
|
||||
'Authorization' => 'Bearer '.$bearerToken,
|
||||
|
|
@ -46,7 +52,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->getJson("/api/v1/applications/{$application->uuid}/scheduled-tasks");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
|
@ -66,7 +72,7 @@ function authHeaders($bearerToken): array
|
|||
'name' => 'Test Task',
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->getJson("/api/v1/applications/{$application->uuid}/scheduled-tasks");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
|
@ -75,7 +81,7 @@ function authHeaders($bearerToken): array
|
|||
});
|
||||
|
||||
test('returns 404 for unknown application uuid', function () {
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->getJson('/api/v1/applications/nonexistent-uuid/scheduled-tasks');
|
||||
|
||||
$response->assertStatus(404);
|
||||
|
|
@ -90,7 +96,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->postJson("/api/v1/applications/{$application->uuid}/scheduled-tasks", [
|
||||
'name' => 'Backup',
|
||||
'command' => 'php artisan backup',
|
||||
|
|
@ -116,7 +122,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->postJson("/api/v1/applications/{$application->uuid}/scheduled-tasks", [
|
||||
'command' => 'echo test',
|
||||
'frequency' => '* * * * *',
|
||||
|
|
@ -132,7 +138,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->postJson("/api/v1/applications/{$application->uuid}/scheduled-tasks", [
|
||||
'name' => 'Test',
|
||||
'command' => 'echo test',
|
||||
|
|
@ -150,7 +156,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->postJson("/api/v1/applications/{$application->uuid}/scheduled-tasks", [
|
||||
'name' => 'Test',
|
||||
'command' => 'echo test',
|
||||
|
|
@ -168,7 +174,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->postJson("/api/v1/applications/{$application->uuid}/scheduled-tasks", [
|
||||
'name' => 'Test',
|
||||
'command' => 'echo test',
|
||||
|
|
@ -199,7 +205,7 @@ function authHeaders($bearerToken): array
|
|||
'name' => 'Old Name',
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->patchJson("/api/v1/applications/{$application->uuid}/scheduled-tasks/{$task->uuid}", [
|
||||
'name' => 'New Name',
|
||||
]);
|
||||
|
|
@ -215,7 +221,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->patchJson("/api/v1/applications/{$application->uuid}/scheduled-tasks/nonexistent", [
|
||||
'name' => 'Test',
|
||||
]);
|
||||
|
|
@ -237,7 +243,7 @@ function authHeaders($bearerToken): array
|
|||
'team_id' => $this->team->id,
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->deleteJson("/api/v1/applications/{$application->uuid}/scheduled-tasks/{$task->uuid}");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
|
@ -253,7 +259,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->deleteJson("/api/v1/applications/{$application->uuid}/scheduled-tasks/nonexistent");
|
||||
|
||||
$response->assertStatus(404);
|
||||
|
|
@ -279,7 +285,7 @@ function authHeaders($bearerToken): array
|
|||
'message' => 'OK',
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->getJson("/api/v1/applications/{$application->uuid}/scheduled-tasks/{$task->uuid}/executions");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
|
@ -294,7 +300,7 @@ function authHeaders($bearerToken): array
|
|||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->getJson("/api/v1/applications/{$application->uuid}/scheduled-tasks/nonexistent/executions");
|
||||
|
||||
$response->assertStatus(404);
|
||||
|
|
@ -316,7 +322,7 @@ function authHeaders($bearerToken): array
|
|||
'name' => 'Service Task',
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->getJson("/api/v1/services/{$service->uuid}/scheduled-tasks");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
|
@ -332,7 +338,7 @@ function authHeaders($bearerToken): array
|
|||
'environment_id' => $this->environment->id,
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->postJson("/api/v1/services/{$service->uuid}/scheduled-tasks", [
|
||||
'name' => 'Service Backup',
|
||||
'command' => 'pg_dump',
|
||||
|
|
@ -356,7 +362,7 @@ function authHeaders($bearerToken): array
|
|||
'team_id' => $this->team->id,
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders($this->bearerToken))
|
||||
$response = $this->withHeaders(scheduledTaskAuthHeaders($this->bearerToken))
|
||||
->deleteJson("/api/v1/services/{$service->uuid}/scheduled-tasks/{$task->uuid}");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
use App\Models\Application;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Mockery;
|
||||
|
||||
/**
|
||||
* Unit test to verify docker_compose_raw is properly synced to the Livewire component
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
use App\Models\Application;
|
||||
use App\Models\EnvironmentVariable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Mockery;
|
||||
|
||||
beforeEach(function () {
|
||||
// Clean up Mockery after each test
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Application;
|
||||
use Mockery;
|
||||
|
||||
/**
|
||||
* Unit tests to verify that containers without health checks are not
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\ApplicationSetting;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Mockery;
|
||||
|
||||
beforeEach(function () {
|
||||
Mockery::close();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Notifications\Server\HetznerDeletionFailed;
|
||||
use Mockery;
|
||||
|
||||
afterEach(function () {
|
||||
Mockery::close();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
use App\Models\Server;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Mockery;
|
||||
|
||||
beforeEach(function () {
|
||||
Queue::fake();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
use App\Enums\ProxyTypes;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Mockery;
|
||||
|
||||
it('filters servers by proxy type using whereProxyType scope', function () {
|
||||
// Mock the Builder
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use Mockery;
|
||||
|
||||
it('returns required port from service template', function () {
|
||||
// Mock get_service_templates() function
|
||||
|
|
|
|||
Loading…
Reference in a new issue