commit
09bcd693f5
@ -10,4 +10,5 @@ enum ProcessStatus: string
|
||||
case ERROR = 'error';
|
||||
case KILLED = 'killed';
|
||||
case CANCELLED = 'cancelled';
|
||||
case CLOSED = 'closed';
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Enums\ApplicationDeploymentStatus;
|
||||
use App\Enums\ProxyTypes;
|
||||
use App\Enums\ProcessStatus;
|
||||
use App\Events\ApplicationStatusChanged;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
@ -158,6 +158,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->preview->fqdn = $preview_fqdn;
|
||||
$this->preview->save();
|
||||
}
|
||||
if ($this->application->is_github_based()) {
|
||||
ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::IN_PROGRESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,6 +232,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
||||
$this->application->isConfigurationChanged(false);
|
||||
return;
|
||||
} else if ($this->pull_request_id !== 0) {
|
||||
$this->deploy_pull_request();
|
||||
} else if ($this->application->dockerfile) {
|
||||
$this->deploy_simple_dockerfile();
|
||||
} else if ($this->application->build_pack === 'dockercompose') {
|
||||
@ -240,11 +245,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
} else if ($this->application->build_pack === 'static') {
|
||||
$this->deploy_static_buildpack();
|
||||
} else {
|
||||
if ($this->pull_request_id !== 0) {
|
||||
$this->deploy_pull_request();
|
||||
} else {
|
||||
$this->deploy_nixpacks_buildpack();
|
||||
}
|
||||
$this->deploy_nixpacks_buildpack();
|
||||
}
|
||||
if ($this->server->isProxyShouldRun()) {
|
||||
dispatch(new ContainerStatusJob($this->server));
|
||||
@ -254,8 +255,17 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->push_to_docker_registry();
|
||||
}
|
||||
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
||||
if ($this->pull_request_id !== 0) {
|
||||
if ($this->application->is_github_based()) {
|
||||
ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::FINISHED);
|
||||
}
|
||||
}
|
||||
$this->application->isConfigurationChanged(true);
|
||||
} catch (Exception $e) {
|
||||
if ($this->pull_request_id !== 0 && $this->application->is_github_based()) {
|
||||
ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::ERROR);
|
||||
}
|
||||
ray($e);
|
||||
$this->fail($e);
|
||||
throw $e;
|
||||
} finally {
|
||||
@ -679,7 +689,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
if ($this->full_healthcheck_url) {
|
||||
$this->application_deployment_queue->addLogEntry("Healthcheck URL (inside the container): {$this->full_healthcheck_url}");
|
||||
}
|
||||
while ($counter < $this->application->health_check_retries) {
|
||||
while ($counter <= $this->application->health_check_retries) {
|
||||
$this->execute_remote_command(
|
||||
[
|
||||
"docker inspect --format='{{json .State.Health.Status}}' {$this->container_name}",
|
||||
@ -722,10 +732,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->generate_nixpacks_confs();
|
||||
}
|
||||
$this->generate_compose_file();
|
||||
|
||||
// Needs separate preview variables
|
||||
$this->generate_build_env_variables();
|
||||
if ($this->application->build_pack !== 'nixpacks') {
|
||||
if ($this->application->build_pack === 'dockerfile') {
|
||||
$this->add_build_env_variables_to_dockerfile();
|
||||
}
|
||||
$this->build_image();
|
||||
@ -861,7 +869,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
|
||||
private function generate_git_import_commands()
|
||||
{
|
||||
['commands' => $commands, 'branch' => $this->branch, 'fullRepoUrl' => $this->fullRepoUrl] = $this->application->generateGitImportCommands($this->deployment_uuid, $this->pull_request_id, $this->git_type);
|
||||
['commands' => $commands, 'branch' => $this->branch, 'fullRepoUrl' => $this->fullRepoUrl] = $this->application->generateGitImportCommands(
|
||||
deployment_uuid: $this->deployment_uuid,
|
||||
pull_request_id: $this->pull_request_id,
|
||||
git_type: $this->git_type,
|
||||
commit: $this->commit
|
||||
);
|
||||
return $commands;
|
||||
}
|
||||
|
||||
@ -1489,13 +1502,13 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
|
||||
private function next(string $status)
|
||||
{
|
||||
queue_next_deployment($this->application);
|
||||
// If the deployment is cancelled by the user, don't update the status
|
||||
if ($this->application_deployment_queue->status !== ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
|
||||
if ($this->application_deployment_queue->status !== ApplicationDeploymentStatus::CANCELLED_BY_USER->value && $this->application_deployment_queue->status !== ApplicationDeploymentStatus::FAILED->value) {
|
||||
$this->application_deployment_queue->update([
|
||||
'status' => $status,
|
||||
]);
|
||||
}
|
||||
queue_next_deployment($this->application);
|
||||
if ($status === ApplicationDeploymentStatus::FINISHED->value) {
|
||||
$this->application->environment->project->team?->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview));
|
||||
}
|
||||
@ -1507,7 +1520,9 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
public function failed(Throwable $exception): void
|
||||
{
|
||||
$this->application_deployment_queue->addLogEntry("Oops something is not okay, are you okay? 😢", 'stderr');
|
||||
$this->application_deployment_queue->addLogEntry($exception->getMessage(), 'stderr');
|
||||
if (str($exception->getMessage())->isNotEmpty()) {
|
||||
$this->application_deployment_queue->addLogEntry($exception->getMessage(), 'stderr');
|
||||
}
|
||||
|
||||
if ($this->application->build_pack !== 'dockercompose') {
|
||||
$this->application_deployment_queue->addLogEntry("Deployment failed. Removing the new version of your application.", 'stderr');
|
||||
|
@ -17,38 +17,34 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public string $build_logs_url;
|
||||
public Application $application;
|
||||
public ApplicationPreview $preview;
|
||||
public string $body;
|
||||
|
||||
public function __construct(
|
||||
public string $application_id,
|
||||
public int $pull_request_id,
|
||||
public string $deployment_uuid,
|
||||
public string $status
|
||||
public Application $application,
|
||||
public ApplicationPreview $preview,
|
||||
public ProcessStatus $status,
|
||||
public ?string $deployment_uuid = null
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
$this->application = Application::findOrFail($this->application_id);
|
||||
$this->preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id);
|
||||
|
||||
$this->build_logs_url = base_url() . "/project/{$this->application->environment->project->uuid}/{$this->application->environment->name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
|
||||
|
||||
if ($this->status === ProcessStatus::IN_PROGRESS->value) {
|
||||
if ($this->status === ProcessStatus::CLOSED) {
|
||||
$this->delete_comment();
|
||||
return;
|
||||
} else if ($this->status === ProcessStatus::IN_PROGRESS) {
|
||||
$this->body = "The preview deployment is in progress. 🟡\n\n";
|
||||
}
|
||||
if ($this->status === ProcessStatus::FINISHED->value) {
|
||||
} else if ($this->status === ProcessStatus::FINISHED) {
|
||||
$this->body = "The preview deployment is ready. 🟢\n\n";
|
||||
if ($this->preview->fqdn) {
|
||||
$this->body .= "[Open Preview]({$this->preview->fqdn}) | ";
|
||||
}
|
||||
}
|
||||
if ($this->status === ProcessStatus::ERROR->value) {
|
||||
} else if ($this->status === ProcessStatus::ERROR) {
|
||||
$this->body = "The preview deployment failed. 🔴\n\n";
|
||||
}
|
||||
$this->build_logs_url = base_url() . "/project/{$this->application->environment->project->uuid}/{$this->application->environment->name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
|
||||
|
||||
$this->body .= "[Open Build Logs](" . $this->build_logs_url . ")\n\n\n";
|
||||
$this->body .= "Last updated at: " . now()->toDateTimeString() . " CET";
|
||||
|
||||
@ -77,10 +73,14 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted
|
||||
|
||||
private function create_comment()
|
||||
{
|
||||
['data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/{$this->pull_request_id}/comments", method: 'post', data: [
|
||||
['data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/{$this->preview->pull_request_id}/comments", method: 'post', data: [
|
||||
'body' => $this->body,
|
||||
]);
|
||||
$this->preview->pull_request_issue_comment_id = $data['id'];
|
||||
$this->preview->save();
|
||||
}
|
||||
private function delete_comment()
|
||||
{
|
||||
githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'delete');
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,35 @@
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class Dashboard extends Component
|
||||
{
|
||||
public $projects = [];
|
||||
public $servers = [];
|
||||
public Collection $servers;
|
||||
public $deployments_per_server;
|
||||
public function mount()
|
||||
{
|
||||
$this->servers = Server::ownedByCurrentTeam()->get();
|
||||
$this->projects = Project::ownedByCurrentTeam()->get();
|
||||
$this->get_deployments();
|
||||
}
|
||||
public function get_deployments()
|
||||
{
|
||||
$this->deployments_per_server = ApplicationDeploymentQueue::whereIn("status", ["in_progress", "queued"])->whereIn("server_id", $this->servers->pluck("id"))->get([
|
||||
"id",
|
||||
"application_id",
|
||||
"application_name",
|
||||
"deployment_url",
|
||||
"pull_request_id",
|
||||
"server_name",
|
||||
"server_id",
|
||||
"status"
|
||||
])->sortBy('id')->groupBy('server_name')->toArray();
|
||||
}
|
||||
// public function getIptables()
|
||||
// {
|
||||
|
@ -15,6 +15,7 @@ class Index extends Component
|
||||
public int $skip = 0;
|
||||
public int $default_take = 40;
|
||||
public bool $show_next = false;
|
||||
public bool $show_prev = false;
|
||||
public ?string $pull_request_id = null;
|
||||
protected $queryString = ['pull_request_id'];
|
||||
public function mount()
|
||||
@ -60,15 +61,30 @@ class Index extends Component
|
||||
{
|
||||
$this->load_deployments();
|
||||
}
|
||||
public function previous_page(?int $take = null)
|
||||
{
|
||||
|
||||
public function load_deployments(int|null $take = null)
|
||||
if ($take) {
|
||||
$this->skip = $this->skip - $take;
|
||||
}
|
||||
$this->skip = $this->skip - $this->default_take;
|
||||
if ($this->skip < 0) {
|
||||
$this->show_prev = false;
|
||||
$this->skip = 0;
|
||||
}
|
||||
$this->load_deployments();
|
||||
}
|
||||
public function next_page(?int $take = null)
|
||||
{
|
||||
if ($take) {
|
||||
$this->skip = $this->skip + $take;
|
||||
}
|
||||
$take = $this->default_take;
|
||||
|
||||
['deployments' => $deployments, 'count' => $count] = $this->application->deployments($this->skip, $take);
|
||||
$this->show_prev = true;
|
||||
$this->load_deployments();
|
||||
}
|
||||
public function load_deployments()
|
||||
{
|
||||
['deployments' => $deployments, 'count' => $count] = $this->application->deployments($this->skip, $this->default_take);
|
||||
$this->deployments = $deployments;
|
||||
$this->deployments_count = $count;
|
||||
$this->show_pull_request_only();
|
||||
|
@ -54,8 +54,7 @@ class Heading extends Component
|
||||
}
|
||||
$this->setDeploymentUuid();
|
||||
queue_application_deployment(
|
||||
application_id: $this->application->id,
|
||||
server_id: $this->application->destination->server->id,
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
force_rebuild: false,
|
||||
is_new_deployment: true,
|
||||
@ -83,8 +82,7 @@ class Heading extends Component
|
||||
}
|
||||
$this->setDeploymentUuid();
|
||||
queue_application_deployment(
|
||||
application_id: $this->application->id,
|
||||
server_id: $this->application->destination->server->id,
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
force_rebuild: $force_rebuild,
|
||||
);
|
||||
@ -113,8 +111,7 @@ class Heading extends Component
|
||||
{
|
||||
$this->setDeploymentUuid();
|
||||
queue_application_deployment(
|
||||
application_id: $this->application->id,
|
||||
server_id: $this->application->destination->server->id,
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
restart_only: true,
|
||||
is_new_deployment: true,
|
||||
@ -130,8 +127,7 @@ class Heading extends Component
|
||||
{
|
||||
$this->setDeploymentUuid();
|
||||
queue_application_deployment(
|
||||
application_id: $this->application->id,
|
||||
server_id: $this->application->destination->server->id,
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
restart_only: true,
|
||||
);
|
||||
|
@ -47,8 +47,7 @@ class Previews extends Component
|
||||
]);
|
||||
}
|
||||
queue_application_deployment(
|
||||
application_id: $this->application->id,
|
||||
server_id: $this->application->destination->server->id,
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deployment_uuid,
|
||||
force_rebuild: false,
|
||||
pull_request_id: $pull_request_id,
|
||||
|
@ -24,8 +24,7 @@ class Rollback extends Component
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
|
||||
queue_application_deployment(
|
||||
application_id: $this->application->id,
|
||||
server_id: $this->application->destination->server->id,
|
||||
application: $this->application,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
commit: $commit,
|
||||
force_rebuild: false,
|
||||
|
@ -10,9 +10,11 @@ class Webhooks extends Component
|
||||
public ?string $deploywebhook = null;
|
||||
public ?string $githubManualWebhook = null;
|
||||
public ?string $gitlabManualWebhook = null;
|
||||
public ?string $bitbucketManualWebhook = null;
|
||||
protected $rules = [
|
||||
'resource.manual_webhook_secret_github' => 'nullable|string',
|
||||
'resource.manual_webhook_secret_gitlab' => 'nullable|string',
|
||||
'resource.manual_webhook_secret_bitbucket' => 'nullable|string',
|
||||
];
|
||||
public function saveSecret()
|
||||
{
|
||||
@ -29,6 +31,7 @@ class Webhooks extends Component
|
||||
$this->deploywebhook = generateDeployWebhook($this->resource);
|
||||
$this->githubManualWebhook = generateGitManualWebhook($this->resource, 'github');
|
||||
$this->gitlabManualWebhook = generateGitManualWebhook($this->resource, 'gitlab');
|
||||
$this->bitbucketManualWebhook = generateGitManualWebhook($this->resource, 'bitbucket');
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
|
@ -111,6 +111,13 @@ class Application extends BaseModel
|
||||
}
|
||||
// End of build packs / deployment types
|
||||
|
||||
public function is_github_based(): bool
|
||||
{
|
||||
if (data_get($this, 'source')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public function link()
|
||||
{
|
||||
if (data_get($this, 'environment.project.uuid')) {
|
||||
@ -807,7 +814,7 @@ class Application extends BaseModel
|
||||
}
|
||||
return $git_clone_command;
|
||||
}
|
||||
function generateGitImportCommands(string $deployment_uuid, int $pull_request_id = 0, ?string $git_type = null, bool $exec_in_docker = true, bool $only_checkout = false, ?string $custom_base_dir = null)
|
||||
function generateGitImportCommands(string $deployment_uuid, int $pull_request_id = 0, ?string $git_type = null, bool $exec_in_docker = true, bool $only_checkout = false, ?string $custom_base_dir = null, ?string $commit = null)
|
||||
{
|
||||
$branch = $this->git_branch;
|
||||
['repository' => $customRepository, 'port' => $customPort] = $this->customRepository();
|
||||
@ -820,7 +827,6 @@ class Application extends BaseModel
|
||||
if ($pull_request_id !== 0) {
|
||||
$pr_branch_name = "pr-{$pull_request_id}-coolify";
|
||||
}
|
||||
|
||||
if ($this->deploymentType() === 'source') {
|
||||
$source_html_url = data_get($this, 'source.html_url');
|
||||
$url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL));
|
||||
@ -926,6 +932,34 @@ class Application extends BaseModel
|
||||
$fullRepoUrl = $customRepository;
|
||||
$git_clone_command = "{$git_clone_command} {$customRepository} {$baseDir}";
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command);
|
||||
|
||||
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'"));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && git checkout $pr_branch_name";
|
||||
} else if ($git_type === 'github') {
|
||||
$branch = "pull/{$pull_request_id}/head:$pr_branch_name";
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && git checkout $pr_branch_name";
|
||||
} else if ($git_type === 'bitbucket') {
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'"));
|
||||
} else {
|
||||
$commands->push("echo 'Checking out $branch'");
|
||||
}
|
||||
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git checkout $commit";
|
||||
}
|
||||
}
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $git_clone_command));
|
||||
} else {
|
||||
|
@ -38,7 +38,7 @@ class DeploymentFailed extends Notification implements ShouldQueue
|
||||
if (Str::of($this->fqdn)->explode(',')->count() > 1) {
|
||||
$this->fqdn = Str::of($this->fqdn)->explode(',')->first();
|
||||
}
|
||||
$this->deployment_url = base_url() . "/project/{$this->project_uuid}/{$this->environment_name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
|
||||
$this->deployment_url = base_url() . "/project/{$this->project_uuid}/" . urlencode($this->environment_name) . "/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
|
||||
}
|
||||
|
||||
public function via(object $notifiable): array
|
||||
|
@ -38,7 +38,7 @@ class DeploymentSuccess extends Notification implements ShouldQueue
|
||||
if (Str::of($this->fqdn)->explode(',')->count() > 1) {
|
||||
$this->fqdn = Str::of($this->fqdn)->explode(',')->first();
|
||||
}
|
||||
$this->deployment_url = base_url() . "/project/{$this->project_uuid}/{$this->environment_name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
|
||||
$this->deployment_url = base_url() . "/project/{$this->project_uuid}/" . urlencode($this->environment_name) . "/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
|
||||
}
|
||||
|
||||
public function via(object $notifiable): array
|
||||
|
@ -31,7 +31,7 @@ class StatusChanged extends Notification implements ShouldQueue
|
||||
if (Str::of($this->fqdn)->explode(',')->count() > 1) {
|
||||
$this->fqdn = Str::of($this->fqdn)->explode(',')->first();
|
||||
}
|
||||
$this->resource_url = base_url() . "/project/{$this->project_uuid}/{$this->environment_name}/application/{$this->resource->uuid}";
|
||||
$this->resource_url = base_url() . "/project/{$this->project_uuid}/" . urlencode($this->environment_name) . "/application/{$this->resource->uuid}";
|
||||
}
|
||||
|
||||
public function via(object $notifiable): array
|
||||
|
@ -6,15 +6,23 @@ use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\Server;
|
||||
use Spatie\Url\Url;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
function queue_application_deployment(int $application_id, int $server_id, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $is_new_deployment = false)
|
||||
function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $is_new_deployment = false)
|
||||
{
|
||||
$server = Application::find($application_id)->destination->server;
|
||||
$application_id = $application->id;
|
||||
$deployment_link = Url::fromString($application->link() . "/deployment/{$deployment_uuid}");
|
||||
$deployment_url = $deployment_link->getPath();
|
||||
$server_id = $application->destination->server->id;
|
||||
$server_name = $application->destination->server->name;
|
||||
$deployment = ApplicationDeploymentQueue::create([
|
||||
'application_id' => $application_id,
|
||||
'application_name' => $application->name,
|
||||
'server_id' => $server_id,
|
||||
'server_name' => $server_name,
|
||||
'deployment_uuid' => $deployment_uuid,
|
||||
'deployment_url' => $deployment_url,
|
||||
'pull_request_id' => $pull_request_id,
|
||||
'force_rebuild' => $force_rebuild,
|
||||
'is_webhook' => $is_webhook,
|
||||
@ -22,26 +30,21 @@ function queue_application_deployment(int $application_id, int $server_id, strin
|
||||
'commit' => $commit,
|
||||
'git_type' => $git_type
|
||||
]);
|
||||
$deployments_per_server = ApplicationDeploymentQueue::where('server_id', $server_id)->whereIn('status', ['in_progress', 'queued'])->get();
|
||||
|
||||
$deployments = ApplicationDeploymentQueue::where('application_id', $application_id)->where('server_id', $server_id);
|
||||
$queued_deployments = $deployments->where('status', 'queued')->get()->sortByDesc('created_at');
|
||||
$running_deployments = $deployments->where('status', 'in_progress')->get()->sortByDesc('created_at');
|
||||
|
||||
ray("serverId:{$server->id}", "concurrentBuilds:{$server->settings->concurrent_builds}", "deployments:{$deployments_per_server->count()}", "queued:{$queued_deployments->count()}", "running:{$running_deployments->count()}");
|
||||
// ray('Q:' . $queued_deployments->count() . 'R:' . $running_deployments->count() . '| Queuing deployment: ' . $deployment_uuid . ' of applicationID: ' . $application_id . ' pull request: ' . $pull_request_id . ' with commit: ' . $commit . ' and is it forced: ' . $force_rebuild);
|
||||
|
||||
if ($queued_deployments->count() > 1) {
|
||||
$queued_deployments = $queued_deployments->skip(1);
|
||||
$queued_deployments->each(function ($queued_deployment, $key) {
|
||||
$queued_deployment->status = 'cancelled by system';
|
||||
$queued_deployment->save();
|
||||
});
|
||||
}
|
||||
if ($running_deployments->count() > 0) {
|
||||
$deployments = ApplicationDeploymentQueue::where('server_id', $server_id)->whereIn('status', ['in_progress', 'queued'])->get()->sortByDesc('created_at');
|
||||
$same_application_deployments = $deployments->where('application_id', $application_id);
|
||||
$in_progress = $same_application_deployments->filter(function ($value, $key) {
|
||||
return $value->status === 'in_progress';
|
||||
});
|
||||
if ($in_progress->count() > 0) {
|
||||
return;
|
||||
}
|
||||
if ($deployments_per_server->count() > $server->settings->concurrent_builds) {
|
||||
$server = Server::find($server_id);
|
||||
$concurrent_builds = $server->settings->concurrent_builds;
|
||||
|
||||
ray("serverId:{$server->id}", "concurrentBuilds:{$concurrent_builds}", "deployments:{$deployments->count()}", "sameApplicationDeployments:{$same_application_deployments->count()}");
|
||||
|
||||
if ($deployments->count() > $concurrent_builds) {
|
||||
return;
|
||||
}
|
||||
if ($is_new_deployment) {
|
||||
@ -60,8 +63,7 @@ function queue_next_deployment(Application $application, bool $isNew = false)
|
||||
{
|
||||
$server_id = $application->destination->server_id;
|
||||
$next_found = ApplicationDeploymentQueue::where('server_id', $server_id)->where('status', 'queued')->get()->sortBy('created_at')->first();;
|
||||
// $next_found = ApplicationDeploymentQueue::where('status', 'queued')->get()->sortBy('created_at')->first();
|
||||
ray($next_found, $server_id);
|
||||
// ray($next_found, $server_id);
|
||||
if ($next_found) {
|
||||
if ($isNew) {
|
||||
dispatch(new ApplicationDeploymentNewJob(
|
||||
|
@ -69,6 +69,7 @@ function githubApi(GithubApp|GitlabApp|null $source, string $endpoint, string $m
|
||||
}
|
||||
$json = $response->json();
|
||||
if ($response->failed() && $throwError) {
|
||||
ray($json);
|
||||
throw new \Exception("Failed to get data from {$source->name} with error:<br><br>" . $json['message'] . "<br><br>Rate Limit resets at: " . Carbon::parse((int)$response->header('X-RateLimit-Reset'))->format('Y-m-d H:i:s') . 'UTC');
|
||||
}
|
||||
return [
|
||||
|
494
composer.lock
generated
494
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ return [
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.200',
|
||||
'release' => '4.0.0-beta.201',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.200';
|
||||
return '4.0.0-beta.201';
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->string('manual_webhook_secret_bitbucket')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->dropColumn('manual_webhook_secret_bitbucket');
|
||||
});
|
||||
}
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->string('application_name')->nullable();
|
||||
$table->string('server_name')->nullable();
|
||||
$table->string('deployment_url')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->dropColumn('application_name');
|
||||
$table->dropColumn('server_name');
|
||||
$table->dropColumn('deployment_url');
|
||||
});
|
||||
}
|
||||
};
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||
$table->text('value')->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||
$table->string('value')->change();
|
||||
});
|
||||
}
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
coolify:
|
||||
image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-4.0.0-beta.190}"
|
||||
image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:latest}"
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /data/coolify/source/.env
|
||||
|
222
package-lock.json
generated
222
package-lock.json
generated
@ -6,22 +6,22 @@
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@tailwindcss/typography": "0.5.10",
|
||||
"alpinejs": "3.13.3",
|
||||
"alpinejs": "3.13.5",
|
||||
"daisyui": "4.4.19",
|
||||
"ioredis": "5.3.2",
|
||||
"tailwindcss-scrollbar": "0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "4.5.1",
|
||||
"autoprefixer": "10.4.16",
|
||||
"axios": "1.6.5",
|
||||
"autoprefixer": "10.4.17",
|
||||
"axios": "1.6.7",
|
||||
"laravel-echo": "1.15.3",
|
||||
"laravel-vite-plugin": "0.8.1",
|
||||
"postcss": "8.4.33",
|
||||
"pusher-js": "8.4.0-rc2",
|
||||
"tailwindcss": "3.4.1",
|
||||
"vite": "4.5.2",
|
||||
"vue": "3.4.13"
|
||||
"vue": "3.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@alloc/quick-lru": {
|
||||
@ -36,9 +36,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz",
|
||||
"integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
|
||||
"version": "7.23.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz",
|
||||
"integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@ -524,77 +524,77 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.13.tgz",
|
||||
"integrity": "sha512-zGUdmB3j3Irn9z51GXLJ5s0EAHxmsm5/eXl0y6MBaajMeOAaiT4+zaDoxui4Ets98dwIRr8BBaqXXHtHSfm+KA==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz",
|
||||
"integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.6",
|
||||
"@vue/shared": "3.4.13",
|
||||
"@vue/shared": "3.4.15",
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.13.tgz",
|
||||
"integrity": "sha512-XSNbpr5Rs3kCfVAmBqMu/HDwOS+RL6y28ZZjDlnDUuf146pRWt2sQkwhsOYc9uu2lxjjJy2NcyOkK7MBLVEc7w==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz",
|
||||
"integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.4.13",
|
||||
"@vue/shared": "3.4.13"
|
||||
"@vue/compiler-core": "3.4.15",
|
||||
"@vue/shared": "3.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.13.tgz",
|
||||
"integrity": "sha512-SkpmQN8xIFBd5onT413DFSDdjxULJf6jmJg/t3w/DZ9I8ZzyNlLIBLO0qFLewVHyHCiAgpPZlWqSRZXYrawk3Q==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz",
|
||||
"integrity": "sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.6",
|
||||
"@vue/compiler-core": "3.4.13",
|
||||
"@vue/compiler-dom": "3.4.13",
|
||||
"@vue/compiler-ssr": "3.4.13",
|
||||
"@vue/shared": "3.4.13",
|
||||
"@vue/compiler-core": "3.4.15",
|
||||
"@vue/compiler-dom": "3.4.15",
|
||||
"@vue/compiler-ssr": "3.4.15",
|
||||
"@vue/shared": "3.4.15",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.5",
|
||||
"postcss": "^8.4.32",
|
||||
"postcss": "^8.4.33",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.13.tgz",
|
||||
"integrity": "sha512-rwnw9SVBgD6eGKh8UucnwztieQo/R3RQrEGpE0b0cxb2xxvJeLs/fe7DoYlhEfaSyzM/qD5odkK87hl3G3oW+A==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz",
|
||||
"integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.13",
|
||||
"@vue/shared": "3.4.13"
|
||||
"@vue/compiler-dom": "3.4.15",
|
||||
"@vue/shared": "3.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
@ -606,64 +606,64 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.13.tgz",
|
||||
"integrity": "sha512-Ov4d4At7z3goxqzSqQxdfVYEcN5HY4dM1uDYL6Hu/Es9Za9BEN602zyjWhhi2+BEki5F9NizRSvn02k/tqNWlg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.15.tgz",
|
||||
"integrity": "sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.4.13",
|
||||
"@vue/shared": "3.4.13"
|
||||
"@vue/reactivity": "3.4.15",
|
||||
"@vue/shared": "3.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core/node_modules/@vue/reactivity": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.13.tgz",
|
||||
"integrity": "sha512-/ZdUOrGKkGVONzVJkfDqNcn2fLMvaa5VlYx2KwTbnRbX06YZ4GJE0PVTmWzIxtBYdpSTLLXgw3pDggO+96KXzg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz",
|
||||
"integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.4.13"
|
||||
"@vue/shared": "3.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.13.tgz",
|
||||
"integrity": "sha512-ynde9p16eEV3u1VCxUre2e0nKzD0l3NzH0r599+bXeLT1Yhac8Atcot3iL9XNqwolxYCI89KBII+2MSVzfrz6w==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz",
|
||||
"integrity": "sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vue/runtime-core": "3.4.13",
|
||||
"@vue/shared": "3.4.13",
|
||||
"@vue/runtime-core": "3.4.15",
|
||||
"@vue/shared": "3.4.15",
|
||||
"csstype": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.13.tgz",
|
||||
"integrity": "sha512-hkw+UQyDZZtSn1q30nObMfc8beVEQv2pG08nghigxGw+iOWodR+tWSuJak0mzWAHlP/xt/qLc//dG6igfgvGEA==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz",
|
||||
"integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.4.13",
|
||||
"@vue/shared": "3.4.13"
|
||||
"@vue/compiler-ssr": "3.4.15",
|
||||
"@vue/shared": "3.4.15"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.4.13"
|
||||
"vue": "3.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
@ -672,9 +672,9 @@
|
||||
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA=="
|
||||
},
|
||||
"node_modules/alpinejs": {
|
||||
"version": "3.13.3",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.3.tgz",
|
||||
"integrity": "sha512-WZ6WQjkAOl+WdW/jukzNHq9zHFDNKmkk/x6WF7WdyNDD6woinrfXCVsZXm0galjbco+pEpYmJLtwlZwcOfIVdg==",
|
||||
"version": "3.13.5",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.5.tgz",
|
||||
"integrity": "sha512-1d2XeNGN+Zn7j4mUAKXtAgdc4/rLeadyTMWeJGXF5DzwawPBxwTiBhFFm6w/Ei8eJxUZeyNWWSD9zknfdz1kEw==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "~3.1.1"
|
||||
}
|
||||
@ -708,9 +708,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.16",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
|
||||
"integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==",
|
||||
"version": "10.4.17",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
|
||||
"integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -727,9 +727,9 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"browserslist": "^4.21.10",
|
||||
"caniuse-lite": "^1.0.30001538",
|
||||
"fraction.js": "^4.3.6",
|
||||
"browserslist": "^4.22.2",
|
||||
"caniuse-lite": "^1.0.30001578",
|
||||
"fraction.js": "^4.3.7",
|
||||
"normalize-range": "^0.1.2",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss-value-parser": "^4.2.0"
|
||||
@ -745,9 +745,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
|
||||
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
|
||||
"version": "1.6.7",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
|
||||
"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.4",
|
||||
@ -789,9 +789,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.11",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.11.tgz",
|
||||
"integrity": "sha512-xn1UXOKUz7DjdGlg9RrUr0GGiWzI97UQJnugHtH0OLDfJB7jMgoIkYvRIEO1l9EeEERVqeqLYOcFBW9ldjypbQ==",
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz",
|
||||
"integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -808,9 +808,9 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001538",
|
||||
"electron-to-chromium": "^1.4.526",
|
||||
"node-releases": "^2.0.13",
|
||||
"caniuse-lite": "^1.0.30001565",
|
||||
"electron-to-chromium": "^1.4.601",
|
||||
"node-releases": "^2.0.14",
|
||||
"update-browserslist-db": "^1.0.13"
|
||||
},
|
||||
"bin": {
|
||||
@ -829,9 +829,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001539",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001539.tgz",
|
||||
"integrity": "sha512-hfS5tE8bnNiNvEOEkm8HElUHroYwlqMMENEzELymy77+tJ6m+gA2krtHl5hxJaj71OlpC2cHZbdSMX1/YEqEkA==",
|
||||
"version": "1.0.30001580",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz",
|
||||
"integrity": "sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -1014,9 +1014,9 @@
|
||||
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.528",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.528.tgz",
|
||||
"integrity": "sha512-UdREXMXzLkREF4jA8t89FQjA8WHI6ssP38PMY4/4KhXFQbtImnghh4GkCgrtiZwLKUKVD2iTVXvDVQjfomEQuA==",
|
||||
"version": "1.4.647",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.647.tgz",
|
||||
"integrity": "sha512-Z/fTNGwc45WrYQhPaEcz5tAJuZZ8G7S/DBnhS6Kgp4BxnS40Z/HqlJ0hHg3Z79IGVzuVartIlTcjw/cQbPLgOw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/entities": {
|
||||
@ -1168,9 +1168,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fraction.js": {
|
||||
"version": "4.3.6",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz",
|
||||
"integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
@ -1506,9 +1506,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.13",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
||||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
|
||||
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
@ -2106,16 +2106,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.13.tgz",
|
||||
"integrity": "sha512-FE3UZ0p+oUZTwz+SzlH/hDFg+XsVRFvwmx0LXjdD1pRK/cO4fu5v6ltAZji4za4IBih3dV78elUK3di8v3pWIg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz",
|
||||
"integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.13",
|
||||
"@vue/compiler-sfc": "3.4.13",
|
||||
"@vue/runtime-dom": "3.4.13",
|
||||
"@vue/server-renderer": "3.4.13",
|
||||
"@vue/shared": "3.4.13"
|
||||
"@vue/compiler-dom": "3.4.15",
|
||||
"@vue/compiler-sfc": "3.4.15",
|
||||
"@vue/runtime-dom": "3.4.15",
|
||||
"@vue/server-renderer": "3.4.15",
|
||||
"@vue/shared": "3.4.15"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
@ -2127,9 +2127,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue/node_modules/@vue/shared": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.13.tgz",
|
||||
"integrity": "sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==",
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
|
||||
"integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
|
@ -7,19 +7,19 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "4.5.1",
|
||||
"autoprefixer": "10.4.16",
|
||||
"axios": "1.6.5",
|
||||
"autoprefixer": "10.4.17",
|
||||
"axios": "1.6.7",
|
||||
"laravel-echo": "1.15.3",
|
||||
"laravel-vite-plugin": "0.8.1",
|
||||
"postcss": "8.4.33",
|
||||
"pusher-js": "8.4.0-rc2",
|
||||
"tailwindcss": "3.4.1",
|
||||
"vite": "4.5.2",
|
||||
"vue": "3.4.13"
|
||||
"vue": "3.4.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/typography": "0.5.10",
|
||||
"alpinejs": "3.13.3",
|
||||
"alpinejs": "3.13.5",
|
||||
"daisyui": "4.4.19",
|
||||
"ioredis": "5.3.2",
|
||||
"tailwindcss-scrollbar": "0.1.0"
|
||||
|
2
public/vendor/horizon/app.js
vendored
2
public/vendor/horizon/app.js
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/horizon/mix-manifest.json
vendored
2
public/vendor/horizon/mix-manifest.json
vendored
@ -1,5 +1,5 @@
|
||||
{
|
||||
"/app.js": "/app.js?id=79bae40dcb18de9ca1b5d0008c577471",
|
||||
"/app.js": "/app.js?id=b4f3f08e60211bd6948ec35e5e9de9a1",
|
||||
"/app-dark.css": "/app-dark.css?id=15c72df05e2b1147fa3e4b0670cfb435",
|
||||
"/app.css": "/app.css?id=4d6a1a7fe095eedc2cb2a4ce822ea8a5",
|
||||
"/img/favicon.png": "/img/favicon.png?id=1542bfe8a0010dcbee710da13cce367f",
|
||||
|
@ -19,7 +19,7 @@ button[isError] {
|
||||
}
|
||||
|
||||
.main {
|
||||
@apply pt-4 pl-24 pr-10 mx-auto;
|
||||
@apply pt-4 pl-24 pr-10 lg:pr-32 lg:pl-44;
|
||||
}
|
||||
|
||||
.custom-modal {
|
||||
|
@ -11,7 +11,7 @@
|
||||
@auth
|
||||
<livewire:realtime-connection />
|
||||
@endauth
|
||||
<main class="pb-10 main max-w-screen-2xl">
|
||||
<main class="pb-10 main">
|
||||
{{ $slot }}
|
||||
</main>
|
||||
@endsection
|
||||
|
@ -11,7 +11,8 @@
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span>Your subscription has been activated! Welcome onboard! <br>It could take a few seconds before your subscription is activated.<br> Please be patient.</span>
|
||||
<span>Your subscription has been activated! Welcome onboard! <br>It could take a few seconds before your
|
||||
subscription is activated.<br> Please be patient.</span>
|
||||
</div>
|
||||
@endif
|
||||
@if ($projects->count() === 0 && $servers->count() === 0)
|
||||
@ -29,14 +30,14 @@
|
||||
@foreach ($projects as $project)
|
||||
<div class="gap-2 border border-transparent cursor-pointer box group">
|
||||
@if (data_get($project, 'environments.0.name'))
|
||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||
href="{{ route('project.resource.index', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
|
||||
<div class="font-bold text-white">{{ $project->name }}</div>
|
||||
<div class="description">
|
||||
{{ $project->description }}</div>
|
||||
</a>
|
||||
@else
|
||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">
|
||||
<div class="font-bold text-white">{{ $project->name }}</div>
|
||||
<div class="description">
|
||||
@ -44,11 +45,11 @@
|
||||
</a>
|
||||
@endif
|
||||
<div class="flex items-center">
|
||||
<a class="mx-4 rounded group-hover:text-white hover:no-underline"
|
||||
<a class="mx-4 rounded group-hover:text-white hover:no-underline"
|
||||
href="{{ route('project.resource.create', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
|
||||
<span class="font-bold hover:text-warning">+ New Resource</span>
|
||||
</a>
|
||||
<a class="mx-4 rounded group-hover:text-white"
|
||||
<a class="mx-4 rounded group-hover:text-white"
|
||||
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon hover:text-warning" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
@ -72,12 +73,11 @@
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@endif
|
||||
@foreach ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||
@class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-transparent' => $server->settings->is_reachable,
|
||||
'border-red-500' => !$server->settings->is_reachable,
|
||||
])>
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}" @class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-transparent' => $server->settings->is_reachable,
|
||||
'border-red-500' => !$server->settings->is_reachable,
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">
|
||||
{{ $server->name }}
|
||||
@ -100,6 +100,45 @@
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments </h3>
|
||||
@if (count($deployments_per_server) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
</div>
|
||||
{{-- <div wire:poll.4000ms="get_deployments" class="grid grid-cols-1 gap-2 lg:grid-cols-3"> --}}
|
||||
<div class="grid grid-cols-1">
|
||||
@forelse ($deployments_per_server as $server_name => $deployments)
|
||||
<h4 class="py-4">{{ $server_name }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'border-white' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
@if (data_get($deployment, 'pull_request_id') !== 0)
|
||||
<div class="description">
|
||||
PR #{{ data_get($deployment, 'pull_request_id') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div>No queued / in progress deployments</div>
|
||||
@endforelse
|
||||
</div>
|
||||
<script>
|
||||
function gotoProject(uuid, environment = 'production') {
|
||||
window.location.href = '/project/' + uuid + '/' + environment;
|
||||
|
@ -39,7 +39,7 @@
|
||||
<a :class="activeTab === 'webhooks' && 'text-white'"
|
||||
@click.prevent="activeTab = 'webhooks'; window.location.hash = 'webhooks'" href="#">Webhooks
|
||||
</a>
|
||||
@if ($application->git_based() && $application->build_pack !== 'static')
|
||||
@if ($application->git_based())
|
||||
<a :class="activeTab === 'previews' && 'text-white'"
|
||||
@click.prevent="activeTab = 'previews'; window.location.hash = 'previews'" href="#">Preview
|
||||
Deployments
|
||||
|
@ -7,6 +7,6 @@
|
||||
@endif
|
||||
@if (data_get($application_deployment_queue, 'status') === 'in_progress' ||
|
||||
data_get($application_deployment_queue, 'status') === 'queued')
|
||||
<x-forms.button wire:click.prevent="cancel">Cancel Deployment</x-forms.button>
|
||||
<x-forms.button isError wire:click.prevent="cancel">Cancel Deployment</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
|
@ -2,12 +2,33 @@
|
||||
<h1>Deployments</h1>
|
||||
<livewire:project.application.heading :application="$application" />
|
||||
{{-- <livewire:project.application.deployment.show :application="$application" :deployments="$deployments" :deployments_count="$deployments_count" /> --}}
|
||||
<div class="flex flex-col gap-2 pb-10" @if ($skip == 0) wire:poll.5000ms='reload_deployments' @endif>
|
||||
<div class="flex flex-col gap-2 pb-10"
|
||||
@if ($skip == 0) wire:poll.5000ms='reload_deployments' @endif>
|
||||
<div class="flex items-end gap-2 pt-4">
|
||||
<h2>Deployments <span class="text-xs">({{ $deployments_count }})</span></h2>
|
||||
@if ($show_prev)
|
||||
<x-forms.button wire:click="previous_page({{ $default_take }})"><svg class="w-6 h-6" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m14 6l-6 6l6 6z" />
|
||||
</svg></x-forms.button>
|
||||
@else
|
||||
<x-forms.button disabled><svg class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m14 6l-6 6l6 6z" />
|
||||
</svg></x-forms.button>
|
||||
@endif
|
||||
@if ($show_next)
|
||||
<x-forms.button wire:click="load_deployments({{ $default_take }})">Next Page
|
||||
</x-forms.button>
|
||||
<x-forms.button wire:click="next_page({{ $default_take }})"><svg class="w-6 h-6" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m10 18l6-6l-6-6z" />
|
||||
</svg></x-forms.button>
|
||||
@else
|
||||
<x-forms.button disabled><svg class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m10 18l6-6l-6-6z" />
|
||||
</svg></x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
<form class="flex items-end gap-2">
|
||||
@ -15,7 +36,7 @@
|
||||
<x-forms.button type="submit">Filter</x-forms.button>
|
||||
</form>
|
||||
@forelse ($deployments as $deployment)
|
||||
<a @class([
|
||||
<a @class([
|
||||
'bg-coolgray-100 p-2 border-l border-dashed transition-colors hover:no-underline',
|
||||
'hover:bg-coolgray-200' => data_get($deployment, 'status') === 'queued',
|
||||
'border-warning hover:bg-warning hover:text-black' =>
|
||||
@ -33,20 +54,28 @@
|
||||
<span class=" text-warning">></span>
|
||||
{{ $deployment->status }}
|
||||
</div>
|
||||
@if (data_get($deployment, 'pull_request_id'))
|
||||
<div>
|
||||
<span class=" text-warning">></span>
|
||||
Pull Request #{{ data_get($deployment, 'pull_request_id') }}
|
||||
@if (data_get($deployment, 'is_webhook') || data_get($deployment, 'pull_request_id'))
|
||||
<div class="flex gap-1">
|
||||
@if (data_get($deployment, 'is_webhook'))
|
||||
(Webhook)
|
||||
Webhook
|
||||
@endif
|
||||
Webhook (SHA
|
||||
@if (data_get($deployment, 'commit'))
|
||||
{{ data_get($deployment, 'commit') }})
|
||||
@else
|
||||
HEAD)
|
||||
@if (data_get($deployment, 'pull_request_id'))
|
||||
@if (data_get($deployment, 'is_webhook'))
|
||||
|
|
||||
@endif
|
||||
Pull Request #{{ data_get($deployment, 'pull_request_id') }}
|
||||
(SHA
|
||||
@if (data_get($deployment, 'commit'))
|
||||
{{ data_get($deployment, 'commit') }})
|
||||
@else
|
||||
HEAD)
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div class="flex gap-1">
|
||||
Manual
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
<div>
|
||||
<livewire:project.application.preview.form :application="$application" />
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3>Pull Requests on Git</h3>
|
||||
<x-forms.button wire:click="load_prs">Load Pull Requests
|
||||
</x-forms.button>
|
||||
</div>
|
||||
@if ($application->is_github_based())
|
||||
<div class="flex items-center gap-2">
|
||||
<h3>Pull Requests on Git</h3>
|
||||
<x-forms.button wire:click="load_prs">Load Pull Requests
|
||||
</x-forms.button>
|
||||
</div>
|
||||
@endif
|
||||
@isset($rate_limit_remaining)
|
||||
<div class="pt-1 ">Requests remaining till rate limited by Git: {{ $rate_limit_remaining }}</div>
|
||||
@endisset
|
||||
|
@ -33,6 +33,10 @@
|
||||
helper="Need to set a secret to be able to use this webhook. It should match with the secret in GitLab."
|
||||
label="GitLab Webhook Secret" id="resource.manual_webhook_secret_gitlab"></x-forms.input>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input readonly label="Bitbucket" id="bitbucketManualWebhook"></x-forms.input>
|
||||
<x-forms.input type="password" helper="Need to set a secret to be able to use this webhook. It should match with the secret in Bitbucket." label="Bitbucket Webhook Secret" id="resource.manual_webhook_secret_bitbucket"></x-forms.input>
|
||||
</div>
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
</form>
|
||||
@else
|
||||
|
@ -70,8 +70,7 @@ Route::group([
|
||||
$type = $resource->getMorphClass();
|
||||
if ($type === 'App\Models\Application') {
|
||||
queue_application_deployment(
|
||||
server_id: $resource->destination->server->id,
|
||||
application_id: $resource->id,
|
||||
application: $resource,
|
||||
deployment_uuid: new Cuid2(7),
|
||||
force_rebuild: $force,
|
||||
);
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\ProcessStatus;
|
||||
use App\Jobs\ApplicationPullRequestUpdateJob;
|
||||
use App\Jobs\SubscriptionInvoiceFailedJob;
|
||||
use App\Jobs\SubscriptionTrialEndedJob;
|
||||
use App\Jobs\SubscriptionTrialEndsSoonJob;
|
||||
@ -149,8 +151,7 @@ Route::post('/source/gitlab/events/manual', function () {
|
||||
ray('Deploying ' . $application->name . ' with branch ' . $branch);
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
queue_application_deployment(
|
||||
server_id: $application->destination->server->id,
|
||||
application_id: $application->id,
|
||||
application: $application,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
is_webhook: true
|
||||
@ -178,8 +179,7 @@ Route::post('/source/gitlab/events/manual', function () {
|
||||
]);
|
||||
}
|
||||
queue_application_deployment(
|
||||
server_id: $application->destination->server->id,
|
||||
application_id: $application->id,
|
||||
application: $application,
|
||||
pull_request_id: $pull_request_id,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
@ -234,8 +234,170 @@ Route::post('/source/gitlab/events/manual', function () {
|
||||
return handleError($e);
|
||||
}
|
||||
});
|
||||
Route::post('/source/bitbucket/events/manual', function () {
|
||||
try {
|
||||
$return_payloads = collect([]);
|
||||
$payload = request()->collect();
|
||||
$headers = request()->headers->all();
|
||||
$x_bitbucket_token = data_get($headers, 'x-hub-signature.0', "");
|
||||
$x_bitbucket_event = data_get($headers, 'x-event-key.0', "");
|
||||
$handled_events = collect(['repo:push', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']);
|
||||
if (!$handled_events->contains($x_bitbucket_event)) {
|
||||
return response([
|
||||
'status' => 'failed',
|
||||
'message' => 'Nothing to do. Event not handled.',
|
||||
]);
|
||||
}
|
||||
if ($x_bitbucket_event === 'repo:push') {
|
||||
$branch = data_get($payload, 'push.changes.0.new.name');
|
||||
$full_name = data_get($payload, 'repository.full_name');
|
||||
|
||||
if (!$branch) {
|
||||
return response([
|
||||
'status' => 'failed',
|
||||
'message' => 'Nothing to do. No branch found in the request.',
|
||||
]);
|
||||
}
|
||||
ray('Manual webhook bitbucket push event with branch: ' . $branch);
|
||||
}
|
||||
if ($x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') {
|
||||
$branch = data_get($payload, 'pullrequest.destination.branch.name');
|
||||
$base_branch = data_get($payload, 'pullrequest.source.branch.name');
|
||||
$full_name = data_get($payload, 'repository.full_name');
|
||||
$pull_request_id = data_get($payload, 'pullrequest.id');
|
||||
$pull_request_html_url = data_get($payload, 'pullrequest.links.html.href');
|
||||
$commit = data_get($payload, 'pullrequest.source.commit.hash');
|
||||
}
|
||||
$applications = Application::where('git_repository', 'like', "%$full_name%");
|
||||
$applications = $applications->where('git_branch', $branch)->get();
|
||||
if ($applications->isEmpty()) {
|
||||
return response([
|
||||
'status' => 'failed',
|
||||
'message' => "Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name.",
|
||||
]);
|
||||
}
|
||||
foreach ($applications as $application) {
|
||||
if (!$application->isPRDeployable()) {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Preview deployments disabled.',
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$webhook_secret = data_get($application, 'manual_webhook_secret_bitbucket');
|
||||
$payload = request()->getContent();
|
||||
|
||||
list($algo, $hash) = explode('=', $x_bitbucket_token, 2);
|
||||
$payloadHash = hash_hmac($algo, $payload, $webhook_secret);
|
||||
if (!hash_equals($hash, $payloadHash) && !isDev()) {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Invalid token.',
|
||||
]);
|
||||
ray('Invalid signature');
|
||||
continue;
|
||||
}
|
||||
$isFunctional = $application->destination->server->isFunctional();
|
||||
if (!$isFunctional) {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Server is not functional.',
|
||||
]);
|
||||
ray('Server is not functional: ' . $application->destination->server->name);
|
||||
continue;
|
||||
}
|
||||
if ($x_bitbucket_event === 'repo:push') {
|
||||
if ($application->isPRDeployable()) {
|
||||
ray('Deploying ' . $application->name . ' with branch ' . $branch);
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
queue_application_deployment(
|
||||
application: $application,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
is_webhook: true
|
||||
);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Preview deployment queued.',
|
||||
]);
|
||||
} else {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Preview deployments disabled.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($x_bitbucket_event === 'pullrequest:created') {
|
||||
if ($application->isPRDeployable()) {
|
||||
ray('Deploying preview for ' . $application->name . ' with branch ' . $branch . ' and base branch ' . $base_branch . ' and pull request id ' . $pull_request_id);
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||
if (!$found) {
|
||||
ApplicationPreview::create([
|
||||
'git_type' => 'bitbucket',
|
||||
'application_id' => $application->id,
|
||||
'pull_request_id' => $pull_request_id,
|
||||
'pull_request_html_url' => $pull_request_html_url,
|
||||
]);
|
||||
}
|
||||
queue_application_deployment(
|
||||
application: $application,
|
||||
pull_request_id: $pull_request_id,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
commit: $commit,
|
||||
is_webhook: true,
|
||||
git_type: 'bitbucket'
|
||||
);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Preview deployment queued.',
|
||||
]);
|
||||
} else {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Preview deployments disabled.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') {
|
||||
ray('Pull request rejected');
|
||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||
if ($found) {
|
||||
$found->delete();
|
||||
$container_name = generateApplicationContainerName($application, $pull_request_id);
|
||||
instant_remote_process(["docker rm -f $container_name"], $application->destination->server);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Preview deployment closed.',
|
||||
]);
|
||||
} else {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'No preview deployment found.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
ray($return_payloads);
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e);
|
||||
return handleError($e);
|
||||
}
|
||||
});
|
||||
Route::post('/source/github/events/manual', function () {
|
||||
try {
|
||||
$return_payloads = collect([]);
|
||||
$x_github_event = Str::lower(request()->header('X-GitHub-Event'));
|
||||
$x_hub_signature_256 = Str::after(request()->header('X-Hub-Signature-256'), 'sha256=');
|
||||
$content_type = request()->header('Content-Type');
|
||||
@ -284,13 +446,22 @@ Route::post('/source/github/events/manual', function () {
|
||||
foreach ($applications as $application) {
|
||||
$webhook_secret = data_get($application, 'manual_webhook_secret_github');
|
||||
$hmac = hash_hmac('sha256', request()->getContent(), $webhook_secret);
|
||||
if (!hash_equals($x_hub_signature_256, $hmac)) {
|
||||
if (!hash_equals($x_hub_signature_256, $hmac) && !isDev()) {
|
||||
ray('Invalid signature');
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Invalid token.',
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$isFunctional = $application->destination->server->isFunctional();
|
||||
if (!$isFunctional) {
|
||||
ray('Server is not functional: ' . $application->destination->server->name);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Server is not functional.',
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
if ($x_github_event === 'push') {
|
||||
@ -298,14 +469,22 @@ Route::post('/source/github/events/manual', function () {
|
||||
ray('Deploying ' . $application->name . ' with branch ' . $branch);
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
queue_application_deployment(
|
||||
server_id: $application->destination->server->id,
|
||||
application_id: $application->id,
|
||||
application: $application,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
is_webhook: true
|
||||
is_webhook: true,
|
||||
);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Deployment queued.',
|
||||
]);
|
||||
} else {
|
||||
ray('Deployments disabled for ' . $application->name);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Deployments disabled.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($x_github_event === 'pull_request') {
|
||||
@ -322,19 +501,24 @@ Route::post('/source/github/events/manual', function () {
|
||||
]);
|
||||
}
|
||||
queue_application_deployment(
|
||||
server_id: $application->destination->server->id,
|
||||
application_id: $application->id,
|
||||
application: $application,
|
||||
pull_request_id: $pull_request_id,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
is_webhook: true,
|
||||
git_type: 'github'
|
||||
);
|
||||
ray('Deploying preview for ' . $application->name . ' with branch ' . $branch . ' and base branch ' . $base_branch . ' and pull request id ' . $pull_request_id);
|
||||
return response('Preview Deployment queued.');
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Preview deployment queued.',
|
||||
]);
|
||||
} else {
|
||||
ray('Preview deployments disabled for ' . $application->name);
|
||||
return response('Nothing to do. Preview Deployments disabled.');
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Preview deployments disabled.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($action === 'closed') {
|
||||
@ -344,12 +528,23 @@ Route::post('/source/github/events/manual', function () {
|
||||
$container_name = generateApplicationContainerName($application, $pull_request_id);
|
||||
// ray('Stopping container: ' . $container_name);
|
||||
instant_remote_process(["docker rm -f $container_name"], $application->destination->server);
|
||||
return response('Preview Deployment closed.');
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Preview deployment closed.',
|
||||
]);
|
||||
} else {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'No preview deployment found.',
|
||||
]);
|
||||
}
|
||||
return response('Nothing to do. No Preview Deployment found');
|
||||
}
|
||||
}
|
||||
}
|
||||
ray($return_payloads);
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e->getMessage());
|
||||
return handleError($e);
|
||||
@ -357,6 +552,7 @@ Route::post('/source/github/events/manual', function () {
|
||||
});
|
||||
Route::post('/source/github/events', function () {
|
||||
try {
|
||||
$return_payloads = collect([]);
|
||||
$id = null;
|
||||
$x_github_delivery = request()->header('X-GitHub-Delivery');
|
||||
$x_github_event = Str::lower(request()->header('X-GitHub-Event'));
|
||||
@ -380,7 +576,7 @@ Route::post('/source/github/events', function () {
|
||||
$hmac = hash_hmac('sha256', request()->getContent(), $webhook_secret);
|
||||
if (config('app.env') !== 'local') {
|
||||
if (!hash_equals($x_hub_signature_256, $hmac)) {
|
||||
return response('not cool');
|
||||
return response('Invalid signature.');
|
||||
}
|
||||
}
|
||||
if ($x_github_event === 'push') {
|
||||
@ -420,7 +616,11 @@ Route::post('/source/github/events', function () {
|
||||
foreach ($applications as $application) {
|
||||
$isFunctional = $application->destination->server->isFunctional();
|
||||
if (!$isFunctional) {
|
||||
ray('Server is not functional: ' . $application->destination->server->name);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Server is not functional.',
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
if ($x_github_event === 'push') {
|
||||
@ -428,14 +628,22 @@ Route::post('/source/github/events', function () {
|
||||
ray('Deploying ' . $application->name . ' with branch ' . $branch);
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
queue_application_deployment(
|
||||
server_id: $application->destination->server->id,
|
||||
application_id: $application->id,
|
||||
application: $application,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
is_webhook: true
|
||||
);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Deployment queued.',
|
||||
]);
|
||||
} else {
|
||||
ray('Deployments disabled for ' . $application->name);
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Deployments disabled.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($x_github_event === 'pull_request') {
|
||||
@ -452,34 +660,51 @@ Route::post('/source/github/events', function () {
|
||||
]);
|
||||
}
|
||||
queue_application_deployment(
|
||||
server_id: $application->destination->server->id,
|
||||
application_id: $application->id,
|
||||
application: $application,
|
||||
pull_request_id: $pull_request_id,
|
||||
deployment_uuid: $deployment_uuid,
|
||||
force_rebuild: false,
|
||||
is_webhook: true,
|
||||
git_type: 'github'
|
||||
);
|
||||
ray('Deploying preview for ' . $application->name . ' with branch ' . $branch . ' and base branch ' . $base_branch . ' and pull request id ' . $pull_request_id);
|
||||
return response('Preview Deployment queued.');
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Preview deployment queued.',
|
||||
]);
|
||||
} else {
|
||||
ray('Preview deployments disabled for ' . $application->name);
|
||||
return response('Nothing to do. Preview Deployments disabled.');
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'Preview deployments disabled.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($action === 'closed' || $action === 'close') {
|
||||
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||
if ($found) {
|
||||
ApplicationPullRequestUpdateJob::dispatchSync(application: $application, preview: $found, status: ProcessStatus::CLOSED);
|
||||
$found->delete();
|
||||
$container_name = generateApplicationContainerName($application, $pull_request_id);
|
||||
// ray('Stopping container: ' . $container_name);
|
||||
instant_remote_process(["docker rm -f $container_name"], $application->destination->server);
|
||||
return response('Preview Deployment closed.');
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'success',
|
||||
'message' => 'Preview deployment closed.',
|
||||
]);
|
||||
} else {
|
||||
$return_payloads->push([
|
||||
'application' => $application->name,
|
||||
'status' => 'failed',
|
||||
'message' => 'No preview deployment found.',
|
||||
]);
|
||||
}
|
||||
return response('Nothing to do. No Preview Deployment found');
|
||||
}
|
||||
}
|
||||
}
|
||||
ray($return_payloads);
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e->getMessage());
|
||||
return handleError($e);
|
||||
|
@ -9,3 +9,7 @@ services:
|
||||
- wordpress-files:/var/www/html
|
||||
environment:
|
||||
SERVICE_FQDN:
|
||||
WORDPRESS_DB_HOST: $WORDPRESS_DB_HOST
|
||||
WORDPRESS_DB_USER: $WORDPRESS_DB_USER
|
||||
WORDPRESS_DB_PASSWORD: $WORDPRESS_DB_PASSWORD
|
||||
WORDPRESS_DB_NAME: $WORDPRESS_DB_NAME
|
||||
|
@ -603,7 +603,7 @@
|
||||
"wordpress-without-database": {
|
||||
"documentation": "https:\/\/wordpress.org\/documentation\/",
|
||||
"slogan": "WordPress with external database. Wordpress is open source software you can use to create a beautiful website, blog, or app.",
|
||||
"compose": "c2VydmljZXM6CiAgd29yZHByZXNzOgogICAgaW1hZ2U6ICd3b3JkcHJlc3M6bGF0ZXN0JwogICAgdm9sdW1lczoKICAgICAgLSAnd29yZHByZXNzLWZpbGVzOi92YXIvd3d3L2h0bWwnCiAgICBlbnZpcm9ubWVudDoKICAgICAgU0VSVklDRV9GUUROOiBudWxsCg==",
|
||||
"compose": "c2VydmljZXM6CiAgd29yZHByZXNzOgogICAgaW1hZ2U6ICd3b3JkcHJlc3M6bGF0ZXN0JwogICAgdm9sdW1lczoKICAgICAgLSAnd29yZHByZXNzLWZpbGVzOi92YXIvd3d3L2h0bWwnCiAgICBlbnZpcm9ubWVudDoKICAgICAgU0VSVklDRV9GUUROOiBudWxsCiAgICAgIFdPUkRQUkVTU19EQl9IT1NUOiAkV09SRFBSRVNTX0RCX0hPU1QKICAgICAgV09SRFBSRVNTX0RCX1VTRVI6ICRXT1JEUFJFU1NfREJfVVNFUgogICAgICBXT1JEUFJFU1NfREJfUEFTU1dPUkQ6ICRXT1JEUFJFU1NfREJfUEFTU1dPUkQKICAgICAgV09SRFBSRVNTX0RCX05BTUU6ICRXT1JEUFJFU1NfREJfTkFNRQo=",
|
||||
"tags": [
|
||||
"cms",
|
||||
"blog",
|
||||
|
@ -1 +0,0 @@
|
||||
[]
|
@ -1,17 +0,0 @@
|
||||
[
|
||||
{
|
||||
"_id": "e6458286-eef1-401c-be84-860b111d66f0",
|
||||
"colName": "Webhooks",
|
||||
"created": "2023-05-09T11:45:36.504Z",
|
||||
"sortNum": 10000,
|
||||
"folders": [
|
||||
{
|
||||
"_id": "b8cfd093-5467-44a2-9221-ad0207717310",
|
||||
"name": "GitHub",
|
||||
"containerId": "",
|
||||
"created": "2023-05-09T11:45:40.630Z",
|
||||
"sortNum": 10000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -1,29 +0,0 @@
|
||||
[
|
||||
{
|
||||
"_id": "e3fbfa6d-da5a-422c-95c5-904c27da8e5a",
|
||||
"name": "(Global Env)",
|
||||
"default": false,
|
||||
"global": true,
|
||||
"sortNum": -2,
|
||||
"created": "2023-05-31T08:28:50.859Z",
|
||||
"modified": "2023-05-31T08:28:50.859Z",
|
||||
"data": [
|
||||
{
|
||||
"name": "repository_id",
|
||||
"value": "603035348"
|
||||
},
|
||||
{
|
||||
"name": "repository_ref",
|
||||
"value": "nodejs-fastify"
|
||||
},
|
||||
{
|
||||
"name": "repository_name",
|
||||
"value": "coollabsio/coolify-examples"
|
||||
},
|
||||
{
|
||||
"name": "repository_ref_pr",
|
||||
"value": "nodejs-fastify-pr"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -1,146 +0,0 @@
|
||||
[
|
||||
{
|
||||
"_id": "b3d379ab-e5e4-4ba4-991d-b6c8c6bbcb98",
|
||||
"colId": "e6458286-eef1-401c-be84-860b111d66f0",
|
||||
"containerId": "b8cfd093-5467-44a2-9221-ad0207717310",
|
||||
"name": "Public Push",
|
||||
"url": "http://localhost:8000/webhooks/source/github/events",
|
||||
"method": "POST",
|
||||
"sortNum": 10000,
|
||||
"created": "2023-05-09T11:45:50.227Z",
|
||||
"modified": "2023-05-09T12:22:27.192Z",
|
||||
"headers": [
|
||||
{
|
||||
"name": "X-GitHub-Delivery",
|
||||
"value": "9b4bc300-ee63-11ed-9133-5f71dd83487d"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Event",
|
||||
"value": "push"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-ID",
|
||||
"value": "400873078"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-ID",
|
||||
"value": "292941"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-Type",
|
||||
"value": "integration"
|
||||
},
|
||||
{
|
||||
"name": "X-Hub-Signature-256",
|
||||
"value": "sha256=d5c8d05cc6de14422ab3661d37ec4b98e71f4fdd63d1116f5dedfcb0213ee03d"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"ref\": \"{{repository_ref}}\",\n \"repository\": {\n \"id\": \"{{repository_id}}\",\n \"full_name\": \"{{repository_name}}\"\n }\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "b5386afc-ad91-428f-88ac-0f449c5c26fd",
|
||||
"colId": "e6458286-eef1-401c-be84-860b111d66f0",
|
||||
"containerId": "b8cfd093-5467-44a2-9221-ad0207717310",
|
||||
"name": "Public PR - Opened",
|
||||
"url": "http://localhost:8000/webhooks/source/github/events",
|
||||
"method": "POST",
|
||||
"sortNum": 20000,
|
||||
"created": "2023-05-31T08:23:28.904Z",
|
||||
"modified": "2023-06-13T14:11:50.286Z",
|
||||
"headers": [
|
||||
{
|
||||
"name": "X-GitHub-Delivery",
|
||||
"value": "e4c43c10-09cf-11ee-8879-0a481c473173"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Event",
|
||||
"value": "pull_request"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-ID",
|
||||
"value": "400873078"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-ID",
|
||||
"value": "292941"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-Type",
|
||||
"value": "integration"
|
||||
},
|
||||
{
|
||||
"name": "X-Hub-Signature-256",
|
||||
"value": "sha256=d02e35ae379a528076710322fcf9386b23bc14d61fd671259ae1d9d20488b36f"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\r\n \"action\": \"opened\",\r\n \"number\": 1,\r\n \"pull_request\": {\r\n \"html_url\": \"https://github.com/{{repository_name}}/pull/1\",\r\n \"head\": {\r\n \"ref\":\"{{repository_ref_pr}}\"\r\n },\r\n \"base\": {\r\n \"ref\":\"{{repository_ref}}\"\r\n }\r\n },\r\n \"repository\": {\r\n \"id\": \"{{repository_id}}\",\r\n \"full_name\": \"{{repository_name}}\"\r\n }\r\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "7e7a3abd-dc01-454f-aa80-eaeb2c18aa56",
|
||||
"colId": "e6458286-eef1-401c-be84-860b111d66f0",
|
||||
"containerId": "b8cfd093-5467-44a2-9221-ad0207717310",
|
||||
"name": "Public PR - Closed",
|
||||
"url": "http://localhost:8000/webhooks/source/github/events",
|
||||
"method": "POST",
|
||||
"sortNum": 30000,
|
||||
"created": "2023-05-31T09:15:15.833Z",
|
||||
"modified": "2023-06-13T08:34:27.203Z",
|
||||
"headers": [
|
||||
{
|
||||
"name": "X-GitHub-Delivery",
|
||||
"value": "9b4bc300-ee63-11ed-9133-5f71dd83487d"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Event",
|
||||
"value": "pull_request"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-ID",
|
||||
"value": "400873078"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-ID",
|
||||
"value": "292941"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-Type",
|
||||
"value": "integration"
|
||||
},
|
||||
{
|
||||
"name": "X-Hub-Signature-256",
|
||||
"value": "sha256=d5c8d05cc6de14422ab3661d37ec4b98e71f4fdd63d1116f5dedfcb0213ee03d"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"action\": \"closed\",\n \"number\": 1,\n \"pull_request\": {\n \"html_url\": \"https://github.com/{{repository_name}}/pull/1\",\n \"head\": {\n \"ref\":\"{{repository_ref_pr}}\"\n },\n \"base\": {\n \"ref\":\"{{repository_ref}}\"\n }\n },\n \"repository\": {\n \"id\": \"{{repository_id}}\",\n \"full_name\": \"{{repository_name}}\"\n }\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
}
|
||||
]
|
@ -4,7 +4,7 @@
|
||||
"version": "3.12.36"
|
||||
},
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.200"
|
||||
"version": "4.0.0-beta.201"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user