feat: init version of any git deployment

This commit is contained in:
Andras Bacsai 2023-10-06 13:46:42 +02:00
parent 3adeb2f73f
commit 5b56c50f03
9 changed files with 94 additions and 50 deletions

View File

@ -25,7 +25,7 @@ public function mount()
public function load_prs() public function load_prs()
{ {
try { try {
['rate_limit_remaining' => $rate_limit_remaining, 'data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/pulls"); ['rate_limit_remaining' => $rate_limit_remaining, 'data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/pulls");
$this->rate_limit_remaining = $rate_limit_remaining; $this->rate_limit_remaining = $rate_limit_remaining;
$this->pull_requests = $data->sortBy('number')->values(); $this->pull_requests = $data->sortBy('number')->values();
} catch (\Throwable $e) { } catch (\Throwable $e) {

View File

@ -27,9 +27,10 @@ class PublicGitRepository extends Component
public int $rate_limit_remaining = 0; public int $rate_limit_remaining = 0;
public $rate_limit_reset = 0; public $rate_limit_reset = 0;
private object $repository_url_parsed; private object $repository_url_parsed;
public GithubApp|GitlabApp|null $git_source = null; public GithubApp|GitlabApp|string $git_source = 'other';
public string $git_host; public string $git_host;
public string $git_repository; public string $git_repository;
protected $rules = [ protected $rules = [
'repository_url' => 'required|url', 'repository_url' => 'required|url',
'port' => 'required|numeric', 'port' => 'required|numeric',
@ -64,7 +65,10 @@ public function instantSave()
} }
$this->emit('success', 'Application settings updated!'); $this->emit('success', 'Application settings updated!');
} }
public function load_any_git()
{
$this->branch_found = true;
}
public function load_branch() public function load_branch()
{ {
try { try {
@ -99,21 +103,22 @@ private function get_git_source()
if ($this->git_host == 'github.com') { if ($this->git_host == 'github.com') {
$this->git_source = GithubApp::where('name', 'Public GitHub')->first(); $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
}
if (is_null($this->git_source)) {
throw new \Exception('Git source not found. What?!');
} }
$this->git_repository = $this->repository_url;
$this->git_source = 'other';
} }
private function get_branch() private function get_branch()
{ {
['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = git_api(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}"); if ($this->git_source === 'other') {
$this->rate_limit_reset = Carbon::parse((int)$this->rate_limit_reset)->format('Y-M-d H:i:s'); $this->branch_found = true;
$this->branch_found = true; return;
}
if ($this->git_source->getMorphClass() === 'App\Models\GithubApp') {
['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = githubApi(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}");
$this->rate_limit_reset = Carbon::parse((int)$this->rate_limit_reset)->format('Y-M-d H:i:s');
$this->branch_found = true;
}
} }
public function submit() public function submit()
@ -136,19 +141,34 @@ public function submit()
$project = Project::where('uuid', $project_uuid)->first(); $project = Project::where('uuid', $project_uuid)->first();
$environment = $project->load(['environments'])->environments->where('name', $environment_name)->first(); $environment = $project->load(['environments'])->environments->where('name', $environment_name)->first();
$application_init = [ if ($this->git_source === 'other') {
'name' => generate_application_name($this->git_repository, $this->git_branch), $application_init = [
'git_repository' => $this->git_repository, 'name' => generate_application_name($this->git_repository, $this->git_branch),
'git_branch' => $this->git_branch, 'git_repository' => $this->git_repository,
'build_pack' => 'nixpacks', 'git_branch' => $this->git_branch,
'ports_exposes' => $this->port, 'build_pack' => 'nixpacks',
'publish_directory' => $this->publish_directory, 'ports_exposes' => $this->port,
'environment_id' => $environment->id, 'publish_directory' => $this->publish_directory,
'destination_id' => $destination->id, 'environment_id' => $environment->id,
'destination_type' => $destination_class, 'destination_id' => $destination->id,
'source_id' => $this->git_source->id, 'destination_type' => $destination_class,
'source_type' => $this->git_source->getMorphClass() ];
]; } else {
$application_init = [
'name' => generate_application_name($this->git_repository, $this->git_branch),
'git_repository' => $this->git_repository,
'git_branch' => $this->git_branch,
'build_pack' => 'nixpacks',
'ports_exposes' => $this->port,
'publish_directory' => $this->publish_directory,
'environment_id' => $environment->id,
'destination_id' => $destination->id,
'destination_type' => $destination_class,
'source_id' => $this->git_source->id,
'source_type' => $this->git_source->getMorphClass()
];
}
$application = Application::create($application_init); $application = Application::create($application_init);

View File

@ -45,7 +45,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
private string $commit; private string $commit;
private bool $force_rebuild; private bool $force_rebuild;
private GithubApp|GitlabApp $source; private GithubApp|GitlabApp|string $source = 'other';
private StandaloneDocker|SwarmDocker $destination; private StandaloneDocker|SwarmDocker $destination;
private Server $server; private Server $server;
private ApplicationPreview|null $preview = null; private ApplicationPreview|null $preview = null;
@ -80,7 +80,10 @@ public function __construct(int $application_deployment_queue_id)
$this->commit = $this->application_deployment_queue->commit; $this->commit = $this->application_deployment_queue->commit;
$this->force_rebuild = $this->application_deployment_queue->force_rebuild; $this->force_rebuild = $this->application_deployment_queue->force_rebuild;
$this->source = $this->application->source->getMorphClass()::where('id', $this->application->source->id)->first(); $source = data_get($this->application, 'source');
if ($source) {
$this->source = $source->getMorphClass()::where('id', $this->application->source->id)->first();
}
$this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first(); $this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first();
$this->server = $this->destination->server; $this->server = $this->destination->server;
@ -89,7 +92,7 @@ public function __construct(int $application_deployment_queue_id)
$this->configuration_dir = application_configuration_dir() . "/{$this->application->uuid}"; $this->configuration_dir = application_configuration_dir() . "/{$this->application->uuid}";
$this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->is_debug_enabled = $this->application->settings->is_debug_enabled;
ray($this->basedir,$this->workdir); ray($this->basedir, $this->workdir);
$this->container_name = generateApplicationContainerName($this->application, $this->pull_request_id); $this->container_name = generateApplicationContainerName($this->application, $this->pull_request_id);
savePrivateKeyToFs($this->server); savePrivateKeyToFs($this->server);
$this->saved_outputs = collect(); $this->saved_outputs = collect();
@ -425,6 +428,7 @@ private function importing_git_repository()
$pr_branch_name = "pr-{$this->pull_request_id}-coolify"; $pr_branch_name = "pr-{$this->pull_request_id}-coolify";
} }
if ($this->application->deploymentType() === 'source') { if ($this->application->deploymentType() === 'source') {
$source_html_url = data_get($this->application, 'source.html_url'); $source_html_url = data_get($this->application, 'source.html_url');
$url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL)); $url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL));
@ -459,6 +463,13 @@ private function importing_git_repository()
]); ]);
return $commands->implode(' && '); return $commands->implode(' && ');
} }
if ($this->application->deploymentType() === 'other') {
$git_clone_command = "{$git_clone_command} {$this->application->git_repository} {$this->basedir}";
$git_clone_command = $this->set_git_import_settings($git_clone_command);
$commands->push(executeInDocker($this->deployment_uuid, $git_clone_command));
ray($commands);
return $commands->implode(' && ');
}
} }
private function set_git_import_settings($git_clone_command) private function set_git_import_settings($git_clone_command)

