mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-30 20:59:22 +00:00
Compare commits
8 Commits
v4.0.0-bet
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e39c3d5ab | ||
|
|
6071412986 | ||
|
|
ba7148206a | ||
|
|
59c5b22e6c | ||
|
|
be7f2ad9c4 | ||
|
|
62295ef573 | ||
|
|
ceb9fcf3b6 | ||
|
|
60282f7b6c |
@@ -2,41 +2,50 @@
|
|||||||
|
|
||||||
namespace App\Actions\Proxy;
|
namespace App\Actions\Proxy;
|
||||||
|
|
||||||
use App\Enums\ProxyTypes;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
use Spatie\Activitylog\Models\Activity;
|
|
||||||
|
|
||||||
class CheckProxy
|
class CheckProxy
|
||||||
{
|
{
|
||||||
use AsAction;
|
use AsAction;
|
||||||
public function handle(Server $server)
|
public function handle(Server $server, $fromUI = false)
|
||||||
{
|
{
|
||||||
if (!$server->isProxyShouldRun()) {
|
if (!$server->isProxyShouldRun()) {
|
||||||
throw new \Exception("Proxy should not run");
|
if ($fromUI) {
|
||||||
|
throw new \Exception("Proxy should not run. You selected the Custom Proxy.");
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$status = getContainerStatus($server, 'coolify-proxy');
|
$status = getContainerStatus($server, 'coolify-proxy');
|
||||||
if ($status === 'running') {
|
if ($status === 'running') {
|
||||||
$server->proxy->set('status', 'running');
|
$server->proxy->set('status', 'running');
|
||||||
$server->save();
|
$server->save();
|
||||||
return 'OK';
|
return false;
|
||||||
}
|
}
|
||||||
$ip = $server->ip;
|
$ip = $server->ip;
|
||||||
if ($server->id === 0) {
|
if ($server->id === 0) {
|
||||||
$ip = 'host.docker.internal';
|
$ip = 'host.docker.internal';
|
||||||
}
|
}
|
||||||
|
|
||||||
$connection = @fsockopen($ip, '80');
|
$connection80 = @fsockopen($ip, '80');
|
||||||
$connection = @fsockopen($ip, '443');
|
$connection443 = @fsockopen($ip, '443');
|
||||||
$port80 = is_resource($connection) && fclose($connection);
|
$port80 = is_resource($connection80) && fclose($connection80);
|
||||||
$port443 = is_resource($connection) && fclose($connection);
|
$port443 = is_resource($connection443) && fclose($connection443);
|
||||||
ray($ip);
|
|
||||||
if ($port80) {
|
if ($port80) {
|
||||||
throw new \Exception("Port 80 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
if ($fromUI) {
|
||||||
|
throw new \Exception("Port 80 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($port443) {
|
if ($port443) {
|
||||||
throw new \Exception("Port 443 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>>");
|
if ($fromUI) {
|
||||||
|
throw new \Exception("Port 443 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ class StartProxy
|
|||||||
public function handle(Server $server, bool $async = true): string|Activity
|
public function handle(Server $server, bool $async = true): string|Activity
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
CheckProxy::run($server);
|
|
||||||
|
|
||||||
$proxyType = $server->proxyType();
|
$proxyType = $server->proxyType();
|
||||||
$commands = collect([]);
|
$commands = collect([]);
|
||||||
$proxy_path = get_proxy_path();
|
$proxy_path = get_proxy_path();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class Kernel extends ConsoleKernel
|
|||||||
// $this->check_scheduled_backups($schedule);
|
// $this->check_scheduled_backups($schedule);
|
||||||
$this->check_resources($schedule);
|
$this->check_resources($schedule);
|
||||||
$this->cleanup_servers($schedule);
|
$this->cleanup_servers($schedule);
|
||||||
|
$this->check_scheduled_backups($schedule);
|
||||||
} else {
|
} else {
|
||||||
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
||||||
$schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer();
|
$schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class Deploy extends Component
|
|||||||
public function checkProxy()
|
public function checkProxy()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
CheckProxy::run($this->server);
|
CheckProxy::run($this->server, true);
|
||||||
$this->emit('startProxyPolling');
|
$this->emit('startProxyPolling');
|
||||||
$this->emit('proxyChecked');
|
$this->emit('proxyChecked');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class Status extends Component
|
|||||||
}
|
}
|
||||||
$this->numberOfPolls++;
|
$this->numberOfPolls++;
|
||||||
}
|
}
|
||||||
CheckProxy::run($this->server);
|
CheckProxy::run($this->server, true);
|
||||||
$this->emit('proxyStatusUpdated');
|
$this->emit('proxyStatusUpdated');
|
||||||
if ($this->server->proxy->status === 'running') {
|
if ($this->server->proxy->status === 'running') {
|
||||||
$this->polling = false;
|
$this->polling = false;
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
|
|
||||||
private string $serverUser = 'root';
|
private string $serverUser = 'root';
|
||||||
private string $serverUserHomeDir = '/root';
|
private string $serverUserHomeDir = '/root';
|
||||||
|
private string $dockerConfigFileExists = 'NOK';
|
||||||
|
|
||||||
public $tries = 1;
|
public $tries = 1;
|
||||||
public function __construct(int $application_deployment_queue_id)
|
public function __construct(int $application_deployment_queue_id)
|
||||||
@@ -165,6 +166,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
|
|
||||||
// Get user home directory
|
// Get user home directory
|
||||||
$this->serverUserHomeDir = instant_remote_process(["echo \$HOME"], $this->server);
|
$this->serverUserHomeDir = instant_remote_process(["echo \$HOME"], $this->server);
|
||||||
|
ray("test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'");
|
||||||
|
$this->dockerConfigFileExists = instant_remote_process(["test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'"], $this->server);
|
||||||
try {
|
try {
|
||||||
if ($this->application->dockerfile) {
|
if ($this->application->dockerfile) {
|
||||||
$this->deploy_simple_dockerfile();
|
$this->deploy_simple_dockerfile();
|
||||||
@@ -463,7 +466,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
{
|
{
|
||||||
$pull = "--pull=always";
|
$pull = "--pull=always";
|
||||||
$helperImage = config('coolify.helper_image');
|
$helperImage = config('coolify.helper_image');
|
||||||
$runCommand = "docker run {$pull} -d --network {$this->destination->network} -v /:/host --name {$this->deployment_uuid} --rm -v {$this->serverUserHomeDir}/.docker/config.json:/root/.docker/config.json:ro -v /var/run/docker.sock:/var/run/docker.sock {$helperImage}";
|
if ($this->dockerConfigFileExists === 'OK') {
|
||||||
|
$runCommand = "docker run {$pull} -d --network {$this->destination->network} -v /:/host --name {$this->deployment_uuid} --rm -v {$this->serverUserHomeDir}/.docker/config.json:/root/.docker/config.json:ro -v /var/run/docker.sock:/var/run/docker.sock {$helperImage}";
|
||||||
|
} else {
|
||||||
|
$runCommand = "docker run {$pull} -d --network {$this->destination->network} -v /:/host --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock {$helperImage}";
|
||||||
|
}
|
||||||
|
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
@@ -830,7 +837,6 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ray("docker build $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}");
|
|
||||||
$this->execute_remote_command([
|
$this->execute_remote_command([
|
||||||
executeInDocker($this->deployment_uuid, "docker build $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
|
executeInDocker($this->deployment_uuid, "docker build $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Actions\Proxy\CheckProxy;
|
||||||
use App\Actions\Proxy\StartProxy;
|
use App\Actions\Proxy\StartProxy;
|
||||||
use App\Models\ApplicationPreview;
|
use App\Models\ApplicationPreview;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
@@ -117,10 +118,18 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
return data_get($value, 'Name') === '/coolify-proxy';
|
return data_get($value, 'Name') === '/coolify-proxy';
|
||||||
})->first();
|
})->first();
|
||||||
if (!$foundProxyContainer) {
|
if (!$foundProxyContainer) {
|
||||||
if ($this->server->isProxyShouldRun()) {
|
try {
|
||||||
StartProxy::run($this->server, false);
|
$shouldStart = CheckProxy::run($this->server);
|
||||||
$this->server->team->notify(new ContainerRestarted('coolify-proxy', $this->server));
|
if ($shouldStart) {
|
||||||
|
StartProxy::run($this->server, false);
|
||||||
|
$this->server->team->notify(new ContainerRestarted('coolify-proxy', $this->server));
|
||||||
|
} else {
|
||||||
|
ray('Proxy could not be started.');
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
ray($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
|
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
|
||||||
$this->server->save();
|
$this->server->save();
|
||||||
|
|||||||
@@ -193,23 +193,24 @@ class Server extends BaseModel
|
|||||||
}
|
}
|
||||||
public function isProxyShouldRun()
|
public function isProxyShouldRun()
|
||||||
{
|
{
|
||||||
$shouldRun = false;
|
|
||||||
if ($this->proxyType() === ProxyTypes::NONE->value) {
|
if ($this->proxyType() === ProxyTypes::NONE->value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
foreach ($this->applications() as $application) {
|
// foreach ($this->applications() as $application) {
|
||||||
if (data_get($application, 'fqdn')) {
|
// if (data_get($application, 'fqdn')) {
|
||||||
$shouldRun = true;
|
// $shouldRun = true;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if ($this->id === 0) {
|
// ray($this->services()->get());
|
||||||
$settings = InstanceSettings::get();
|
|
||||||
if (data_get($settings, 'fqdn')) {
|
// if ($this->id === 0) {
|
||||||
$shouldRun = true;
|
// $settings = InstanceSettings::get();
|
||||||
}
|
// if (data_get($settings, 'fqdn')) {
|
||||||
}
|
// $shouldRun = true;
|
||||||
return $shouldRun;
|
// }
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
public function isFunctional()
|
public function isFunctional()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ return [
|
|||||||
|
|
||||||
// The release version of your application
|
// The release version of your application
|
||||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||||
'release' => '4.0.0-beta.89',
|
'release' => '4.0.0-beta.92',
|
||||||
// When left empty or `null` the Laravel environment will be used
|
// When left empty or `null` the Laravel environment will be used
|
||||||
'environment' => config('app.env'),
|
'environment' => config('app.env'),
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return '4.0.0-beta.89';
|
return '4.0.0-beta.92';
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
@if ($application->required_fqdn)
|
@if ($application->required_fqdn)
|
||||||
<x-forms.input required placeholder="https://app.coolify.io" label="Domains"
|
<x-forms.input required placeholder="https://app.coolify.io" label="Domains"
|
||||||
id="application.fqdn"></x-forms.input>
|
id="application.fqdn" helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io, https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
||||||
@else
|
@else
|
||||||
<x-forms.input placeholder="https://app.coolify.io" label="Domains"
|
<x-forms.input placeholder="https://app.coolify.io" label="Domains"
|
||||||
id="application.fqdn"></x-forms.input>
|
id="application.fqdn" helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io, https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
||||||
@endif
|
@endif
|
||||||
<x-forms.input required
|
<x-forms.input required
|
||||||
helper="You can change the image you would like to deploy.<br><br><span class='text-warning'>WARNING. You could corrupt your data. Only do it if you know what you are doing.</span>"
|
helper="You can change the image you would like to deploy.<br><br><span class='text-warning'>WARNING. You could corrupt your data. Only do it if you know what you are doing.</span>"
|
||||||
|
|||||||
@@ -29,5 +29,20 @@
|
|||||||
"documentation": "https://github.com/louislam/uptime-kuma/wiki",
|
"documentation": "https://github.com/louislam/uptime-kuma/wiki",
|
||||||
"slogan": "Uptime Kuma is a free, self-hosted monitoring tool for tracking the status and performance of your web services and applications in real-time.",
|
"slogan": "Uptime Kuma is a free, self-hosted monitoring tool for tracking the status and performance of your web services and applications in real-time.",
|
||||||
"compose": "c2VydmljZXM6CiAgdXB0aW1lLWt1bWE6CiAgICBpbWFnZTogbG91aXNsYW0vdXB0aW1lLWt1bWE6MQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROCiAgICB2b2x1bWVzOgogICAgICAtIHVwdGltZS1rdW1hOi9hcHAvZGF0YQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6IFsiQ01ELVNIRUxMIiwgImV4dHJhL2hlYWx0aGNoZWNrIl0KICAgICAgaW50ZXJ2YWw6IDJzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxNQ=="
|
"compose": "c2VydmljZXM6CiAgdXB0aW1lLWt1bWE6CiAgICBpbWFnZTogbG91aXNsYW0vdXB0aW1lLWt1bWE6MQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROCiAgICB2b2x1bWVzOgogICAgICAtIHVwdGltZS1rdW1hOi9hcHAvZGF0YQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6IFsiQ01ELVNIRUxMIiwgImV4dHJhL2hlYWx0aGNoZWNrIl0KICAgICAgaW50ZXJ2YWw6IDJzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxNQ=="
|
||||||
|
},
|
||||||
|
"wordpress-with-mariadb": {
|
||||||
|
"documentation": "https://wordpress.org/documentation/",
|
||||||
|
"slogan": "Wordpress is a free and open-source content management system (CMS) written in PHP and paired with a MySQL or MariaDB database.",
|
||||||
|
"compose": "c2VydmljZXM6CiAgIHdvcmRwcmVzczoKICAgICBpbWFnZTogd29yZHByZXNzOmxhdGVzdAogICAgIHZvbHVtZXM6CiAgICAgICAtIHdvcmRwcmVzcy1maWxlczovdmFyL3d3dy9odG1sCiAgICAgZW52aXJvbm1lbnQ6CiAgICAgICBTRVJWSUNFX0ZRRE46CiAgICAgICBXT1JEUFJFU1NfREJfSE9TVDogbWFyaWFkYgogICAgICAgV09SRFBSRVNTX0RCX1VTRVI6ICRTRVJWSUNFX1VTRVJfV09SRFBSRVNTCiAgICAgICBXT1JEUFJFU1NfREJfUEFTU1dPUkQ6ICRTRVJWSUNFX1BBU1NXT1JEX1dPUkRQUkVTUwogICAgICAgV09SRFBSRVNTX0RCX05BTUU6IHdvcmRwcmVzcwogICAgIGRlcGVuZHNfb246CiAgICAgICAtIG1hcmlhZGIKCiAgIG1hcmlhZGI6CiAgICAgaW1hZ2U6IG1hcmlhZGI6MTEKICAgICB2b2x1bWVzOgogICAgICAgLSBtYXJpYWRiLWRhdGE6L3Zhci9saWIvbXlzcWwKICAgICBlbnZpcm9ubWVudDoKICAgICAgIE1ZU1FMX1JPT1RfUEFTU1dPUkQ6ICRTRVJWSUNFX1BBU1NXT1JEX1JPT1QKICAgICAgIE1ZU1FMX0RBVEFCQVNFOiB3b3JkcHJlc3MKICAgICAgIE1ZU1FMX1VTRVI6ICRTRVJWSUNFX1VTRVJfV09SRFBSRVNTCiAgICAgICBNWVNRTF9QQVNTV09SRDogJFNFUlZJQ0VfUEFTU1dPUkRfV09SRFBSRVNT"
|
||||||
|
},
|
||||||
|
"wordpress-with-mysql": {
|
||||||
|
"documentation": "https://wordpress.org/documentation/",
|
||||||
|
"slogan": "Wordpress with MySQL.",
|
||||||
|
"compose": "c2VydmljZXM6CiAgIHdvcmRwcmVzczoKICAgICBpbWFnZTogd29yZHByZXNzOmxhdGVzdAogICAgIHZvbHVtZXM6CiAgICAgICAtIHdvcmRwcmVzcy1maWxlczovdmFyL3d3dy9odG1sCiAgICAgZW52aXJvbm1lbnQ6CiAgICAgICBTRVJWSUNFX0ZRRE46CiAgICAgICBXT1JEUFJFU1NfREJfSE9TVDogbXlzcWwKICAgICAgIFdPUkRQUkVTU19EQl9VU0VSOiAkU0VSVklDRV9VU0VSX1dPUkRQUkVTUwogICAgICAgV09SRFBSRVNTX0RCX1BBU1NXT1JEOiAkU0VSVklDRV9QQVNTV09SRF9XT1JEUFJFU1MKICAgICAgIFdPUkRQUkVTU19EQl9OQU1FOiB3b3JkcHJlc3MKICAgICBkZXBlbmRzX29uOgogICAgICAgLSBteXNxbAoKICAgbXlzcWw6CiAgICAgaW1hZ2U6IG15c3FsOjUuNwogICAgIHZvbHVtZXM6CiAgICAgICAtIG15c3FsLWRhdGE6L3Zhci9saWIvbXlzcWwKICAgICBlbnZpcm9ubWVudDoKICAgICAgIE1ZU1FMX1JPT1RfUEFTU1dPUkQ6ICRTRVJWSUNFX1BBU1NXT1JEX1JPT1QKICAgICAgIE1ZU1FMX0RBVEFCQVNFOiB3b3JkcHJlc3MKICAgICAgIE1ZU1FMX1VTRVI6ICRTRVJWSUNFX1VTRVJfV09SRFBSRVNTCiAgICAgICBNWVNRTF9QQVNTV09SRDogJFNFUlZJQ0VfUEFTU1dPUkRfV09SRFBSRVNT"
|
||||||
|
},
|
||||||
|
"wordpress-without-database": {
|
||||||
|
"documentation": "https://wordpress.org/documentation/",
|
||||||
|
"slogan": "Wordpress without predefined database.",
|
||||||
|
"compose": "c2VydmljZXM6CiAgIHdvcmRwcmVzczoKICAgICBpbWFnZTogd29yZHByZXNzOmxhdGVzdAogICAgIHZvbHVtZXM6CiAgICAgICAtIHdvcmRwcmVzcy1maWxlczovdmFyL3d3dy9odG1sCiAgICAgZW52aXJvbm1lbnQ6CiAgICAgICBTRVJWSUNFX0ZRRE46CiAgICA="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"version": "3.12.36"
|
"version": "3.12.36"
|
||||||
},
|
},
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.89"
|
"version": "4.0.0-beta.92"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user