updates
This commit is contained in:
parent
0f28acac00
commit
e5aad4d170
@ -21,7 +21,7 @@ class Deploy extends Component
|
|||||||
protected $source;
|
protected $source;
|
||||||
|
|
||||||
protected $listeners = [
|
protected $listeners = [
|
||||||
'applicationStatusChanged' => 'applicationStatusChanged',
|
'applicationStatusChanged',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
@ -40,8 +40,12 @@ protected function set_deployment_uuid()
|
|||||||
$this->deployment_uuid = new Cuid2(7);
|
$this->deployment_uuid = new Cuid2(7);
|
||||||
$this->parameters['deployment_uuid'] = $this->deployment_uuid;
|
$this->parameters['deployment_uuid'] = $this->deployment_uuid;
|
||||||
}
|
}
|
||||||
public function deploy(bool $force = false)
|
public function deploy(bool $force = false, bool|null $debug = null)
|
||||||
{
|
{
|
||||||
|
if ($debug && !$this->application->settings->is_debug_enabled) {
|
||||||
|
$this->application->settings->is_debug_enabled = true;
|
||||||
|
$this->application->settings->save();
|
||||||
|
}
|
||||||
$this->set_deployment_uuid();
|
$this->set_deployment_uuid();
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
@ -62,5 +66,6 @@ public function stop()
|
|||||||
instant_remote_process(["docker rm -f {$this->application->uuid}"], $this->application->destination->server);
|
instant_remote_process(["docker rm -f {$this->application->uuid}"], $this->application->destination->server);
|
||||||
$this->application->status = get_container_status(server: $this->application->destination->server, container_id: $this->application->uuid);
|
$this->application->status = get_container_status(server: $this->application->destination->server, container_id: $this->application->uuid);
|
||||||
$this->application->save();
|
$this->application->save();
|
||||||
|
$this->emit('applicationStatusChanged');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Project\Application\EnvironmentVariable;
|
namespace App\Http\Livewire\Project\Application\EnvironmentVariable;
|
||||||
|
|
||||||
use App\Models\Application;
|
|
||||||
use App\Models\EnvironmentVariable;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Support\Facades\Route;
|
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Add extends Component
|
class Add extends Component
|
||||||
{
|
{
|
||||||
public $parameters;
|
public $parameters;
|
||||||
|
public bool $is_preview = false;
|
||||||
public string $key;
|
public string $key;
|
||||||
public string $value;
|
public string $value;
|
||||||
public bool $is_build_time = false;
|
public bool $is_build_time = false;
|
||||||
@ -32,6 +29,7 @@ public function submit()
|
|||||||
'key' => $this->key,
|
'key' => $this->key,
|
||||||
'value' => $this->value,
|
'value' => $this->value,
|
||||||
'is_build_time' => $this->is_build_time,
|
'is_build_time' => $this->is_build_time,
|
||||||
|
'is_preview' => $this->is_preview,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
public function clear()
|
public function clear()
|
||||||
|
@ -21,6 +21,7 @@ public function submit($data)
|
|||||||
'key' => $data['key'],
|
'key' => $data['key'],
|
||||||
'value' => $data['value'],
|
'value' => $data['value'],
|
||||||
'is_build_time' => $data['is_build_time'],
|
'is_build_time' => $data['is_build_time'],
|
||||||
|
'is_preview' => $data['is_preview'],
|
||||||
'application_id' => $this->application->id,
|
'application_id' => $this->application->id,
|
||||||
]);
|
]);
|
||||||
$this->application->refresh();
|
$this->application->refresh();
|
||||||
|
@ -11,7 +11,7 @@ class Status extends Component
|
|||||||
|
|
||||||
public function applicationStatusChanged()
|
public function applicationStatusChanged()
|
||||||
{
|
{
|
||||||
$this->emit('applicationStatusChanged');
|
|
||||||
$this->application->refresh();
|
$this->application->refresh();
|
||||||
|
$this->emit('applicationStatusChanged');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,16 +14,22 @@
|
|||||||
class PublicGitRepository extends Component
|
class PublicGitRepository extends Component
|
||||||
{
|
{
|
||||||
public string $repository_url;
|
public string $repository_url;
|
||||||
|
private object $repository_url_parsed;
|
||||||
|
|
||||||
public int $port = 3000;
|
public int $port = 3000;
|
||||||
public string $type;
|
public string $type;
|
||||||
public $parameters;
|
public $parameters;
|
||||||
public $query;
|
public $query;
|
||||||
|
|
||||||
public $github_apps;
|
public $branches = [];
|
||||||
public $gitlab_apps;
|
public string $selected_branch = 'main';
|
||||||
|
|
||||||
public bool $is_static = false;
|
public bool $is_static = false;
|
||||||
public null|string $publish_directory = null;
|
public string|null $publish_directory = null;
|
||||||
|
|
||||||
|
private GithubApp|GitlabApp $git_source;
|
||||||
|
private string $git_host;
|
||||||
|
private string $git_repository;
|
||||||
|
private string $git_branch;
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'repository_url' => 'required|url',
|
'repository_url' => 'required|url',
|
||||||
@ -34,7 +40,7 @@ class PublicGitRepository extends Component
|
|||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
if (config('app.env') === 'local') {
|
if (config('app.env') === 'local') {
|
||||||
$this->repository_url = 'https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify';
|
$this->repository_url = 'https://github.com/coollabsio/coolify-examples';
|
||||||
$this->port = 3000;
|
$this->port = 3000;
|
||||||
}
|
}
|
||||||
$this->parameters = get_parameters();
|
$this->parameters = get_parameters();
|
||||||
@ -52,18 +58,43 @@ public function instantSave()
|
|||||||
}
|
}
|
||||||
$this->emit('saved', 'Application settings updated!');
|
$this->emit('saved', 'Application settings updated!');
|
||||||
}
|
}
|
||||||
|
public function load_branches()
|
||||||
|
{
|
||||||
|
$this->get_git_source();
|
||||||
|
|
||||||
|
try {
|
||||||
|
['data' => $data] = get_from_git_api($this->git_source, "/repos/{$this->git_repository}/branches");
|
||||||
|
$this->branches = collect($data)->pluck('name')->toArray();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return general_error_handler($th, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private function get_git_source()
|
||||||
|
{
|
||||||
|
$this->repository_url_parsed = Url::fromString($this->repository_url);
|
||||||
|
$this->git_host = $this->repository_url_parsed->getHost();
|
||||||
|
$this->git_repository = $this->repository_url_parsed->getSegment(1) . '/' . $this->repository_url_parsed->getSegment(2);
|
||||||
|
$this->git_branch = $this->repository_url_parsed->getSegment(4) ?? 'main';
|
||||||
|
|
||||||
|
if ($this->git_host == 'github.com') {
|
||||||
|
$this->git_source = GithubApp::where('name', 'Public GitHub')->first();
|
||||||
|
} elseif ($this->git_host == 'gitlab.com') {
|
||||||
|
$this->git_source = GitlabApp::where('name', 'Public GitLab')->first();
|
||||||
|
} elseif ($this->git_host == 'bitbucket.org') {
|
||||||
|
// Not supported yet
|
||||||
|
}
|
||||||
|
}
|
||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|
||||||
$url = Url::fromString($this->repository_url);
|
|
||||||
$git_host = $url->getHost();
|
|
||||||
$git_repository = $url->getSegment(1) . '/' . $url->getSegment(2);
|
|
||||||
$git_branch = $url->getSegment(4) ?? 'main';
|
|
||||||
|
|
||||||
$destination_uuid = $this->query['destination'];
|
$destination_uuid = $this->query['destination'];
|
||||||
|
$project_uuid = $this->parameters['project_uuid'];
|
||||||
|
$environment_name = $this->parameters['environment_name'];
|
||||||
|
|
||||||
|
$this->get_git_source();
|
||||||
|
$this->git_branch = $this->selected_branch ?? $this->git_branch;
|
||||||
|
|
||||||
$destination = StandaloneDocker::where('uuid', $destination_uuid)->first();
|
$destination = StandaloneDocker::where('uuid', $destination_uuid)->first();
|
||||||
if (!$destination) {
|
if (!$destination) {
|
||||||
$destination = SwarmDocker::where('uuid', $destination_uuid)->first();
|
$destination = SwarmDocker::where('uuid', $destination_uuid)->first();
|
||||||
@ -73,29 +104,24 @@ public function submit()
|
|||||||
}
|
}
|
||||||
$destination_class = $destination->getMorphClass();
|
$destination_class = $destination->getMorphClass();
|
||||||
|
|
||||||
$project = Project::where('uuid', $this->parameters['project_uuid'])->first();
|
$project = Project::where('uuid', $project_uuid)->first();
|
||||||
$environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
|
$environment = $project->load(['environments'])->environments->where('name', $environment_name)->first();
|
||||||
|
|
||||||
|
|
||||||
$application_init = [
|
$application_init = [
|
||||||
'name' => generate_application_name($git_repository, $git_branch),
|
'name' => generate_application_name($this->git_repository, $this->git_branch),
|
||||||
'git_repository' => $git_repository,
|
'git_repository' => $this->git_repository,
|
||||||
'git_branch' => $git_branch,
|
'git_branch' => $this->git_branch,
|
||||||
'build_pack' => 'nixpacks',
|
'build_pack' => 'nixpacks',
|
||||||
'ports_exposes' => $this->port,
|
'ports_exposes' => $this->port,
|
||||||
'publish_directory' => $this->publish_directory,
|
'publish_directory' => $this->publish_directory,
|
||||||
'environment_id' => $environment->id,
|
'environment_id' => $environment->id,
|
||||||
'destination_id' => $destination->id,
|
'destination_id' => $destination->id,
|
||||||
'destination_type' => $destination_class,
|
'destination_type' => $destination_class,
|
||||||
|
'source_id' => $this->git_source->id,
|
||||||
|
'source_type' => $this->git_source->getMorphClass()
|
||||||
];
|
];
|
||||||
if ($git_host == 'github.com') {
|
|
||||||
$application_init['source_id'] = GithubApp::where('name', 'Public GitHub')->first()->id;
|
|
||||||
$application_init['source_type'] = GithubApp::class;
|
|
||||||
} elseif ($git_host == 'gitlab.com') {
|
|
||||||
$application_init['source_id'] = GitlabApp::where('name', 'Public GitLab')->first()->id;
|
|
||||||
$application_init['source_type'] = GitlabApp::class;
|
|
||||||
} elseif ($git_host == 'bitbucket.org') {
|
|
||||||
}
|
|
||||||
$application = Application::create($application_init);
|
$application = Application::create($application_init);
|
||||||
$application->settings->is_static = $this->is_static;
|
$application->settings->is_static = $this->is_static;
|
||||||
$application->settings->save();
|
$application->settings->save();
|
||||||
@ -106,7 +132,7 @@ public function submit()
|
|||||||
'application_uuid' => $application->uuid,
|
'application_uuid' => $application->uuid,
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return general_error_handler($e);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ public function __construct(
|
|||||||
|
|
||||||
$this->application = Application::find($this->application_id);
|
$this->application = Application::find($this->application_id);
|
||||||
|
|
||||||
if ($this->pull_request_id) {
|
if ($this->pull_request_id !== 0) {
|
||||||
$this->preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id);
|
$this->preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ public function handle(): void
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->workdir = "/artifacts/{$this->deployment_uuid}";
|
$this->workdir = "/artifacts/{$this->deployment_uuid}";
|
||||||
if ($this->pull_request_id) {
|
if ($this->pull_request_id !== 0) {
|
||||||
ray('Deploying pull/' . $this->pull_request_id . '/head for application: ' . $this->application->name);
|
ray('Deploying pull/' . $this->pull_request_id . '/head for application: ' . $this->application->name);
|
||||||
$this->deploy_pull_request();
|
$this->deploy_pull_request();
|
||||||
} else {
|
} else {
|
||||||
@ -177,7 +177,7 @@ private function build_image()
|
|||||||
"echo -n 'Building image... '",
|
"echo -n 'Building image... '",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($this->application->settings->is_static) {
|
if ($this->application->settings->is_static && isset($this->application->build_command)) {
|
||||||
$this->execute_now([
|
$this->execute_now([
|
||||||
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t { $this->build_image_name {$this->workdir}"),
|
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t { $this->build_image_name {$this->workdir}"),
|
||||||
], isDebuggable: true);
|
], isDebuggable: true);
|
||||||
@ -292,10 +292,18 @@ private function execute_in_builder(string $command)
|
|||||||
private function generate_environment_variables($ports)
|
private function generate_environment_variables($ports)
|
||||||
{
|
{
|
||||||
$environment_variables = collect();
|
$environment_variables = collect();
|
||||||
|
ray('Generate Environment Variables');
|
||||||
|
if ($this->pull_request_id === 0) {
|
||||||
|
ray($this->application->runtime_environment_variables);
|
||||||
foreach ($this->application->runtime_environment_variables as $env) {
|
foreach ($this->application->runtime_environment_variables as $env) {
|
||||||
$environment_variables->push("$env->key=$env->value");
|
$environment_variables->push("$env->key=$env->value");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ray($this->application->runtime_environment_variables_preview);
|
||||||
|
foreach ($this->application->runtime_environment_variables_preview as $env) {
|
||||||
|
$environment_variables->push("$env->key=$env->value");
|
||||||
|
}
|
||||||
|
}
|
||||||
// Add PORT if not exists, use the first port as default
|
// Add PORT if not exists, use the first port as default
|
||||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
|
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
|
||||||
$environment_variables->push("PORT={$ports[0]}");
|
$environment_variables->push("PORT={$ports[0]}");
|
||||||
@ -305,17 +313,31 @@ private function generate_environment_variables($ports)
|
|||||||
private function generate_env_variables()
|
private function generate_env_variables()
|
||||||
{
|
{
|
||||||
$this->env_args = collect([]);
|
$this->env_args = collect([]);
|
||||||
|
if ($this->pull_request_id === 0) {
|
||||||
foreach ($this->application->nixpacks_environment_variables as $env) {
|
foreach ($this->application->nixpacks_environment_variables as $env) {
|
||||||
$this->env_args->push("--env {$env->key}={$env->value}");
|
$this->env_args->push("--env {$env->key}={$env->value}");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($this->application->nixpacks_environment_variables_preview as $env) {
|
||||||
|
$this->env_args->push("--env {$env->key}={$env->value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->env_args = $this->env_args->implode(' ');
|
$this->env_args = $this->env_args->implode(' ');
|
||||||
}
|
}
|
||||||
private function generate_build_env_variables()
|
private function generate_build_env_variables()
|
||||||
{
|
{
|
||||||
$this->build_args = collect(["--build-arg SOURCE_COMMIT={$this->git_commit}"]);
|
$this->build_args = collect(["--build-arg SOURCE_COMMIT={$this->git_commit}"]);
|
||||||
|
if ($this->pull_request_id === 0) {
|
||||||
foreach ($this->application->build_environment_variables as $env) {
|
foreach ($this->application->build_environment_variables as $env) {
|
||||||
$this->build_args->push("--build-arg {$env->key}={$env->value}");
|
$this->build_args->push("--build-arg {$env->key}={$env->value}");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($this->application->build_environment_variables_preview as $env) {
|
||||||
|
$this->build_args->push("--build-arg {$env->key}={$env->value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->build_args = $this->build_args->implode(' ');
|
$this->build_args = $this->build_args->implode(' ');
|
||||||
}
|
}
|
||||||
private function add_build_env_variables_to_dockerfile()
|
private function add_build_env_variables_to_dockerfile()
|
||||||
@ -336,15 +358,11 @@ private function add_build_env_variables_to_dockerfile()
|
|||||||
private function generate_docker_compose()
|
private function generate_docker_compose()
|
||||||
{
|
{
|
||||||
$ports = $this->application->settings->is_static ? [80] : $this->application->ports_exposes_array;
|
$ports = $this->application->settings->is_static ? [80] : $this->application->ports_exposes_array;
|
||||||
if ($this->pull_request_id) {
|
|
||||||
$persistent_storages = [];
|
|
||||||
$volume_names = [];
|
|
||||||
$environment_variables = [];
|
|
||||||
} else {
|
|
||||||
$persistent_storages = $this->generate_local_persistent_volumes();
|
$persistent_storages = $this->generate_local_persistent_volumes();
|
||||||
$volume_names = $this->generate_local_persistent_volumes_only_volume_names();
|
$volume_names = $this->generate_local_persistent_volumes_only_volume_names();
|
||||||
$environment_variables = $this->generate_environment_variables($ports);
|
$environment_variables = $this->generate_environment_variables($ports);
|
||||||
}
|
|
||||||
$docker_compose = [
|
$docker_compose = [
|
||||||
'version' => '3.8',
|
'version' => '3.8',
|
||||||
'services' => [
|
'services' => [
|
||||||
@ -385,7 +403,7 @@ private function generate_docker_compose()
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
if (count($this->application->ports_mappings_array) > 0 && !$this->pull_request_id) {
|
if (count($this->application->ports_mappings_array) > 0 && $this->pull_request_id === 0) {
|
||||||
$docker_compose['services'][$this->container_name]['ports'] = $this->application->ports_mappings_array;
|
$docker_compose['services'][$this->container_name]['ports'] = $this->application->ports_mappings_array;
|
||||||
}
|
}
|
||||||
if (count($persistent_storages) > 0) {
|
if (count($persistent_storages) > 0) {
|
||||||
@ -400,8 +418,12 @@ private function generate_local_persistent_volumes()
|
|||||||
{
|
{
|
||||||
foreach ($this->application->persistentStorages as $persistentStorage) {
|
foreach ($this->application->persistentStorages as $persistentStorage) {
|
||||||
$volume_name = $persistentStorage->host_path ?? $persistentStorage->name;
|
$volume_name = $persistentStorage->host_path ?? $persistentStorage->name;
|
||||||
|
if ($this->pull_request_id !== 0) {
|
||||||
|
$volume_name = $volume_name . '-pr-' . $this->pull_request_id;
|
||||||
|
}
|
||||||
$local_persistent_volumes[] = $volume_name . ':' . $persistentStorage->mount_path;
|
$local_persistent_volumes[] = $volume_name . ':' . $persistentStorage->mount_path;
|
||||||
}
|
}
|
||||||
|
ray('local_persistent_volumes', $local_persistent_volumes);
|
||||||
return $local_persistent_volumes ?? [];
|
return $local_persistent_volumes ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,8 +433,14 @@ private function generate_local_persistent_volumes_only_volume_names()
|
|||||||
if ($persistentStorage->host_path) {
|
if ($persistentStorage->host_path) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$local_persistent_volumes_names[$persistentStorage->name] = [
|
$name = $persistentStorage->name;
|
||||||
'name' => $persistentStorage->name,
|
|
||||||
|
if ($this->pull_request_id !== 0) {
|
||||||
|
$name = $name . '-pr-' . $this->pull_request_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$local_persistent_volumes_names[$name] = [
|
||||||
|
'name' => $name,
|
||||||
'external' => false,
|
'external' => false,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -443,11 +471,11 @@ private function set_labels_for_applications()
|
|||||||
$labels[] = 'coolify.applicationId=' . $this->application->id;
|
$labels[] = 'coolify.applicationId=' . $this->application->id;
|
||||||
$labels[] = 'coolify.type=application';
|
$labels[] = 'coolify.type=application';
|
||||||
$labels[] = 'coolify.name=' . $this->application->name;
|
$labels[] = 'coolify.name=' . $this->application->name;
|
||||||
if ($this->pull_request_id) {
|
if ($this->pull_request_id !== 0) {
|
||||||
$labels[] = 'coolify.pullRequestId=' . $this->pull_request_id;
|
$labels[] = 'coolify.pullRequestId=' . $this->pull_request_id;
|
||||||
}
|
}
|
||||||
if ($this->application->fqdn) {
|
if ($this->application->fqdn) {
|
||||||
if ($this->pull_request_id) {
|
if ($this->pull_request_id !== 0) {
|
||||||
$preview_fqdn = data_get($this->preview, 'fqdn');
|
$preview_fqdn = data_get($this->preview, 'fqdn');
|
||||||
$template = $this->application->preview_url_template;
|
$template = $this->application->preview_url_template;
|
||||||
$url = Url::fromString($this->application->fqdn);
|
$url = Url::fromString($this->application->fqdn);
|
||||||
@ -566,7 +594,7 @@ private function set_git_import_settings($git_clone_command)
|
|||||||
private function importing_git_repository()
|
private function importing_git_repository()
|
||||||
{
|
{
|
||||||
$git_clone_command = "git clone -q -b {$this->application->git_branch}";
|
$git_clone_command = "git clone -q -b {$this->application->git_branch}";
|
||||||
if ($this->pull_request_id) {
|
if ($this->pull_request_id !== 0) {
|
||||||
$pr_branch_name = "pr-{$this->pull_request_id}-coolify";
|
$pr_branch_name = "pr-{$this->pull_request_id}-coolify";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +611,7 @@ private function importing_git_repository()
|
|||||||
|
|
||||||
$commands = [$this->execute_in_builder($git_clone_command)];
|
$commands = [$this->execute_in_builder($git_clone_command)];
|
||||||
|
|
||||||
if ($this->pull_request_id) {
|
if ($this->pull_request_id !== 0) {
|
||||||
$commands[] = $this->execute_in_builder("cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name >/dev/null 2>&1 && git checkout $pr_branch_name >/dev/null 2>&1");
|
$commands[] = $this->execute_in_builder("cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name >/dev/null 2>&1 && git checkout $pr_branch_name >/dev/null 2>&1");
|
||||||
}
|
}
|
||||||
return $commands;
|
return $commands;
|
||||||
@ -592,7 +620,7 @@ private function importing_git_repository()
|
|||||||
$commands = [
|
$commands = [
|
||||||
$this->execute_in_builder("git clone -q -b {$this->application->git_branch} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$this->application->git_repository}.git {$this->workdir}")
|
$this->execute_in_builder("git clone -q -b {$this->application->git_branch} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$this->application->git_repository}.git {$this->workdir}")
|
||||||
];
|
];
|
||||||
if ($this->pull_request_id) {
|
if ($this->pull_request_id !== 0) {
|
||||||
$commands[] = $this->execute_in_builder("cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name && git checkout $pr_branch_name");
|
$commands[] = $this->execute_in_builder("cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name && git checkout $pr_branch_name");
|
||||||
}
|
}
|
||||||
return $commands;
|
return $commands;
|
||||||
|
@ -99,21 +99,39 @@ public function portsExposesArray(): Attribute
|
|||||||
: explode(',', $this->ports_exposes)
|
: explode(',', $this->ports_exposes)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Normal Deployments
|
||||||
public function environment_variables(): HasMany
|
public function environment_variables(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(EnvironmentVariable::class);
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false);
|
||||||
}
|
}
|
||||||
public function runtime_environment_variables(): HasMany
|
public function runtime_environment_variables(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(EnvironmentVariable::class)->where('key', 'not like', 'NIXPACKS_%');
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'not like', 'NIXPACKS_%');
|
||||||
}
|
}
|
||||||
public function build_environment_variables(): HasMany
|
public function build_environment_variables(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(EnvironmentVariable::class)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%');
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%');
|
||||||
}
|
}
|
||||||
public function nixpacks_environment_variables(): HasMany
|
public function nixpacks_environment_variables(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(EnvironmentVariable::class)->where('key', 'like', 'NIXPACKS_%');
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'like', 'NIXPACKS_%');
|
||||||
|
}
|
||||||
|
// Preview Deployments
|
||||||
|
public function environment_variables_preview(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true);
|
||||||
|
}
|
||||||
|
public function runtime_environment_variables_preview(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'not like', 'NIXPACKS_%');
|
||||||
|
}
|
||||||
|
public function build_environment_variables_preview(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%');
|
||||||
|
}
|
||||||
|
public function nixpacks_environment_variables_preview(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'like', 'NIXPACKS_%');
|
||||||
}
|
}
|
||||||
public function private_key()
|
public function private_key()
|
||||||
{
|
{
|
||||||
|
@ -2,13 +2,28 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class EnvironmentVariable extends Model
|
class EnvironmentVariable extends Model
|
||||||
{
|
{
|
||||||
protected $fillable = ['key', 'value', 'is_build_time', 'application_id'];
|
protected static function booted()
|
||||||
|
{
|
||||||
|
static::created(function ($environment_variable) {
|
||||||
|
if (!$environment_variable->is_preview) {
|
||||||
|
ModelsEnvironmentVariable::create([
|
||||||
|
'key' => $environment_variable->key,
|
||||||
|
'value' => $environment_variable->value,
|
||||||
|
'is_build_time' => $environment_variable->is_build_time,
|
||||||
|
'application_id' => $environment_variable->application_id,
|
||||||
|
'is_preview' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
protected $fillable = ['key', 'value', 'is_build_time', 'application_id', 'is_preview'];
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
"key" => 'string',
|
"key" => 'string',
|
||||||
'value' => 'encrypted',
|
'value' => 'encrypted',
|
||||||
|
@ -17,14 +17,15 @@ public function up(): void
|
|||||||
$table->string('key');
|
$table->string('key');
|
||||||
$table->string('value')->nullable();
|
$table->string('value')->nullable();
|
||||||
$table->boolean('is_build_time')->default(false);
|
$table->boolean('is_build_time')->default(false);
|
||||||
|
$table->boolean('is_preview')->default(false);
|
||||||
|
|
||||||
$table->foreignId('application_id')->nullable();
|
$table->foreignId('application_id')->nullable();
|
||||||
$table->foreignId('service_id')->nullable();
|
$table->foreignId('service_id')->nullable();
|
||||||
$table->foreignId('database_id')->nullable();
|
$table->foreignId('database_id')->nullable();
|
||||||
|
|
||||||
$table->unique(['key', 'application_id', 'is_build_time']);
|
$table->unique(['key', 'application_id', 'is_build_time', 'is_preview']);
|
||||||
$table->unique(['key', 'service_id', 'is_build_time']);
|
$table->unique(['key', 'service_id', 'is_build_time', 'is_preview']);
|
||||||
$table->unique(['key', 'database_id', 'is_build_time']);
|
$table->unique(['key', 'database_id', 'is_build_time', 'is_preview']);
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -7,7 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/typography": "0.5.9",
|
"@tailwindcss/typography": "0.5.9",
|
||||||
"alpinejs": "3.12.2",
|
"alpinejs": "3.12.2",
|
||||||
"daisyui": "3.0.0",
|
"daisyui": "3.0.3",
|
||||||
"tailwindcss-scrollbar": "0.1.0"
|
"tailwindcss-scrollbar": "0.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -941,9 +941,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/daisyui": {
|
"node_modules/daisyui": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-3.0.3.tgz",
|
||||||
"integrity": "sha512-EuNK9JQd5yrPLDynAPQkG/29vjZXFWhBK4HXvM83d9oJU0EmF35UNLLs0cslBFfLK4b+bOuhgoYPJ4BjytOxNQ==",
|
"integrity": "sha512-RSbXsEBj2LonvjOKEI0I64F5xFJrFrthPgxRNeAZKmACQ3NoIoP45lO6UXLW3bm8PVOUGpKf1Br2SWwc1NqnHQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colord": "^2.9",
|
"colord": "^2.9",
|
||||||
"css-selector-tokenizer": "^0.8",
|
"css-selector-tokenizer": "^0.8",
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/typography": "0.5.9",
|
"@tailwindcss/typography": "0.5.9",
|
||||||
"alpinejs": "3.12.2",
|
"alpinejs": "3.12.2",
|
||||||
"daisyui": "3.0.0",
|
"daisyui": "3.0.3",
|
||||||
"tailwindcss-scrollbar": "0.1.0"
|
"tailwindcss-scrollbar": "0.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,14 +14,14 @@ body {
|
|||||||
@apply scrollbar min-h-screen bg-coolgray-100 text-neutral-400 antialiased ;
|
@apply scrollbar min-h-screen bg-coolgray-100 text-neutral-400 antialiased ;
|
||||||
}
|
}
|
||||||
main {
|
main {
|
||||||
@apply px-32 xl:px-14 mx-auto max-w-screen-xl;
|
@apply px-32 xl:px-14 mx-auto max-w-screen-xl pt-10;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
@apply toggle toggle-warning toggle-xs rounded;
|
@apply toggle toggle-warning toggle-xs rounded;
|
||||||
}
|
}
|
||||||
input {
|
input {
|
||||||
@apply input input-sm placeholder:text-neutral-700 text-white rounded-none;
|
@apply input input-sm h-7 outline-none placeholder:text-neutral-700 text-white rounded-none;
|
||||||
}
|
}
|
||||||
input[type="text"],[type="number"],[type="email"],[type="password"] {
|
input[type="text"],[type="number"],[type="email"],[type="password"] {
|
||||||
@apply read-only:opacity-40;
|
@apply read-only:opacity-40;
|
||||||
@ -34,7 +34,7 @@ textarea {
|
|||||||
@apply textarea placeholder:text-neutral-700 text-white rounded-none;
|
@apply textarea placeholder:text-neutral-700 text-white rounded-none;
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
@apply select select-sm disabled:opacity-40 font-normal placeholder:text-neutral-700 text-white rounded-none;
|
@apply select select-sm disabled:bg-coolgray-200 border-none disabled:opacity-50 font-normal placeholder:text-neutral-700 text-white rounded-none;
|
||||||
}
|
}
|
||||||
.breadcrumbs > ul > li::before {
|
.breadcrumbs > ul > li::before {
|
||||||
@apply text-warning opacity-100;
|
@apply text-warning opacity-100;
|
||||||
@ -47,7 +47,7 @@ button[type="button"] {
|
|||||||
@apply hover:bg-coolgray-400 btn h-7 btn-xs border-none bg-coolgray-200 no-animation normal-case text-white rounded;
|
@apply hover:bg-coolgray-400 btn h-7 btn-xs border-none bg-coolgray-200 no-animation normal-case text-white rounded;
|
||||||
}
|
}
|
||||||
button[type="submit"] {
|
button[type="submit"] {
|
||||||
@apply btn btn-xs no-animation h-7 normal-case text-white btn-primary rounded;
|
@apply hover:bg-coolgray-400 btn h-7 btn-xs border-none bg-coolgray-200 no-animation normal-case text-white rounded;
|
||||||
}
|
}
|
||||||
button[isWarning] {
|
button[isWarning] {
|
||||||
@apply bg-error;
|
@apply bg-error;
|
||||||
|
@ -15,23 +15,32 @@
|
|||||||
]) }}">
|
]) }}">
|
||||||
<button>Deployments</button>
|
<button>Deployments</button>
|
||||||
</a>
|
</a>
|
||||||
<livewire:project.application.status :application="$application" />
|
|
||||||
<div class="flex-1"></div>
|
<div class="flex-1"></div>
|
||||||
<div class="dropdown dropdown-bottom">
|
<div class="dropdown dropdown-bottom dropdown-hover">
|
||||||
<label tabindex="0">
|
<label tabindex="0" class="flex items-center gap-2 text-sm cursor-pointer hover:text-white"> Links
|
||||||
<x-forms.button>
|
|
||||||
Open
|
|
||||||
<x-chevron-down />
|
<x-chevron-down />
|
||||||
</x-forms.button>
|
|
||||||
</label>
|
</label>
|
||||||
<ul tabindex="0"
|
<ul tabindex="0"
|
||||||
class="mt-1 text-xs text-white normal-case rounded min-w-max dropdown-content menu bg-coolgray-200">
|
class="text-xs text-white normal-case rounded min-w-max dropdown-content menu bg-coolgray-200">
|
||||||
|
<li>
|
||||||
|
<a target="_blank" class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs"
|
||||||
|
href="{{ $application->gitBranchLocation }}">
|
||||||
|
<x-git-icon git="{{ $application->source->getMorphClass() }}" />
|
||||||
|
Git Repository
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
@if (data_get($application, 'fqdn'))
|
@if (data_get($application, 'fqdn'))
|
||||||
<li>
|
<li>
|
||||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs" target="_blank"
|
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs" target="_blank"
|
||||||
href="{{ $application->fqdn }}">
|
href="{{ $application->fqdn }}">
|
||||||
{{ $application->fqdn }}
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
<x-external-link />
|
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M9 15l6 -6" />
|
||||||
|
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||||
|
<path
|
||||||
|
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||||
|
</svg>{{ $application->fqdn }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
@ -40,9 +49,16 @@ class="mt-1 text-xs text-white normal-case rounded min-w-max dropdown-content me
|
|||||||
@if (config('app.env') === 'local')
|
@if (config('app.env') === 'local')
|
||||||
<li>
|
<li>
|
||||||
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs"
|
<a class="text-xs text-white rounded-none hover:no-underline hover:bg-coollabs"
|
||||||
target="_blank" href="http://localhost:{{ explode(':', $port)[0] }}">Port
|
target="_blank" href="http://localhost:{{ explode(':', $port)[0] }}">
|
||||||
{{ explode(':', $port)[0] }}
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24"
|
||||||
<x-external-link />
|
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M9 15l6 -6" />
|
||||||
|
<path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" />
|
||||||
|
<path
|
||||||
|
d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />
|
||||||
|
</svg>{{ $port }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@else
|
@else
|
||||||
@ -50,7 +66,6 @@ class="mt-1 text-xs text-white normal-case rounded min-w-max dropdown-content me
|
|||||||
<a class="text-xs hover:no-underline hover:bg-coollabs" target="_blank"
|
<a class="text-xs hover:no-underline hover:bg-coollabs" target="_blank"
|
||||||
href="http://{{ $application->destination->server->ip }}:{{ explode(':', $port)[0] }}">Port
|
href="http://{{ $application->destination->server->ip }}:{{ explode(':', $port)[0] }}">Port
|
||||||
{{ $port }}
|
{{ $port }}
|
||||||
<x-external-link />
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
])
|
])
|
||||||
|
|
||||||
<span {{ $attributes->merge(['class' => 'flex flex-col']) }}>
|
<span {{ $attributes->merge(['class' => 'flex flex-col']) }}>
|
||||||
<label for={{ $id }}>
|
<label class="label" for={{ $id }}>
|
||||||
|
<span class="label-text">
|
||||||
@if ($label)
|
@if ($label)
|
||||||
{{ $label }}
|
{{ $label }}
|
||||||
@else
|
@else
|
||||||
@ -14,6 +15,7 @@
|
|||||||
@if ($required)
|
@if ($required)
|
||||||
<span class="text-warning">*</span>
|
<span class="text-warning">*</span>
|
||||||
@endif
|
@endif
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<select {{ $attributes }} wire:model.defer={{ $id }}>
|
<select {{ $attributes }} wire:model.defer={{ $id }}>
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
|
18
resources/views/components/git-icon.blade.php
Normal file
18
resources/views/components/git-icon.blade.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
@props([
|
||||||
|
'git' => null,
|
||||||
|
])
|
||||||
|
|
||||||
|
@if ($git === 'App\Models\GithubApp')
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||||
|
fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" />
|
||||||
|
</svg>
|
||||||
|
@elseif($git === 'App\Models\GitlabApp')
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||||
|
fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M21 14l-9 7l-9 -7l3 -11l3 7h6l3 -7z" />
|
||||||
|
</svg>
|
||||||
|
@endif
|
@ -1 +1 @@
|
|||||||
<span class="loading loading-bars"></span>
|
<span {{ $attributes->class(['bg-warning loading', 'loading-spinner' => !$attributes->has('class')]) }}></span>
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
<div>
|
<div>
|
||||||
@if ($this->activity)
|
@if ($this->activity)
|
||||||
@if ($header)
|
@if ($header)
|
||||||
|
<div class="flex gap-2">
|
||||||
<h2>Logs</h2>
|
<h2>Logs</h2>
|
||||||
|
@if ($isPollingActive)
|
||||||
|
<x-loading />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div
|
<div
|
||||||
class="scrollbar flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 text-xs text-white">
|
class="scrollbar flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 text-xs text-white">
|
||||||
@if ($isPollingActive)
|
|
||||||
<span class="loading loading-bars"></span>
|
|
||||||
@endif
|
|
||||||
<pre class="font-mono whitespace-pre-wrap" @if ($isPollingActive) wire:poll.2000ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($this->activity) }}</pre>
|
<pre class="font-mono whitespace-pre-wrap" @if ($isPollingActive) wire:poll.2000ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($this->activity) }}</pre>
|
||||||
{{-- @else
|
{{-- @else
|
||||||
<pre class="whitespace-pre-wrap">Output will be here...</pre> --}}
|
<pre class="whitespace-pre-wrap">Output will be here...</pre> --}}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Notifications</h2>
|
<h2>Notifications</h2>
|
||||||
<x-forms.button isHighlighted class="text-white normal-case btn btn-xs no-animation btn-primary"
|
<x-forms.button class="text-white normal-case btn btn-xs no-animation btn-primary" wire:click="sendTestNotification">
|
||||||
wire:click="sendTestNotification">
|
|
||||||
Send Test Notifications
|
Send Test Notifications
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,40 +1,114 @@
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@if ($application->status === 'running')
|
<div class="dropdown dropdown-bottom dropdown-hover">
|
||||||
<div class="dropdown dropdown-bottom">
|
<label tabindex="0" class="flex items-center gap-2 cursor-pointer hover:text-white"> Actions
|
||||||
<x-forms.button isHighlighted tabindex="0" class="">
|
|
||||||
Actions
|
|
||||||
<x-chevron-down />
|
<x-chevron-down />
|
||||||
</x-forms.button>
|
|
||||||
<ul tabindex="0"
|
|
||||||
class="mt-1 text-xs text-white normal-case rounded min-w-max dropdown-content menu bg-coolgray-200">
|
|
||||||
<li>
|
|
||||||
<div class="rounded-none hover:bg-coollabs" wire:click='deploy'>Restart</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="rounded-none hover:bg-coollabs" wire:click='deploy(true)'>Force deploy without cache</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="rounded-none hover:bg-red-500" wire:click='stop'>Stop</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="dropdown dropdown-bottom">
|
|
||||||
<label tabindex="0">
|
|
||||||
<x-forms.button isHighlighted>
|
|
||||||
Actions
|
|
||||||
<x-chevron-down />
|
|
||||||
</x-forms.button>
|
|
||||||
</label>
|
</label>
|
||||||
|
@if ($application->status === 'running')
|
||||||
<ul tabindex="0"
|
<ul tabindex="0"
|
||||||
class="mt-1 text-xs text-white normal-case rounded min-w-max dropdown-content menu bg-coolgray-200">
|
class="text-xs text-white normal-case rounded min-w-max dropdown-content menu bg-coolgray-200">
|
||||||
<li>
|
<li>
|
||||||
<div class="rounded-none hover:bg-coollabs" wire:click='deploy'>Deploy</div>
|
<div class="rounded-none hover:bg-coollabs" wire:click='deploy'><svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
|
||||||
|
<path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
|
||||||
|
<path d="M12 9l0 3" />
|
||||||
|
<path d="M12 15l.01 0" />
|
||||||
|
</svg>Restart</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div class="rounded-none hover:bg-coollabs" wire:click='deploy(true)'>Deploy without cache</div>
|
<div class="rounded-none hover:bg-coollabs" wire:click='deploy(true, true)'><svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
|
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M9 9v-1a3 3 0 0 1 6 0v1" />
|
||||||
|
<path d="M8 9h8a6 6 0 0 1 1 3v3a5 5 0 0 1 -10 0v-3a6 6 0 0 1 1 -3" />
|
||||||
|
<path d="M3 13l4 0" />
|
||||||
|
<path d="M17 13l4 0" />
|
||||||
|
<path d="M12 20l0 -6" />
|
||||||
|
<path d="M4 19l3.35 -2" />
|
||||||
|
<path d="M20 19l-3.35 -2" />
|
||||||
|
<path d="M4 7l3.75 2.4" />
|
||||||
|
<path d="M20 7l-3.75 2.4" />
|
||||||
|
</svg>Force deploy (with
|
||||||
|
debug)
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="rounded-none hover:bg-coollabs" wire:click='deploy(true)'><svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
|
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74" />
|
||||||
|
<path
|
||||||
|
d="M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6" />
|
||||||
|
<path d="M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4" />
|
||||||
|
<path d="M3 3l18 18" />
|
||||||
|
</svg>Force deploy (without
|
||||||
|
cache)
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="rounded-none hover:bg-red-500" wire:click='stop'><svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M8 13v-7.5a1.5 1.5 0 0 1 3 0v6.5" />
|
||||||
|
<path d="M11 5.5v-2a1.5 1.5 0 1 1 3 0v8.5" />
|
||||||
|
<path d="M14 5.5a1.5 1.5 0 0 1 3 0v6.5" />
|
||||||
|
<path
|
||||||
|
d="M17 7.5a1.5 1.5 0 0 1 3 0v8.5a6 6 0 0 1 -6 6h-2h.208a6 6 0 0 1 -5.012 -2.7a69.74 69.74 0 0 1 -.196 -.3c-.312 -.479 -1.407 -2.388 -3.286 -5.728a1.5 1.5 0 0 1 .536 -2.022a1.867 1.867 0 0 1 2.28 .28l1.47 1.47" />
|
||||||
|
</svg>Stop</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@else
|
||||||
|
<ul tabindex="0"
|
||||||
|
class="text-xs text-white normal-case rounded min-w-max dropdown-content menu bg-coolgray-200">
|
||||||
|
<li>
|
||||||
|
<div class="rounded-none hover:bg-coollabs" wire:click='deploy'><svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
|
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M7 4v16l13 -8z" />
|
||||||
|
</svg>Deploy</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="rounded-none hover:bg-coollabs" wire:click='deploy(true, true)'><svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
|
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M9 9v-1a3 3 0 0 1 6 0v1" />
|
||||||
|
<path d="M8 9h8a6 6 0 0 1 1 3v3a5 5 0 0 1 -10 0v-3a6 6 0 0 1 1 -3" />
|
||||||
|
<path d="M3 13l4 0" />
|
||||||
|
<path d="M17 13l4 0" />
|
||||||
|
<path d="M12 20l0 -6" />
|
||||||
|
<path d="M4 19l3.35 -2" />
|
||||||
|
<path d="M20 19l-3.35 -2" />
|
||||||
|
<path d="M4 7l3.75 2.4" />
|
||||||
|
<path d="M20 7l-3.75 2.4" />
|
||||||
|
</svg>Force deploy (with
|
||||||
|
debug)
|
||||||
</div>
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="rounded-none hover:bg-coollabs" wire:click='deploy(true)'><svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74" />
|
||||||
|
<path
|
||||||
|
d="M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6" />
|
||||||
|
<path d="M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4" />
|
||||||
|
<path d="M3 3l18 18" />
|
||||||
|
</svg>Force deploy (without
|
||||||
|
cache)
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -2,14 +2,15 @@
|
|||||||
<h2>Logs</h2>
|
<h2>Logs</h2>
|
||||||
<livewire:project.application.deployment-navbar :activity="$activity" :application="$application" :deployment_uuid="$deployment_uuid" />
|
<livewire:project.application.deployment-navbar :activity="$activity" :application="$application" :deployment_uuid="$deployment_uuid" />
|
||||||
@if (data_get($activity, 'properties.status') === 'in_progress')
|
@if (data_get($activity, 'properties.status') === 'in_progress')
|
||||||
<div class="pt-2 text-sm">Deployment is
|
<div class="flex items-center gap-1 pt-2 text-sm">Deployment is
|
||||||
<span class="text-warning">{{ Str::headline(data_get($activity, 'properties.status')) }}</span>. Logs will
|
<div class="text-warning"> {{ Str::headline(data_get($activity, 'properties.status')) }}.</div>
|
||||||
be updated
|
<x-loading class="loading-ring" />
|
||||||
automatically.
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>Logs will be updated automatically.</div>
|
||||||
@else
|
@else
|
||||||
<div class="pt-2 text-sm">Deployment is <span
|
<div class="pt-2 text-sm">Deployment is <span
|
||||||
class="text-warning">{{ Str::headline(data_get($activity, 'properties.status')) }}</span>.</div>
|
class="text-warning">{{ Str::headline(data_get($activity, 'properties.status')) }}</span>.
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div
|
<div
|
||||||
class="scrollbar flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 mt-4 text-xs text-white">
|
class="scrollbar flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 mt-4 text-xs text-white">
|
||||||
|
@ -2,14 +2,11 @@
|
|||||||
@if ($skip == 0) wire:poll.5000ms='reload_deployments' @endif>
|
@if ($skip == 0) wire:poll.5000ms='reload_deployments' @endif>
|
||||||
<h2 class="pt-4">Deployments <span class="text-xs">({{ $deployments_count }})</span></h2>
|
<h2 class="pt-4">Deployments <span class="text-xs">({{ $deployments_count }})</span></h2>
|
||||||
@if (count($deployments) === 0)
|
@if (count($deployments) === 0)
|
||||||
<x-forms.button isHighlighted wire:click="load_deployments({{ $default_take }})">Load Deployments
|
<x-forms.button wire:click="load_deployments({{ $default_take }})">Load Deployments
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
<div wire:loading wire:target='load_deployments'>
|
|
||||||
<x-loading />
|
|
||||||
</div>
|
|
||||||
@if ($show_next)
|
@if ($show_next)
|
||||||
<x-forms.button isHighlighted wire:click="load_deployments({{ $default_take }})">Show More
|
<x-forms.button wire:click="load_deployments({{ $default_take }})">Show More
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
@foreach ($deployments as $deployment)
|
@foreach ($deployments as $deployment)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<div>
|
<div>
|
||||||
<h2>Destination</h2>
|
<h2>Destination</h2>
|
||||||
<div class="text-sm">The destination server / network where your application will be deployed to.</div>
|
<div class="text-sm">The destination server / network where your application will be deployed to.</div>
|
||||||
<div class="py-4">
|
<div class="py-4 text-sm">
|
||||||
<p>Server: {{ data_get($destination, 'server.name') }}</p>
|
<p>Server: {{ data_get($destination, 'server.name') }}</p>
|
||||||
<p>Destination: {{ $destination->network }}</p>
|
<p>Destination Network: {{ $destination->network }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
<form wire:submit.prevent='submit' class="flex flex-col max-w-fit">
|
<form wire:submit.prevent='submit' class="flex flex-col max-w-fit">
|
||||||
<div class="flex gap-2">
|
<div class="flex items-end justify-center gap-2">
|
||||||
<x-forms.input placeholder="NODE_ENV" noDirty id="key" label="Name" required />
|
<x-forms.input placeholder="NODE_ENV" noDirty id="key" label="Name" required />
|
||||||
<x-forms.input placeholder="production" noDirty id="value" label="Value" required />
|
<x-forms.input placeholder="production" noDirty id="value" label="Value" required />
|
||||||
<x-forms.checkbox noDirty class="flex-col items-center" id="is_build_time" label="Build Variable?" />
|
<x-forms.checkbox noDirty class="flex-col text-center w-96" id="is_build_time" label="Build Variable?" />
|
||||||
</div>
|
|
||||||
<div class="pt-2">
|
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Add
|
Add New Variable
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div>
|
<div>
|
||||||
<h2>Environment Variables</h2>
|
<h2>Environment Variables</h2>
|
||||||
<div class="text-sm">Environment (secrets) configuration. You can set variables for your Preview Deployments as
|
<div class="text-sm">Environment (secrets) variables for normal deployments.</div>
|
||||||
well
|
|
||||||
here.</div>
|
|
||||||
</div>
|
</div>
|
||||||
@forelse ($application->environment_variables as $env)
|
@foreach ($application->environment_variables as $env)
|
||||||
<livewire:project.application.environment-variable.show wire:key="environment-{{ $env->id }}"
|
<livewire:project.application.environment-variable.show wire:key="environment-{{ $env->id }}"
|
||||||
:env="$env" />
|
:env="$env" />
|
||||||
@empty
|
@endforeach
|
||||||
<p>There are no environment variables added for this application.</p>
|
<div class="pt-2 pb-8">
|
||||||
@endforelse
|
|
||||||
<div class="pt-10">
|
|
||||||
<livewire:project.application.environment-variable.add />
|
<livewire:project.application.environment-variable.add />
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>Preview Deployments</h3>
|
||||||
|
<div class="text-sm">Environment (secrets) variables for Preview Deployments.</div>
|
||||||
|
</div>
|
||||||
|
@foreach ($application->environment_variables_preview as $env)
|
||||||
|
<livewire:project.application.environment-variable.show wire:key="environment-{{ $env->id }}"
|
||||||
|
:env="$env" />
|
||||||
|
@endforeach
|
||||||
|
<div class="pt-2 pb-8">
|
||||||
|
<livewire:project.application.environment-variable.add is_preview="true" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
<div x-data="{ deleteEnvironment: false }">
|
<div x-data="{ deleteEnvironment: false }">
|
||||||
<form wire:submit.prevent='submit' class="flex flex-col max-w-fit">
|
<form wire:submit.prevent='submit' class="flex flex-col max-w-fit">
|
||||||
<div class="flex gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input label="Name" id="env.key" />
|
<x-forms.input label="Name" id="env.key" />
|
||||||
<x-forms.input label="Value" id="env.value" />
|
<x-forms.input label="Value" id="env.value" />
|
||||||
<x-forms.checkbox disabled class="flex-col items-center" id="env.is_build_time" label="Build Variable?" />
|
<x-forms.checkbox disabled class="flex-col text-center w-96" id="env.is_build_time" label="Build Variable?" />
|
||||||
</div>
|
<div class="flex gap-2">
|
||||||
<div class="pt-2">
|
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Update
|
Update
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@ -13,6 +12,7 @@
|
|||||||
Delete
|
Delete
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<x-naked-modal show="deleteEnvironment" message="Are you sure you want to delete {{ $env->key }}?" />
|
<x-naked-modal show="deleteEnvironment" message="Are you sure you want to delete {{ $env->key }}?" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,11 +18,11 @@
|
|||||||
<div class="pb-6">
|
<div class="pb-6">
|
||||||
<div class="text-sm">Set Random Domain</div>
|
<div class="text-sm">Set Random Domain</div>
|
||||||
@if ($global_wildcard_domain)
|
@if ($global_wildcard_domain)
|
||||||
<x-forms.button isHighlighted wire:click="generateGlobalRandomDomain">Global Wildcard
|
<x-forms.button wire:click="generateGlobalRandomDomain">Global Wildcard
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
@if ($project_wildcard_domain)
|
@if ($project_wildcard_domain)
|
||||||
<x-forms.button isHighlighted wire:click="generateProjectRandomDomain">Project Wildcard
|
<x-forms.button wire:click="generateProjectRandomDomain">Project Wildcard
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,40 +1,69 @@
|
|||||||
<div>
|
<div>
|
||||||
<livewire:project.application.preview.form :application="$application" />
|
<livewire:project.application.preview.form :application="$application" />
|
||||||
<h3>Pull Requests on Git</h3>
|
|
||||||
<div>
|
<div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3>Pull Requests on Git</h3>
|
||||||
<x-forms.button wire:click="load_prs">Load Pull Requests (open)
|
<x-forms.button wire:click="load_prs">Load Pull Requests (open)
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
@isset($rate_limit_remaining)
|
@isset($rate_limit_remaining)
|
||||||
<div class="pt-1 text-sm">Requests remaning till rate limited by Git: {{ $rate_limit_remaining }}</div>
|
<div class="pt-1 text-sm">Requests remaning till rate limited by Git: {{ $rate_limit_remaining }}</div>
|
||||||
@endisset
|
@endisset
|
||||||
@if (count($pull_requests) > 0)
|
@if (count($pull_requests) > 0)
|
||||||
<div wire:loading.remove wire:target='load_prs' class="flex gap-4 py-8">
|
<div wire:loading.remove wire:target='load_prs' class="flex gap-4 py-4">
|
||||||
|
<div class="overflow-x-auto table-md">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr class="text-warning border-coolgray-200">
|
||||||
|
<th>PR Number</th>
|
||||||
|
<th>PR Title</th>
|
||||||
|
<th>Git</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
@foreach ($pull_requests as $pull_request)
|
@foreach ($pull_requests as $pull_request)
|
||||||
<div class="flex flex-col gap-4 p-4 text-sm bg-coolgray-200 hover:bg-coolgray-300">
|
<tr class="border-coolgray-200">
|
||||||
<div class="text-base font-bold text-white">PR #{{ data_get($pull_request, 'number') }} |
|
<th>{{ data_get($pull_request, 'number') }}</th>
|
||||||
{{ data_get($pull_request, 'title') }}</div>
|
<td>{{ data_get($pull_request, 'title') }}</td>
|
||||||
<div class="flex items-center justify-start gap-2">
|
<td>
|
||||||
<x-forms.button isHighlighted
|
<a target="_blank" class="text-xs"
|
||||||
wire:click="deploy('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
|
href="{{ data_get($pull_request, 'html_url') }}">Open PR on
|
||||||
Deploy
|
|
||||||
</x-forms.button>
|
|
||||||
<a target="_blank" class="text-xs" href="{{ data_get($pull_request, 'html_url') }}">Open PR
|
|
||||||
on
|
|
||||||
Git
|
Git
|
||||||
<x-external-link />
|
<x-external-link />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</td>
|
||||||
</div>
|
<td class="flex items-center justify-center gap-2">
|
||||||
|
<x-forms.button
|
||||||
|
wire:click="deploy('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
|
||||||
|
Deploy
|
||||||
|
</x-forms.button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@if ($application->previews->count() > 0)
|
@if ($application->previews->count() > 0)
|
||||||
<h3>Preview Deployments</h3>
|
<h4 class="pt-4">Preview Deployments</h4>
|
||||||
<div class="flex gap-6 text-sm">
|
<div class="flex gap-6 text-sm">
|
||||||
@foreach ($application->previews as $preview)
|
@foreach ($application->previews as $preview)
|
||||||
<div class="flex flex-col p-4 bg-coolgray-200 " x-init="$wire.loadStatus('{{ data_get($preview, 'pull_request_id') }}')">
|
<div class="flex flex-col p-4 bg-coolgray-200 " x-init="$wire.loadStatus('{{ data_get($preview, 'pull_request_id') }}')">
|
||||||
<div>PR #{{ data_get($preview, 'pull_request_id') }} | {{ data_get($preview, 'status') }}
|
<div class="flex gap-2">PR #{{ data_get($preview, 'pull_request_id') }} |
|
||||||
|
@if (data_get($preview, 'status') === 'running')
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div class="badge badge-success badge-xs"></div>
|
||||||
|
<div class="text-xs font-medium tracking-wide">Running</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div class="badge badge-error badge-xs"></div>
|
||||||
|
<div class="text-xs font-medium tracking-wide">Stopped</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@if (data_get($preview, 'status') !== 'exited')
|
@if (data_get($preview, 'status') !== 'exited')
|
||||||
| <a target="_blank" href="{{ data_get($preview, 'fqdn') }}">Open Preview
|
| <a target="_blank" href="{{ data_get($preview, 'fqdn') }}">Open Preview
|
||||||
<x-external-link />
|
<x-external-link />
|
||||||
@ -46,7 +75,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2 pt-6">
|
<div class="flex items-center gap-2 pt-6">
|
||||||
<x-forms.button isHighlighted wire:click="deploy({{ data_get($preview, 'pull_request_id') }})">
|
<x-forms.button wire:click="deploy({{ data_get($preview, 'pull_request_id') }})">
|
||||||
@if (data_get($preview, 'status') === 'exited')
|
@if (data_get($preview, 'status') === 'exited')
|
||||||
Deploy
|
Deploy
|
||||||
@else
|
@else
|
||||||
@ -58,7 +87,6 @@
|
|||||||
Preview
|
Preview
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
<div x-init="$wire.loadImages">
|
<div x-init="$wire.loadImages">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Rollback</h2>
|
<h2>Rollback</h2>
|
||||||
<x-forms.button isHighlighted wire:click='loadImages'>Reload Available Images</x-forms.button>
|
<x-forms.button wire:click='loadImages'>Reload Available Images</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="pb-4 text-sm">You can easily rollback to a previously built image quickly.</div>
|
<div class="pb-4 text-sm">You can easily rollback to a previously built image quickly.</div>
|
||||||
<div wire:loading wire:target='loadImages'>
|
|
||||||
<x-loading />
|
|
||||||
</div>
|
|
||||||
<div wire:loading.remove wire:target='loadImages'>
|
<div wire:loading.remove wire:target='loadImages'>
|
||||||
<div class="flex flex-wrap">
|
<div class="flex flex-wrap">
|
||||||
@forelse ($images as $image)
|
@forelse ($images as $image)
|
||||||
@ -28,8 +25,7 @@
|
|||||||
Rollback
|
Rollback
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@else
|
@else
|
||||||
<x-forms.button isHighlighted
|
<x-forms.button wire:click="rollbackImage('{{ data_get($image, 'tag') }}')">
|
||||||
wire:click="rollbackImage('{{ data_get($image, 'tag') }}')">
|
|
||||||
Rollback
|
Rollback
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
|
@ -1,25 +1,32 @@
|
|||||||
<div>
|
<div>
|
||||||
<form wire:submit.prevent='submit' class="flex flex-col">
|
<form wire:submit.prevent='submit' class="flex flex-col w-96">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Source</h2>
|
<h2>Source</h2>
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
|
<a target="_blank" class="hover:no-underline" href="{{ $application->gitBranchLocation }}">
|
||||||
|
<x-forms.button>
|
||||||
|
<x-git-icon git="{{ $application->source->getMorphClass() }}" />Open Repository on Git
|
||||||
|
<x-external-link />
|
||||||
|
</x-forms.button>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm">Code source of your application.</div>
|
<div class="text-sm">Code source of your application.</div>
|
||||||
<div class="py-4 ">
|
|
||||||
<a target="_blank" class="hover:no-underline" href="{{ $application->gitCommits }}">
|
|
||||||
<x-forms.button>Open Commits on Git
|
|
||||||
<x-external-link />
|
|
||||||
</x-forms.button>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" class="hover:no-underline" href="{{ $application->gitBranchLocation }}">
|
|
||||||
<x-forms.button>Open Repository on Git
|
|
||||||
<x-external-link />
|
|
||||||
</x-forms.button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<x-forms.input placeholder="coollabsio/coolify-example" id="application.git_repository" label="Repository" />
|
<x-forms.input placeholder="coollabsio/coolify-example" id="application.git_repository" label="Repository" />
|
||||||
<x-forms.input placeholder="main" id="application.git_branch" label="Branch" />
|
<x-forms.input placeholder="main" id="application.git_branch" label="Branch" />
|
||||||
|
<div class="flex items-end gap-2 w-96">
|
||||||
<x-forms.input placeholder="HEAD" id="application.git_commit_sha" placeholder="HEAD" label="Commit SHA" />
|
<x-forms.input placeholder="HEAD" id="application.git_commit_sha" placeholder="HEAD" label="Commit SHA" />
|
||||||
|
<a target="_blank" class="flex hover:no-underline" href="{{ $application->gitCommits }}">
|
||||||
|
<x-forms.button><svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M12 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
|
||||||
|
<path d="M12 3l0 6" />
|
||||||
|
<path d="M12 15l0 6" />
|
||||||
|
</svg>Open Commits on Git
|
||||||
|
<x-external-link />
|
||||||
|
</x-forms.button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
<div wire:poll.5000ms='applicationStatusChanged'>
|
<div wire:poll.5000ms='applicationStatusChanged'>
|
||||||
@if ($application->status === 'running')
|
@if ($application->status === 'running')
|
||||||
<span class="text-xs text-pink-600" wire:loading.delay.longer>Loading current status...</span>
|
<x-loading wire:loading.delay.longer />
|
||||||
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
||||||
<div class="text-xs font-medium tracking-wide text-white badge border-success">Running</div>
|
<div class="badge badge-success badge-xs"></div>
|
||||||
|
<div class="text-xs font-medium tracking-wide">Running</div>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<span class="text-xs text-pink-600" wire:loading.delay.longer>Loading current status...</span>
|
<x-loading wire:loading.delay.longer />
|
||||||
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
||||||
<div class="text-xs font-medium tracking-wide text-white badge border-error">Stopped</div>
|
<div class="badge badge-error badge-xs"></div>
|
||||||
|
<div class="text-xs font-medium tracking-wide">Stopped</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<form wire:submit.prevent='submit' class="flex flex-col px-2 pt-10 max-w-fit">
|
<form wire:submit.prevent='submit' class="flex flex-col w-full px-2">
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input placeholder="pv-name" noDirty id="name" label="Name" required />
|
<x-forms.input placeholder="pv-name" noDirty id="name" label="Name" required />
|
||||||
<x-forms.input placeholder="/root" noDirty id="host_path" label="Source Path" />
|
<x-forms.input placeholder="/root" noDirty id="host_path" label="Source Path" />
|
||||||
<x-forms.input placeholder="/tmp/root" noDirty id="mount_path" label="Destination Path" required />
|
<x-forms.input placeholder="/tmp/root" noDirty id="mount_path" label="Destination Path" required />
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Add
|
Add New Volume
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<h2>Storages</h2>
|
<h2>Storages</h2>
|
||||||
<div class="text-sm">Persistent storage to preserve data between deployments.</div>
|
<div class="text-sm">Persistent storage to preserve data between deployments.</div>
|
||||||
|
<div class="text-sm">Preview Deployments has a <span class='text-helper'>-pr-#PRNumber</span> in their
|
||||||
|
volume
|
||||||
|
name, example: <span class='text-helper'>-pr-1</span>.</div>
|
||||||
|
</div>
|
||||||
<div class="flex flex-col gap-2 py-4">
|
<div class="flex flex-col gap-2 py-4">
|
||||||
@forelse ($application->persistentStorages as $storage)
|
@forelse ($application->persistentStorages as $storage)
|
||||||
<livewire:project.application.storages.show wire:key="storage-{{ $storage->id }}" :storage="$storage" />
|
<livewire:project.application.storages.show wire:key="storage-{{ $storage->id }}" :storage="$storage" />
|
||||||
|
@ -1,10 +1,28 @@
|
|||||||
<div>
|
<div>
|
||||||
<h1>Enter a public repository URL</h1>
|
<h1>Enter a public repository URL</h1>
|
||||||
<form class="flex flex-col gap-2" wire:submit.prevent='submit'>
|
<form class="flex flex-col gap-2" wire:submit.prevent='submit'>
|
||||||
<x-forms.checkbox instantSave id="is_static" label="Is it a static site?" />
|
<div class="flex flex-col gap-2">
|
||||||
<div class="flex gap-2">
|
<div class="flex flex-col">
|
||||||
<x-forms.input id="repository_url" label="Repository URL"
|
<div class="flex items-end gap-2">
|
||||||
|
<x-forms.input wire:keypress.enter='load_branches' id="repository_url" label="Repository URL"
|
||||||
helper="<span class='text-helper'>Example</span>https://github.com/coollabsio/coolify-examples => main branch will be selected<br>https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify => nodejs-fastify branch will be selected" />
|
helper="<span class='text-helper'>Example</span>https://github.com/coollabsio/coolify-examples => main branch will be selected<br>https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify => nodejs-fastify branch will be selected" />
|
||||||
|
<x-forms.button wire:click.prevent="load_branches">
|
||||||
|
Check repository
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
@if (count($branches) > 0)
|
||||||
|
<x-forms.select id="selected_branch" label="Branch">
|
||||||
|
<option value="default" disabled selected>Select a branch</option>
|
||||||
|
@foreach ($branches as $branch)
|
||||||
|
<option value="{{ $branch }}">{{ $branch }}</option>
|
||||||
|
@endforeach
|
||||||
|
</x-forms.select>
|
||||||
|
@else
|
||||||
|
<x-forms.select id="branch" label="Branch" disabled>
|
||||||
|
<option value="default" selected>Set a repository first</option>
|
||||||
|
</x-forms.select>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
@if ($is_static)
|
@if ($is_static)
|
||||||
<x-forms.input id="publish_directory" label="Publish Directory"
|
<x-forms.input id="publish_directory" label="Publish Directory"
|
||||||
helper="If there is a build process involved (like Svelte, React, Next, etc..), please specify the output directory for the build assets." />
|
helper="If there is a build process involved (like Svelte, React, Next, etc..), please specify the output directory for the build assets." />
|
||||||
@ -12,9 +30,18 @@
|
|||||||
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static"
|
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static"
|
||||||
helper="The port your application listens on." />
|
helper="The port your application listens on." />
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<x-forms.checkbox instantSave id="is_static" label="Is it a static site?" />
|
||||||
|
@if (count($branches) > 0)
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Submit
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
|
@else
|
||||||
|
<x-forms.button disabled type="submit">
|
||||||
|
Save
|
||||||
|
</x-forms.button>
|
||||||
|
@endif
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@if (!$server->settings->is_validated)
|
@if (!$server->settings->is_validated)
|
||||||
<x-forms.button class="mt-4" isHighlighted wire:click.prevent='validateServer'>
|
<x-forms.button class="mt-4" wire:click.prevent='validateServer'>
|
||||||
Validate Server
|
Validate Server
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
@if ($server->settings->is_validated)
|
@if ($server->settings->is_validated)
|
||||||
@if ($server->extra_attributes->proxy_status === 'running')
|
@if ($server->extra_attributes->proxy_status === 'running')
|
||||||
<div class="dropdown dropdown-bottom">
|
<div class="dropdown dropdown-bottom">
|
||||||
<x-forms.button isHighlighted tabindex="0">
|
<x-forms.button tabindex="0">
|
||||||
Actions
|
Actions
|
||||||
<x-chevron-down />
|
<x-chevron-down />
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@ -33,9 +33,9 @@ class="mt-1 text-xs text-white normal-case rounded min-w-max dropdown-content me
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<x-forms.button isHighlighted wire:click='deploy'> <svg xmlns="http://www.w3.org/2000/svg" class="icon"
|
<x-forms.button wire:click='deploy'> <svg xmlns="http://www.w3.org/2000/svg" class="icon" width="44"
|
||||||
width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none"
|
||||||
fill="none" stroke-linecap="round" stroke-linejoin="round">
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M7 4v16l13 -8z" />
|
<path d="M7 4v16l13 -8z" />
|
||||||
</svg>Start</x-forms.button>
|
</svg>Start</x-forms.button>
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
@if ($server->settings->is_validated)
|
@if ($server->settings->is_validated)
|
||||||
<div wire:poll.5000ms="proxyStatus">
|
<div wire:poll.5000ms="proxyStatus">
|
||||||
@if ($server->extra_attributes->proxy_status === 'running')
|
@if ($server->extra_attributes->proxy_status === 'running')
|
||||||
<span class="text-xs text-pink-600" wire:loading.delay.longer>Loading current status...</span>
|
<x-loading wire:loading.delay.longer />
|
||||||
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
||||||
<div class="text-xs font-medium tracking-wide text-white badge border-success">Running</div>
|
<div class="text-xs font-medium tracking-wide text-white badge border-success">Running</div>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<span class="text-xs text-pink-600" wire:loading.delay.longer>Loading current status...</span>
|
<x-loading wire:loading.delay.longer />
|
||||||
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
<div class="flex items-center gap-2 text-sm" wire:loading.remove.delay.longer>
|
||||||
<div class="text-xs font-medium tracking-wide text-white badge border-error">Stopped</div>
|
<div class="text-xs font-medium tracking-wide text-white badge border-error">Stopped</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<div class="text-sm">You need to register a GitHub App before using this source!</div>
|
<div class="text-sm">You need to register a GitHub App before using this source!</div>
|
||||||
<form>
|
<form>
|
||||||
<x-forms.button isHighlighted x-on:click.prevent="createGithubApp">Register a GitHub
|
<x-forms.button x-on:click.prevent="createGithubApp">Register a GitHub
|
||||||
Application
|
Application
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div>
|
<div class="w-64 -mt-9">
|
||||||
<x-forms.select wire:model="selectedTeamId" class="w-64 select-xs">
|
<x-forms.select wire:model="selectedTeamId" class="pr-0 select-xs ">
|
||||||
<option value="default" disabled selected>Switch team</option>
|
<option value="default" disabled selected>Switch team</option>
|
||||||
@foreach (auth()->user()->teams as $team)
|
@foreach (auth()->user()->teams as $team)
|
||||||
<option value="{{ $team->id }}">{{ $team->name }}</option>
|
<option value="{{ $team->id }}">{{ $team->name }}</option>
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a>
|
href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>{{ data_get($application, 'name') }}</li>
|
<li>{{ data_get($application, 'name') }}</li>
|
||||||
|
<li>
|
||||||
|
<livewire:project.application.status :application="$application" />
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<x-applications.navbar :application="$application" />
|
<x-applications.navbar :application="$application" />
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a>
|
href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>{{ data_get($application, 'name') }}</li>
|
<li>{{ data_get($application, 'name') }}</li>
|
||||||
|
<li>
|
||||||
|
<livewire:project.application.status :application="$application" />
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<x-applications.navbar :application="$application" />
|
<x-applications.navbar :application="$application" />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<x-layout>
|
<x-layout>
|
||||||
<h1>Deployments</h1>
|
<h1>Deployments</h1>
|
||||||
<div class="pb-10 text-sm breadcrumbs">
|
<div class="pb-10 text-sm breadcrumbs">
|
||||||
<ul>`
|
<ul>
|
||||||
<li><a
|
<li><a
|
||||||
href="{{ route('project.show', ['project_uuid' => request()->route('project_uuid')]) }}">{{ $application->environment->project->name }}</a>
|
href="{{ route('project.show', ['project_uuid' => request()->route('project_uuid')]) }}">{{ $application->environment->project->name }}</a>
|
||||||
</li>
|
</li>
|
||||||
@ -9,6 +9,9 @@
|
|||||||
href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a>
|
href="{{ route('project.resources', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>{{ data_get($application, 'name') }}</li>
|
<li>{{ data_get($application, 'name') }}</li>
|
||||||
|
<li>
|
||||||
|
<livewire:project.application.status :application="$application" />
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<x-applications.navbar :application="$application" />
|
<x-applications.navbar :application="$application" />
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<h2>Invite a new member</h2>
|
<h2>Invite a new member</h2>
|
||||||
<form class="flex items-center gap-2">
|
<form class="flex items-center gap-2">
|
||||||
<x-forms.input type="email" name="email" placeholder="Email" />
|
<x-forms.input type="email" name="email" placeholder="Email" />
|
||||||
<x-forms.button isHighlighted>Invite</x-forms.button>
|
<x-forms.button>Invite</x-forms.button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</x-layout>
|
</x-layout>
|
||||||
|
Loading…
Reference in New Issue
Block a user