View File

@ -66,7 +66,7 @@ public function handle()
private function update_comment() private function update_comment()
{ {
['data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'patch', data: [ ['data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'patch', data: [
'body' => $this->body, 'body' => $this->body,
], throwError: false); ], throwError: false);
if (data_get($data, 'message') === 'Not Found') { if (data_get($data, 'message') === 'Not Found') {
@ -77,7 +77,7 @@ private function update_comment()
private function create_comment() private function create_comment()
{ {
['data' => $data] = git_api(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->pull_request_id}/comments", method: 'post', data: [
'body' => $this->body, 'body' => $this->body,
]); ]);
$this->preview->pull_request_issue_comment_id = $data['id']; $this->preview->pull_request_issue_comment_id = $data['id'];

View File

@ -68,6 +68,7 @@ public function gitBranchLocation(): Attribute
if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) { if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) {
return "{$this->source->html_url}/{$this->git_repository}/tree/{$this->git_branch}"; return "{$this->source->html_url}/{$this->git_repository}/tree/{$this->git_branch}";
} }
return $this->git_repository;
} }
); );
@ -80,6 +81,7 @@ public function gitCommits(): Attribute
if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) { if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) {
return "{$this->source->html_url}/{$this->git_repository}/commits/{$this->git_branch}"; return "{$this->source->html_url}/{$this->git_repository}/commits/{$this->git_branch}";
} }
return $this->git_repository;
} }
); );
} }
@ -224,6 +226,8 @@ public function deploymentType()
return 'deploy_key'; return 'deploy_key';
} else if (data_get($this, 'source')) { } else if (data_get($this, 'source')) {
return 'source'; return 'source';
} else {
return 'other';
} }
throw new \Exception('No deployment type found'); throw new \Exception('No deployment type found');
} }
@ -239,6 +243,9 @@ public function git_based(): bool
if ($this->dockerfile) { if ($this->dockerfile) {
return false; return false;
} }
if (is_null($this->source)) {
return false;
}
return true; return true;
} }
public function isHealthcheckDisabled(): bool public function isHealthcheckDisabled(): bool

