mirror of
https://github.com/vitodeploy/vito.git
synced 2025-04-20 02:11:36 +00:00
parent
700cc5f44c
commit
1bf3c94358
35
app/Actions/Site/UpdateSourceControl.php
Executable file
35
app/Actions/Site/UpdateSourceControl.php
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Site;
|
||||||
|
|
||||||
|
use App\Models\Site;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
class UpdateSourceControl
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function update(Site $site, array $input): void
|
||||||
|
{
|
||||||
|
$this->validate($input);
|
||||||
|
|
||||||
|
$site->source_control_id = $input['source_control'];
|
||||||
|
$site->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function validate(array $input): void
|
||||||
|
{
|
||||||
|
Validator::make($input, [
|
||||||
|
'source_control' => [
|
||||||
|
'required',
|
||||||
|
Rule::exists('source_controls', 'id'),
|
||||||
|
],
|
||||||
|
])->validate();
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,4 @@ final class SourceControl extends Enum
|
|||||||
const GITLAB = 'gitlab';
|
const GITLAB = 'gitlab';
|
||||||
|
|
||||||
const BITBUCKET = 'bitbucket';
|
const BITBUCKET = 'bitbucket';
|
||||||
|
|
||||||
const CUSTOM = 'custom';
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
class SourceControlIsNotConnected extends Exception
|
class SourceControlIsNotConnected extends Exception
|
||||||
{
|
{
|
||||||
public function __construct(protected SourceControl|string $sourceControl, string $message = null)
|
public function __construct(protected SourceControl|string|null $sourceControl, string $message = null)
|
||||||
{
|
{
|
||||||
parent::__construct($message ?? 'Source control is not connected');
|
parent::__construct($message ?? 'Source control is not connected');
|
||||||
}
|
}
|
||||||
|
39
app/Http/Controllers/GitHookController.php
Normal file
39
app/Http/Controllers/GitHookController.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
|
use App\Models\GitHook;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class GitHookController extends Controller
|
||||||
|
{
|
||||||
|
public function __invoke(Request $request)
|
||||||
|
{
|
||||||
|
if (! $request->input('secret')) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var GitHook $gitHook */
|
||||||
|
$gitHook = GitHook::query()
|
||||||
|
->where('secret', $request->input('secret'))
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
foreach ($gitHook->actions as $action) {
|
||||||
|
if ($action == 'deploy') {
|
||||||
|
try {
|
||||||
|
$gitHook->site->deploy();
|
||||||
|
} catch (SourceControlIsNotConnected) {
|
||||||
|
// TODO: send notification
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::error('git-hook-exception', (array) $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
60
app/Http/Livewire/Application/AutoDeployment.php
Normal file
60
app/Http/Livewire/Application/AutoDeployment.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire\Application;
|
||||||
|
|
||||||
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Traits\HasToast;
|
||||||
|
use App\Traits\RefreshComponentOnBroadcast;
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Livewire\Component;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class AutoDeployment extends Component
|
||||||
|
{
|
||||||
|
use RefreshComponentOnBroadcast;
|
||||||
|
use HasToast;
|
||||||
|
|
||||||
|
public Site $site;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function enable(): void
|
||||||
|
{
|
||||||
|
if (! $this->site->auto_deployment) {
|
||||||
|
try {
|
||||||
|
$this->site->enableAutoDeployment();
|
||||||
|
|
||||||
|
$this->site->refresh();
|
||||||
|
|
||||||
|
$this->toast()->success(__('Auto deployment has been enabled.'));
|
||||||
|
} catch (SourceControlIsNotConnected) {
|
||||||
|
$this->toast()->error(__('Source control is not connected. Check site\'s settings.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function disable(): void
|
||||||
|
{
|
||||||
|
if ($this->site->auto_deployment) {
|
||||||
|
try {
|
||||||
|
$this->site->disableAutoDeployment();
|
||||||
|
|
||||||
|
$this->site->refresh();
|
||||||
|
|
||||||
|
$this->toast()->success(__('Auto deployment has been disabled.'));
|
||||||
|
} catch (SourceControlIsNotConnected) {
|
||||||
|
$this->toast()->error(__('Source control is not connected. Check site\'s settings.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
return view('livewire.application.auto-deployment');
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ public function save(): void
|
|||||||
session()->flash('status', 'script-updated');
|
session()->flash('status', 'script-updated');
|
||||||
|
|
||||||
$this->emitTo(Deploy::class, '$refresh');
|
$this->emitTo(Deploy::class, '$refresh');
|
||||||
|
$this->emitTo(AutoDeployment::class, '$refresh');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(): View
|
public function render(): View
|
||||||
|
31
app/Http/Livewire/Sites/UpdateSourceControlProvider.php
Normal file
31
app/Http/Livewire/Sites/UpdateSourceControlProvider.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire\Sites;
|
||||||
|
|
||||||
|
use App\Actions\Site\UpdateSourceControl;
|
||||||
|
use App\Models\Site;
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class UpdateSourceControlProvider extends Component
|
||||||
|
{
|
||||||
|
public Site $site;
|
||||||
|
|
||||||
|
public ?int $source_control = null;
|
||||||
|
|
||||||
|
public function update(): void
|
||||||
|
{
|
||||||
|
app(UpdateSourceControl::class)->update($this->site, $this->all());
|
||||||
|
|
||||||
|
session()->flash('status', 'source-control-updated');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
if (! $this->source_control) {
|
||||||
|
$this->source_control = $this->site->source_control_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('livewire.sites.update-source-control-provider');
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Exceptions\FailedToDeployGitHook;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@ -22,6 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
class GitHook extends AbstractModel
|
class GitHook extends AbstractModel
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'site_id',
|
'site_id',
|
||||||
'source_control_id',
|
'source_control_id',
|
||||||
@ -55,9 +57,6 @@ public function scopeHasEvent(Builder $query, string $event): Builder
|
|||||||
return $query->where('events', 'like', "%\"{$event}\"%");
|
return $query->where('events', 'like', "%\"{$event}\"%");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws FailedToDeployGitHook
|
|
||||||
*/
|
|
||||||
public function deployHook(): void
|
public function deployHook(): void
|
||||||
{
|
{
|
||||||
$this->update(
|
$this->update(
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
use App\Enums\DeploymentStatus;
|
use App\Enums\DeploymentStatus;
|
||||||
use App\Enums\SiteStatus;
|
use App\Enums\SiteStatus;
|
||||||
use App\Enums\SslStatus;
|
use App\Enums\SslStatus;
|
||||||
use App\Exceptions\FailedToDeployGitHook;
|
|
||||||
use App\Exceptions\SourceControlIsNotConnected;
|
use App\Exceptions\SourceControlIsNotConnected;
|
||||||
use App\Jobs\Site\ChangePHPVersion;
|
use App\Jobs\Site\ChangePHPVersion;
|
||||||
use App\Jobs\Site\Deploy;
|
use App\Jobs\Site\Deploy;
|
||||||
@ -19,7 +18,7 @@
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Support\Str;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -341,22 +340,16 @@ public function getWebDirectoryPathAttribute(): string
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws SourceControlIsNotConnected
|
* @throws SourceControlIsNotConnected
|
||||||
* @throws ValidationException
|
|
||||||
* @throws FailedToDeployGitHook
|
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function enableAutoDeployment(): void
|
public function enableAutoDeployment(): void
|
||||||
{
|
{
|
||||||
if ($this->gitHook) {
|
if ($this->gitHook) {
|
||||||
throw ValidationException::withMessages([
|
return;
|
||||||
'auto_deployment' => __('Auto deployment already enabled'),
|
|
||||||
])->errorBag('auto_deployment');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $this->sourceControl()) {
|
if (! $this->sourceControl()) {
|
||||||
throw ValidationException::withMessages([
|
throw new SourceControlIsNotConnected($this->source_control);
|
||||||
'auto_deployment' => __('Your application does not use any source controls'),
|
|
||||||
])->errorBag('auto_deployment');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -364,7 +357,7 @@ public function enableAutoDeployment(): void
|
|||||||
$gitHook = new GitHook([
|
$gitHook = new GitHook([
|
||||||
'site_id' => $this->id,
|
'site_id' => $this->id,
|
||||||
'source_control_id' => $this->sourceControl()->id,
|
'source_control_id' => $this->sourceControl()->id,
|
||||||
'secret' => generate_uid(),
|
'secret' => Str::uuid()->toString(),
|
||||||
'actions' => ['deploy'],
|
'actions' => ['deploy'],
|
||||||
'events' => ['push'],
|
'events' => ['push'],
|
||||||
]);
|
]);
|
||||||
|
@ -46,7 +46,7 @@ public function deployHook(string $repo, array $events, string $secret): array
|
|||||||
{
|
{
|
||||||
$response = Http::withToken($this->sourceControl->access_token)->post($this->apiUrl."/repositories/$repo/hooks", [
|
$response = Http::withToken($this->sourceControl->access_token)->post($this->apiUrl."/repositories/$repo/hooks", [
|
||||||
'description' => 'deploy',
|
'description' => 'deploy',
|
||||||
'url' => url('/git-hooks?secret='.$secret),
|
'url' => url('/api/git-hooks?secret='.$secret),
|
||||||
'events' => [
|
'events' => [
|
||||||
'repo:'.implode(',', $events),
|
'repo:'.implode(',', $events),
|
||||||
],
|
],
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\SourceControlProviders;
|
|
||||||
|
|
||||||
class Custom extends AbstractSourceControlProvider
|
|
||||||
{
|
|
||||||
public function connect(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRepo(string $repo = null): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function fullRepoUrl(string $repo, string $key): string
|
|
||||||
{
|
|
||||||
return $repo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deployHook(string $repo, array $events, string $secret): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroyHook(string $repo, string $hookId): void
|
|
||||||
{
|
|
||||||
// TODO: Implement destroyHook() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLastCommit(string $repo, string $branch): ?array
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deployKey(string $title, string $repo, string $key): void
|
|
||||||
{
|
|
||||||
// TODO: Implement deployKey() method.
|
|
||||||
}
|
|
||||||
}
|
|
@ -59,7 +59,7 @@ public function deployHook(string $repo, array $events, string $secret): array
|
|||||||
'name' => 'web',
|
'name' => 'web',
|
||||||
'events' => $events,
|
'events' => $events,
|
||||||
'config' => [
|
'config' => [
|
||||||
'url' => url('/git-hooks?secret='.$secret),
|
'url' => url('/api/git-hooks?secret='.$secret),
|
||||||
'content_type' => 'json',
|
'content_type' => 'json',
|
||||||
],
|
],
|
||||||
'active' => true,
|
'active' => true,
|
||||||
|
@ -53,7 +53,7 @@ public function deployHook(string $repo, array $events, string $secret): array
|
|||||||
$this->getApiUrl().'/projects/'.$repository.'/hooks',
|
$this->getApiUrl().'/projects/'.$repository.'/hooks',
|
||||||
[
|
[
|
||||||
'description' => 'deploy',
|
'description' => 'deploy',
|
||||||
'url' => url('/git-hooks?secret='.$secret),
|
'url' => url('/api/git-hooks?secret='.$secret),
|
||||||
'push_events' => in_array('push', $events),
|
'push_events' => in_array('push', $events),
|
||||||
'issues_events' => false,
|
'issues_events' => false,
|
||||||
'job_events' => false,
|
'job_events' => false,
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
use App\SiteTypes\Laravel;
|
use App\SiteTypes\Laravel;
|
||||||
use App\SiteTypes\PHPSite;
|
use App\SiteTypes\PHPSite;
|
||||||
use App\SourceControlProviders\Bitbucket;
|
use App\SourceControlProviders\Bitbucket;
|
||||||
use App\SourceControlProviders\Custom;
|
|
||||||
use App\SourceControlProviders\Github;
|
use App\SourceControlProviders\Github;
|
||||||
use App\SourceControlProviders\Gitlab;
|
use App\SourceControlProviders\Gitlab;
|
||||||
use App\StorageProviders\Dropbox;
|
use App\StorageProviders\Dropbox;
|
||||||
@ -284,7 +283,6 @@
|
|||||||
'github' => Github::class,
|
'github' => Github::class,
|
||||||
'gitlab' => Gitlab::class,
|
'gitlab' => Gitlab::class,
|
||||||
'bitbucket' => Bitbucket::class,
|
'bitbucket' => Bitbucket::class,
|
||||||
'custom' => Custom::class,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
29
database/factories/GitHookFactory.php
Normal file
29
database/factories/GitHookFactory.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\GitHook;
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Models\SourceControl;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
class GitHookFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = GitHook::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'secret' => $this->faker->word(),
|
||||||
|
'events' => $this->faker->words(),
|
||||||
|
'actions' => $this->faker->words(),
|
||||||
|
'hook_id' => $this->faker->word(),
|
||||||
|
'hook_response' => $this->faker->words(),
|
||||||
|
'created_at' => Carbon::now(),
|
||||||
|
'updated_at' => Carbon::now(),
|
||||||
|
'site_id' => Site::factory(),
|
||||||
|
'source_control_id' => SourceControl::factory(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,6 @@ class SourceControlFactory extends Factory
|
|||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'provider' => $this->faker->randomElement(\App\Enums\SourceControl::getValues()),
|
|
||||||
'access_token' => Str::random(10),
|
'access_token' => Str::random(10),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -44,13 +43,4 @@ public function bitbucket(): Factory
|
|||||||
];
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function custom(): Factory
|
|
||||||
{
|
|
||||||
return $this->state(function (array $attributes) {
|
|
||||||
return [
|
|
||||||
'provider' => \App\Enums\SourceControl::CUSTOM,
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
1
public/build/assets/app-99c9ce18.css
Normal file
1
public/build/assets/app-99c9ce18.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
22
public/build/assets/app-fa1f93fa.js
Normal file
22
public/build/assets/app-fa1f93fa.js
Normal file
File diff suppressed because one or more lines are too long
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"resources/css/app.css": {
|
"resources/css/app.css": {
|
||||||
"file": "assets/app-46ad72d7.css",
|
"file": "assets/app-99c9ce18.css",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/css/app.css"
|
"src": "resources/css/app.css"
|
||||||
},
|
},
|
||||||
"resources/js/app.js": {
|
"resources/js/app.js": {
|
||||||
"file": "assets/app-dfd48f80.js",
|
"file": "assets/app-fa1f93fa.js",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/js/app.js"
|
"src": "resources/js/app.js"
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
<div>
|
||||||
|
@if($site->deploymentScript?->content)
|
||||||
|
<x-dropdown>
|
||||||
|
<x-slot name="trigger">
|
||||||
|
<x-secondary-button>
|
||||||
|
{{ __('Auto Deployment') }}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 ml-1">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" />
|
||||||
|
</svg>
|
||||||
|
</x-secondary-button>
|
||||||
|
</x-slot>
|
||||||
|
<x-slot name="content">
|
||||||
|
<x-dropdown-link class="cursor-pointer" wire:click="enable">
|
||||||
|
{{ __("Enable") }}
|
||||||
|
@if($site->auto_deployment)
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 ml-1 text-green-600">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
@endif
|
||||||
|
</x-dropdown-link>
|
||||||
|
<x-dropdown-link class="cursor-pointer" wire:click="disable">
|
||||||
|
{{ __("Disable") }}
|
||||||
|
@if(!$site->auto_deployment)
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 ml-1 text-green-600">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
@endif
|
||||||
|
</x-dropdown-link>
|
||||||
|
</x-slot>
|
||||||
|
</x-dropdown>
|
||||||
|
@endif
|
||||||
|
</div>
|
@ -1,5 +1,4 @@
|
|||||||
<div x-data="">
|
<div x-data="">
|
||||||
<x-secondary-button x-on:click="$dispatch('open-modal', 'change-branch')">{{ __("Branch") }}</x-secondary-button>
|
|
||||||
<x-modal name="change-branch">
|
<x-modal name="change-branch">
|
||||||
<form wire:submit.prevent="change" class="p-6">
|
<form wire:submit.prevent="change" class="p-6">
|
||||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<div x-data="">
|
<div x-data="">
|
||||||
<x-secondary-button x-on:click="$dispatch('open-modal', 'deployment-script')">{{ __("Deployment Script") }}</x-secondary-button>
|
|
||||||
<x-modal name="deployment-script">
|
<x-modal name="deployment-script">
|
||||||
<form wire:submit.prevent="save" class="p-6">
|
<form wire:submit.prevent="save" class="p-6">
|
||||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<div x-data="">
|
<div x-data="">
|
||||||
<x-secondary-button x-on:click="$dispatch('open-modal', 'update-env')">{{ __(".env") }}</x-secondary-button>
|
|
||||||
<x-modal name="update-env">
|
<x-modal name="update-env">
|
||||||
<form wire:submit.prevent="save" class="p-6">
|
<form wire:submit.prevent="save" class="p-6">
|
||||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||||
|
@ -5,17 +5,29 @@
|
|||||||
<x-slot name="aside">
|
<x-slot name="aside">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="mr-2">
|
<div class="mr-2">
|
||||||
<livewire:application.change-branch :site="$site" />
|
|
||||||
</div>
|
|
||||||
<div class="mr-2">
|
|
||||||
<livewire:application.deployment-script :site="$site" />
|
|
||||||
</div>
|
|
||||||
<div class="mr-2">
|
|
||||||
<livewire:application.env :site="$site" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<livewire:application.deploy :site="$site" />
|
<livewire:application.deploy :site="$site" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mr-2">
|
||||||
|
<livewire:application.auto-deployment :site="$site" />
|
||||||
|
</div>
|
||||||
|
<x-dropdown>
|
||||||
|
<x-slot name="trigger">
|
||||||
|
<x-secondary-button>
|
||||||
|
{{ __('Manage') }}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 ml-1">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" />
|
||||||
|
</svg>
|
||||||
|
</x-secondary-button>
|
||||||
|
</x-slot>
|
||||||
|
<x-slot name="content">
|
||||||
|
<x-dropdown-link class="cursor-pointer" x-on:click="$dispatch('open-modal', 'change-branch')">{{ __("Branch") }}</x-dropdown-link>
|
||||||
|
<x-dropdown-link class="cursor-pointer" x-on:click="$dispatch('open-modal', 'deployment-script')">{{ __("Deployment Script") }}</x-dropdown-link>
|
||||||
|
<x-dropdown-link class="cursor-pointer" x-on:click="$dispatch('open-modal', 'update-env')">{{ __(".env") }}</x-dropdown-link>
|
||||||
|
</x-slot>
|
||||||
|
</x-dropdown>
|
||||||
|
<livewire:application.change-branch :site="$site" />
|
||||||
|
<livewire:application.deployment-script :site="$site" />
|
||||||
|
<livewire:application.env :site="$site" />
|
||||||
</div>
|
</div>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
</x-card-header>
|
</x-card-header>
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
<x-card>
|
||||||
|
<x-slot name="title">{{ __("Update Source Control") }}</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">{{ __("You can change the source control provider for this site") }}</x-slot>
|
||||||
|
|
||||||
|
<form id="update-source-control" wire:submit.prevent="update" class="space-y-6">
|
||||||
|
<div>
|
||||||
|
<x-input-label for="provider" :value="__('Source Control')" />
|
||||||
|
<x-select-input wire:model.defer="source_control" id="source_control" name="source_control" class="mt-1 w-full">
|
||||||
|
<option value="" disabled selected>{{ __("Select") }}</option>
|
||||||
|
@foreach(\App\Models\SourceControl::all() as $sourceControl)
|
||||||
|
<option value="{{ $sourceControl->id }}" @if($sourceControl->id === $source_control) selected @endif>{{ $sourceControl->profile }} ({{ $sourceControl->provider }})</option>
|
||||||
|
@endforeach
|
||||||
|
</x-select-input>
|
||||||
|
@error('source_control')
|
||||||
|
<x-input-error class="mt-2" :messages="$message" />
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<x-slot name="actions">
|
||||||
|
@if (session('status') === 'source-control-updated')
|
||||||
|
<p class="mr-2">{{ __('Saved') }}</p>
|
||||||
|
@endif
|
||||||
|
<x-primary-button form="update-source-control" wire:loading.attr="disabled">{{ __('Save') }}</x-primary-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-card>
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
<livewire:sites.change-php-version :site="$site"/>
|
<livewire:sites.change-php-version :site="$site"/>
|
||||||
|
|
||||||
|
<livewire:sites.update-source-control-provider :site="$site"/>
|
||||||
|
|
||||||
<x-card>
|
<x-card>
|
||||||
<x-slot name="title">{{ __("Delete Site") }}</x-slot>
|
<x-slot name="title">{{ __("Delete Site") }}</x-slot>
|
||||||
<x-slot name="description">{{ __("Permanently delete the site from server") }}</x-slot>
|
<x-slot name="description">{{ __("Permanently delete the site from server") }}</x-slot>
|
||||||
|
@ -1,19 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
// git hook
|
||||||
|
use App\Http\Controllers\GitHookController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
/*
|
Route::any('git-hooks', GitHookController::class)->name('git-hooks');
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| API Routes
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Here is where you can register API routes for your application. These
|
|
||||||
| routes are loaded by the RouteServiceProvider and all of them will
|
|
||||||
| be assigned to the "api" middleware group. Make something great!
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
|
||||||
return $request->user();
|
|
||||||
});
|
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
|
|
||||||
namespace Tests\Feature\Http;
|
namespace Tests\Feature\Http;
|
||||||
|
|
||||||
|
use App\Http\Livewire\Application\AutoDeployment;
|
||||||
use App\Http\Livewire\Application\ChangeBranch;
|
use App\Http\Livewire\Application\ChangeBranch;
|
||||||
use App\Http\Livewire\Application\Deploy;
|
use App\Http\Livewire\Application\Deploy;
|
||||||
use App\Http\Livewire\Application\DeploymentScript;
|
use App\Http\Livewire\Application\DeploymentScript;
|
||||||
use App\Http\Livewire\Application\LaravelApp;
|
use App\Http\Livewire\Application\LaravelApp;
|
||||||
use App\Jobs\Site\UpdateBranch;
|
use App\Jobs\Site\UpdateBranch;
|
||||||
|
use App\Models\GitHook;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Bus;
|
use Illuminate\Support\Facades\Bus;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
use Livewire\Livewire;
|
use Livewire\Livewire;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
@ -66,4 +69,45 @@ public function test_change_branch()
|
|||||||
|
|
||||||
Bus::assertDispatched(UpdateBranch::class);
|
Bus::assertDispatched(UpdateBranch::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_enable_auto_deployment()
|
||||||
|
{
|
||||||
|
Http::fake([
|
||||||
|
'github.com/*' => Http::response([
|
||||||
|
'id' => '123',
|
||||||
|
], 201),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
|
Livewire::test(AutoDeployment::class, ['site' => $this->site])
|
||||||
|
->call('enable')
|
||||||
|
->assertSuccessful();
|
||||||
|
|
||||||
|
$this->site->refresh();
|
||||||
|
|
||||||
|
$this->assertTrue($this->site->auto_deployment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_disable_auto_deployment()
|
||||||
|
{
|
||||||
|
Http::fake([
|
||||||
|
'github.com/*' => Http::response([], 204),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
|
GitHook::factory()->create([
|
||||||
|
'site_id' => $this->site->id,
|
||||||
|
'source_control_id' => $this->site->source_control_id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(AutoDeployment::class, ['site' => $this->site])
|
||||||
|
->call('disable')
|
||||||
|
->assertSuccessful();
|
||||||
|
|
||||||
|
$this->site->refresh();
|
||||||
|
|
||||||
|
$this->assertFalse($this->site->auto_deployment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
use App\Http\Livewire\Sites\CreateSite;
|
use App\Http\Livewire\Sites\CreateSite;
|
||||||
use App\Http\Livewire\Sites\DeleteSite;
|
use App\Http\Livewire\Sites\DeleteSite;
|
||||||
use App\Http\Livewire\Sites\SitesList;
|
use App\Http\Livewire\Sites\SitesList;
|
||||||
|
use App\Http\Livewire\Sites\UpdateSourceControlProvider;
|
||||||
use App\Jobs\Site\CreateVHost;
|
use App\Jobs\Site\CreateVHost;
|
||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
@ -109,4 +110,21 @@ public function test_change_php_version(): void
|
|||||||
|
|
||||||
Bus::assertDispatched(\App\Jobs\Site\ChangePHPVersion::class);
|
Bus::assertDispatched(\App\Jobs\Site\ChangePHPVersion::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_update_source_control(): void
|
||||||
|
{
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
|
/** @var \App\Models\SourceControl $gitlab */
|
||||||
|
$gitlab = \App\Models\SourceControl::factory()->gitlab()->create();
|
||||||
|
|
||||||
|
Livewire::test(UpdateSourceControlProvider::class, ['site' => $this->site])
|
||||||
|
->set('source_control', $gitlab->id)
|
||||||
|
->call('update')
|
||||||
|
->assertSuccessful();
|
||||||
|
|
||||||
|
$this->site->refresh();
|
||||||
|
|
||||||
|
$this->assertEquals($gitlab->id, $this->site->source_control_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public function test_delete_provider(string $provider): void
|
|||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
|
|
||||||
$this->assertDatabaseMissing('source_controls', [
|
$this->assertDatabaseMissing('source_controls', [
|
||||||
'provider' => $provider,
|
'id' => $sourceControl->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
use App\Enums\Webserver;
|
use App\Enums\Webserver;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
|
use App\Models\SourceControl;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
@ -53,8 +54,12 @@ private function setupServer(): void
|
|||||||
|
|
||||||
private function setupSite(): void
|
private function setupSite(): void
|
||||||
{
|
{
|
||||||
|
/** @var SourceControl $sourceControl */
|
||||||
|
$sourceControl = SourceControl::factory()->github()->create();
|
||||||
$this->site = Site::factory()->create([
|
$this->site = Site::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
|
'source_control_id' => $sourceControl->id,
|
||||||
|
'repository' => 'organization/repository',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user