Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Console/Commands/UpgradeCommand.php
7460 views
1
<?php
2
3
namespace Pterodactyl\Console\Commands;
4
5
use Illuminate\Console\Command;
6
use Pterodactyl\Console\Kernel;
7
use Symfony\Component\Process\Process;
8
use Symfony\Component\Console\Helper\ProgressBar;
9
10
class UpgradeCommand extends Command
11
{
12
protected const DEFAULT_URL = 'https://github.com/pterodactyl/panel/releases/%s/panel.tar.gz';
13
14
protected $signature = 'p:upgrade
15
{--user= : The user that PHP runs under. All files will be owned by this user.}
16
{--group= : The group that PHP runs under. All files will be owned by this group.}
17
{--url= : The specific archive to download.}
18
{--release= : A specific Pterodactyl version to download from GitHub. Leave blank to use latest.}
19
{--skip-download : If set no archive will be downloaded.}';
20
21
protected $description = 'Downloads a new archive for Pterodactyl from GitHub and then executes the normal upgrade commands.';
22
23
/**
24
* Executes an upgrade command which will run through all of our standard
25
* commands for Pterodactyl and enable users to basically just download
26
* the archive and execute this and be done.
27
*
28
* This places the application in maintenance mode as well while the commands
29
* are being executed.
30
*
31
* @throws \Exception
32
*/
33
public function handle()
34
{
35
$skipDownload = $this->option('skip-download');
36
if (!$skipDownload) {
37
$this->output->warning('This command does not verify the integrity of downloaded assets. Please ensure that you trust the download source before continuing. If you do not wish to download an archive, please indicate that using the --skip-download flag, or answering "no" to the question below.');
38
$this->output->comment('Download Source (set with --url=):');
39
$this->line($this->getUrl());
40
}
41
42
if (version_compare(PHP_VERSION, '7.4.0') < 0) {
43
$this->error('Cannot execute self-upgrade process. The minimum required PHP version required is 7.4.0, you have [' . PHP_VERSION . '].');
44
}
45
46
$user = 'www-data';
47
$group = 'www-data';
48
if ($this->input->isInteractive()) {
49
if (!$skipDownload) {
50
$skipDownload = !$this->confirm('Would you like to download and unpack the archive files for the latest version?', true);
51
}
52
53
if (is_null($this->option('user'))) {
54
$userDetails = posix_getpwuid(fileowner('public'));
55
$user = $userDetails['name'] ?? 'www-data';
56
57
if (!$this->confirm("Your webserver user has been detected as <fg=blue>[{$user}]:</> is this correct?", true)) {
58
$user = $this->anticipate(
59
'Please enter the name of the user running your webserver process. This varies from system to system, but is generally "www-data", "nginx", or "apache".',
60
[
61
'www-data',
62
'nginx',
63
'apache',
64
]
65
);
66
}
67
}
68
69
if (is_null($this->option('group'))) {
70
$groupDetails = posix_getgrgid(filegroup('public'));
71
$group = $groupDetails['name'] ?? 'www-data';
72
73
if (!$this->confirm("Your webserver group has been detected as <fg=blue>[{$group}]:</> is this correct?", true)) {
74
$group = $this->anticipate(
75
'Please enter the name of the group running your webserver process. Normally this is the same as your user.',
76
[
77
'www-data',
78
'nginx',
79
'apache',
80
]
81
);
82
}
83
}
84
85
if (!$this->confirm('Are you sure you want to run the upgrade process for your Panel?')) {
86
$this->warn('Upgrade process terminated by user.');
87
88
return;
89
}
90
}
91
92
ini_set('output_buffering', '0');
93
$bar = $this->output->createProgressBar($skipDownload ? 9 : 10);
94
$bar->start();
95
96
if (!$skipDownload) {
97
$this->withProgress($bar, function () {
98
$this->line("\$upgrader> curl -L \"{$this->getUrl()}\" | tar -xzv");
99
$process = Process::fromShellCommandline("curl -L \"{$this->getUrl()}\" | tar -xzv");
100
$process->run(function ($type, $buffer) {
101
$this->{$type === Process::ERR ? 'error' : 'line'}($buffer);
102
});
103
});
104
}
105
106
$this->withProgress($bar, function () {
107
$this->line('$upgrader> php artisan down');
108
$this->call('down');
109
});
110
111
$this->withProgress($bar, function () {
112
$this->line('$upgrader> chmod -R 755 storage bootstrap/cache');
113
$process = new Process(['chmod', '-R', '755', 'storage', 'bootstrap/cache']);
114
$process->run(function ($type, $buffer) {
115
$this->{$type === Process::ERR ? 'error' : 'line'}($buffer);
116
});
117
});
118
119
$this->withProgress($bar, function () {
120
$command = ['composer', 'install', '--no-ansi'];
121
if (config('app.env') === 'production' && !config('app.debug')) {
122
$command[] = '--optimize-autoloader';
123
$command[] = '--no-dev';
124
}
125
126
$this->line('$upgrader> ' . implode(' ', $command));
127
$process = new Process($command);
128
$process->setTimeout(10 * 60);
129
$process->run(function ($type, $buffer) {
130
$this->line($buffer);
131
});
132
});
133
134
/** @var \Illuminate\Foundation\Application $app */
135
$app = require __DIR__ . '/../../../bootstrap/app.php';
136
/** @var Kernel $kernel */
137
$kernel = $app->make(Kernel::class);
138
$kernel->bootstrap();
139
$this->setLaravel($app);
140
141
$this->withProgress($bar, function () {
142
$this->line('$upgrader> php artisan view:clear');
143
$this->call('view:clear');
144
});
145
146
$this->withProgress($bar, function () {
147
$this->line('$upgrader> php artisan config:clear');
148
$this->call('config:clear');
149
});
150
151
$this->withProgress($bar, function () {
152
$this->line('$upgrader> php artisan migrate --force --seed');
153
$this->call('migrate', ['--force' => true, '--seed' => true]);
154
});
155
156
$this->withProgress($bar, function () use ($user, $group) {
157
$this->line("\$upgrader> chown -R {$user}:{$group} *");
158
$process = Process::fromShellCommandline("chown -R {$user}:{$group} *", $this->getLaravel()->basePath());
159
$process->setTimeout(10 * 60);
160
$process->run(function ($type, $buffer) {
161
$this->{$type === Process::ERR ? 'error' : 'line'}($buffer);
162
});
163
});
164
165
$this->withProgress($bar, function () {
166
$this->line('$upgrader> php artisan queue:restart');
167
$this->call('queue:restart');
168
});
169
170
$this->withProgress($bar, function () {
171
$this->line('$upgrader> php artisan up');
172
$this->call('up');
173
});
174
175
$this->newLine(2);
176
$this->info('Panel has been successfully upgraded. Please ensure you also update any Wings instances: https://pterodactyl.io/wings/1.0/upgrading.html');
177
}
178
179
protected function withProgress(ProgressBar $bar, \Closure $callback)
180
{
181
$bar->clear();
182
$callback();
183
$bar->advance();
184
$bar->display();
185
}
186
187
protected function getUrl(): string
188
{
189
if ($this->option('url')) {
190
return $this->option('url');
191
}
192
193
return sprintf(self::DEFAULT_URL, $this->option('release') ? 'download/v' . $this->option('release') : 'latest/download');
194
}
195
}
196
197