View File

@ -50,7 +50,7 @@ function generate_github_jwt_token(GithubApp $source)
return $issuedToken; return $issuedToken;
} }
function git_api(GithubApp|GitlabApp $source, string $endpoint, string $method = 'get', array|null $data = null, bool $throwError = true) function githubApi(GithubApp|GitlabApp $source, string $endpoint, string $method = 'get', array|null $data = null, bool $throwError = true)
{ {
if ($source->getMorphClass() == 'App\Models\GithubApp') { if ($source->getMorphClass() == 'App\Models\GithubApp') {
if ($source->is_public) { if ($source->is_public) {

View File

@ -8,9 +8,9 @@ ARG DOCKER_COMPOSE_VERSION=2.21.0
# https://github.com/docker/buildx/releases # https://github.com/docker/buildx/releases
ARG DOCKER_BUILDX_VERSION=0.11.2 ARG DOCKER_BUILDX_VERSION=0.11.2
# https://github.com/buildpacks/pack/releases # https://github.com/buildpacks/pack/releases
ARG PACK_VERSION=0.30.0 ARG PACK_VERSION=0.31.0
# https://github.com/railwayapp/nixpacks/releases # https://github.com/railwayapp/nixpacks/releases
ARG NIXPACKS_VERSION=1.16.0 ARG NIXPACKS_VERSION=1.17.0
USER root USER root
WORKDIR /artifacts WORKDIR /artifacts

View File

@ -19,19 +19,28 @@
</x-forms.button> </x-forms.button>
</div> </div>
@if (!$application->dockerfile) @if (!$application->dockerfile)
<div class="flex items-end gap-2"> <div class="flex flex-col gap-2">
<x-forms.select id="application.build_pack" label="Build Pack" required> <div class="flex gap-2">
<option value="nixpacks">Nixpacks</option> <x-forms.select id="application.build_pack" label="Build Pack" required>
<option value="dockerfile">Dockerfile</option> <option value="nixpacks">Nixpacks</option>
</x-forms.select> <option value="dockerfile">Dockerfile</option>
</x-forms.select>
@if ($application->settings->is_static)
<x-forms.select id="application.static_image" label="Static Image" required>
<option value="nginx:alpine">nginx:alpine</option>
<option disabled value="apache:alpine">apache:alpine</option>
</x-forms.select>
@endif
</div>
@if ($application->could_set_build_commands())
<div class="w-64">
<x-forms.checkbox instantSave id="is_static" label="Is it a static site?"
helper="If your application is a static site or the final build assets should be served as a static site, enable this." />
</div>
@endif
</div> </div>
@endif @endif
@if ($application->settings->is_static)
<x-forms.select id="application.static_image" label="Static Image" required>
<option value="nginx:alpine">nginx:alpine</option>
<option disabled value="apache:alpine">apache:alpine</option>
</x-forms.select>
@endif
@if ($application->could_set_build_commands()) @if ($application->could_set_build_commands())
<h3>Build</h3> <h3>Build</h3>
<div class="flex flex-col gap-2 xl:flex-row"> <div class="flex flex-col gap-2 xl:flex-row">
@ -69,10 +78,7 @@
</div> </div>
<h3>Advanced</h3> <h3>Advanced</h3>
<div class="flex flex-col"> <div class="flex flex-col">
@if ($application->could_set_build_commands())
<x-forms.checkbox instantSave id="is_static" label="Is it a static site?"
helper="If your application is a static site or the final build assets should be served as a static site, enable this." />
@endif
<x-forms.checkbox <x-forms.checkbox
helper="Your application will be available only on https if your domain starts with https://..." helper="Your application will be available only on https if your domain starts with https://..."
instantSave id="is_force_https_enabled" label="Force Https" /> instantSave id="is_force_https_enabled" label="Force Https" />

View File

@ -9,7 +9,7 @@
<x-external-link /> <x-external-link />
</x-forms.button> </x-forms.button>
</a> </a>
@if (!$application->source->is_public) @if (data_get($application, 'source.is_public') === false)
<a target="_blank" class="hover:no-underline" href="{{ get_installation_path($application->source) }}"> <a target="_blank" class="hover:no-underline" href="{{ get_installation_path($application->source) }}">
<x-forms.button> <x-forms.button>
Open Git App Open Git App