[update] auto download source code

This commit is contained in:
xiaomlove
2021-06-17 20:07:22 +08:00
parent a6ca92706b
commit 5259ff9862
4 changed files with 170 additions and 82 deletions

View File

@@ -53,7 +53,10 @@ class Test extends Command
*/
public function handle()
{
$time = '2021-06-16T04:03:35Z';
$date = Carbon::parse($time);
$date->tz = 'Asia/Shanghai';
dd($date->toDateTimeString());
}
}

View File

@@ -287,16 +287,19 @@ class Install
$table = '<div class="table w-full text-left">';
$table .= '<div class="table-row-group">';
$table .= '<div class="table-row">';
foreach ($header as $value) {
$table .= '<div class="table-cell bg-gray-400 text-gray-700 px-4 py-2">' . $value . '</div>';
foreach ($header as $text) {
$table .= '<div class="table-cell bg-gray-400 text-gray-700 px-4 py-2">' . $text . '</div>';
}
$table .= '</div>';
foreach ($data as $value) {
$table .= '<div class="table-row">';
$table .= '<div class="table-cell bg-gray-200 text-gray-700 px-4 py-2 text-sm">' . $value['label'] . '</div>';
$table .= '<div class="table-cell bg-gray-200 text-gray-700 px-4 py-2 text-sm">' . $value['required'] . '</div>';
$table .= '<div class="table-cell bg-gray-200 text-gray-700 px-4 py-2 text-sm">' . $value['current'] . '</div>';
$table .= '<div class="table-cell bg-' . ($value['result'] == 'YES' ? 'green' : 'red') . '-200 text-gray-700 px-4 py-2 text-sm">' . $value['result'] . '</div>';
foreach ($header as $name => $text) {
$color = 'gray';
if ($name == 'result' && in_array($value[$name], ['YES', 'NO'])) {
$color = $value[$name] == 'YES' ? 'green' : 'red';
}
$table .= '<div class="table-cell bg-gray-200 text-' . $color . '-700 px-4 py-2 text-sm">' . $value[$name] . '</div>';
}
$table .= '</div>';
}
$table .= '</div>';

View File

@@ -9,13 +9,14 @@ use App\Models\ExamUser;
use App\Models\Icon;
use App\Models\Setting;
use App\Repositories\ExamRepository;
use GuzzleHttp\Client;
use Illuminate\Support\Str;
use Nexus\Database\NexusDB;
class Update extends Install
{
protected $steps = ['环境检测', '添加 .env 文件', '修改&创建数据表', '导入数据'];
protected $steps = ['环境检测', '选择版本安装', '更新 .env 文件', '更新配置'];
public function getLogFile()
@@ -143,4 +144,84 @@ class Update extends Install
}
public function listVersions()
{
$client = new Client();
$url = "https://api.github.com/repos/xiaomlove/nexusphp/releases";
$response = $client->get($url, ['timeout' => 10,]);
if (($statusCode = $response->getStatusCode()) != 200) {
throw new \RuntimeException("获取版本列表失败,状态码:$statusCode");
}
if ($response->getBody()->getSize() <= 0) {
throw new \RuntimeException("获取版本列表失败,结果为空");
}
$bodyString = $response->getBody()->getContents();
$this->doLog("[LIST_VERSION_RESPONSE]: $bodyString");
$versions = json_decode($bodyString, true);
if (empty($versions) || !is_array($versions)) {
throw new \RuntimeException("获取版本列表结果异常");
}
return array_reverse($versions);
}
public function downAndExtractCode($url)
{
$arr = explode('/', $url);
$basename = last($arr);
$suffix = '.tar.gz';
$filename = sprintf('%s/nexusphp-%s-%s%s', sys_get_temp_dir(), $basename, date('YmdHis'), $suffix);
$client = new Client();
$response = $client->request('GET', $url, ['sink' => $filename]);
if (($statusCode = $response->getStatusCode()) != 200) {
throw new \RuntimeException("下载错误,状态码:$statusCode");
}
if (($bodySize = $response->getBody()->getSize()) <= 0) {
throw new \RuntimeException("下载错误,文件体积:$bodySize");
}
if (!file_exists($filename)) {
throw new \RuntimeException("下载错误,文件不存在:$filename");
}
if (filesize($filename) <= 0) {
throw new \RuntimeException("下载错误文件大小为0");
}
$this->doLog('SUCCESS_DOWNLOAD');
$extractDir = str_replace($suffix, "", $filename);
$command = "mkdir -p $extractDir";
$result = exec($command, $output, $result_code);
$this->doLog(sprintf(
"command: %s, output: %s, result_code: %s, result: %s",
$command, json_encode($output), $result_code, $result
));
if ($result_code != 0) {
throw new \RuntimeException("创建解压目录:$extractDir 失败, result_code: $result_code");
}
$command = "tar -xf $filename -C $extractDir";
$result = exec($command, $output, $result_code);
$this->doLog(sprintf(
"command: %s, output: %s, result_code: %s, result: %s",
$command, json_encode($output), $result_code, $result
));
if ($result_code != 0) {
throw new \RuntimeException("解压文件:$filename 到:$extractDir 失败, result_code: $result_code");
}
foreach (glob("$extractDir/*") as $path) {
if (is_dir($path)) {
$command = sprintf('cp -Rf %s/* %s', $path, ROOT_PATH);
$result = exec($command, $output, $result_code);
$this->doLog(sprintf(
"command: %s, output: %s, result_code: %s, result: %s",
$command, json_encode($output), $result_code, $result
));
if ($result_code != 0) {
throw new \RuntimeException("复制错误, result_code: $result_code");
}
break;
}
}
$this->doLog('SUCCESS_EXTRACT');
return true;
}
}

View File

@@ -23,6 +23,69 @@ if ($currentStep == 1) {
}
if ($currentStep == 2) {
$tableRows = [];
$versionTable = $versions = [];
$cacheKkey = '__versions_' . date('Ymd_H');
try {
if (!empty($_SESSION[$cacheKkey])) {
$update->doLog("get versions from session.");
$versions = $_SESSION[$cacheKkey];
} else {
$versions = $update->listVersions();
}
} catch (\Exception $exception) {
$error = $exception->getMessage();
}
$_SESSION[$cacheKkey] = $versions;
$versionHeader = [
'checkbox' => '选择',
'tag_name' => '版本(标签)',
'name' => '名称',
'published_at' => '发布时间',
];
foreach ($versions as $version) {
if ($version['draft']) {
continue;
}
$time = \Carbon\Carbon::parse($version['published_at']);
$time->tz = nexus_env('TIMEZONE');
$versionUrl = $version['tag_name'] . '|' . $version['tarball_url'];
$checked = !empty($_REQUEST['version_url']) && $_REQUEST['version_url'] == $versionUrl ? ' checked' : '';
$tableRows[] = [
'checkbox' => sprintf('<input type="radio" name="version_url" value="%s"%s/>', $versionUrl, $checked),
'tag_name' => $version['tag_name'],
'name' => $version['name'],
'published_at' => $time->format('Y-m-d H:i:s'),
];
}
while ($isPost) {
try {
if (empty($_REQUEST['version_url'])) {
throw new \RuntimeException("没有选择版本");
}
$versionUrlArr = explode('|', $_REQUEST['version_url']);
$version = strtolower($versionUrlArr[0]);
$downloadUrl = $versionUrlArr[1];
if (\Illuminate\Support\Str::startsWith($version, 'v')) {
$version = substr($version, 1);
}
$update->doLog("version: $version, downloadUrl: $downloadUrl, currentVersion: " . VERSION_NUMBER);
if (version_compare($version, VERSION_NUMBER, '<=')) {
throw new \RuntimeException("必须选择一个高于当前版本(" . VERSION_NUMBER . ")的");
}
$update->downAndExtractCode($downloadUrl);
$update->nextStep();
} catch (\Exception $exception) {
$update->doLog($exception->getMessage() . $exception->getTraceAsString());
$error = $exception->getMessage();
break;
}
break;
}
}
if ($currentStep == 3) {
$envExampleFile = $rootpath . ".env.example";
// $dbstructureFile = $rootpath . "_db/dbstructure_v1.6.sql";
$envExampleData = readEnvFile($envExampleFile);
@@ -56,74 +119,6 @@ if ($currentStep == 2) {
$pass = empty($fails);
}
if ($currentStep == 3) {
// $createTables = $update->listAllTableCreate();
$createTables = $update->listAllTableCreateFromMigrations();
$existsTables = $update->listExistsTable();
$tableRows = [];
$toCreateTable = $toAlterTable = $toUpdateTable = [];
foreach ($createTables as $table => $tableCreate) {
//Table not exists
if (!in_array($table, $existsTables)) {
$tableRows[] = [
"label" => "Table: $table",
"required" => "exists",
"current" => "",
"result" => 'NO',
];
$toCreateTable[$table] = $tableCreate;
continue;
}
$tableHaveFields = $update->listTableFieldsFromDb($table);
foreach ($tableHaveFields as $field => $fieldInfo) {
if ($fieldInfo['Type'] == 'datetime' && $fieldInfo['Default'] == '0000-00-00 00:00:00') {
$tableRows[] = [
'label' => "Field: $table.$field",
'required' => 'default null',
'current' => '0000-00-00 00:00:00',
'result' => 'NO',
];
$toAlterTable[$table][$field] = "modify $field datetime default null";
$toUpdateTable[$table][$field] = "null";
}
}
}
while ($isPost) {
try {
sql_query('SET sql_mode=(SELECT REPLACE(@@sql_mode,"NO_ZERO_DATE", ""))');
$command = "php " . ROOT_PATH . "artisan migrate --force";
$result = exec($command, $output, $result_code);
$update->doLog(sprintf('command: %s, result_code: %s, result: %s', $command, $result_code, $result));
$update->doLog("output: " . json_encode($output));
if ($result_code != 0) {
throw new \RuntimeException(json_encode($output));
} else {
$update->doLog("[MIGRATE] success.");
}
foreach ($toAlterTable as $table => $modies) {
$query = "alter table $table " . implode(', ', $modies);
$update->doLog("[ALTER TABLE] $query");
sql_query($query);
}
foreach ($toUpdateTable as $table => $updates) {
foreach ($updates as $field => $fieldUpdate) {
$query = sprintf("update %s set %s = %s where %s = '0000-00-00 00:00:00'", $table, $field, $fieldUpdate, $field);
$update->doLog("[UPDATE TABLE] $query, affectedRows: " . mysql_affected_rows());
sql_query($query);
}
}
$update->runExtraQueries();
$update->nextStep();
} catch (\Exception $exception) {
$update->doLog($exception->getMessage() . $exception->getTraceAsString());
$error = $exception->getMessage();
break;
}
break;
}
}
if ($currentStep == 4) {
$settingTableRows = $update->listSettingTableRows();
@@ -135,6 +130,7 @@ if ($currentStep == 4) {
try {
$update->createSymbolicLinks($symbolicLinks);
$update->saveSettings($settings);
$update->runExtraQueries();
$update->nextStep();
} catch (\Exception $e) {
$error = $e->getMessage();
@@ -166,20 +162,25 @@ if (!empty($error)) {
<input type="hidden" name="step" value="<?php echo $currentStep?>">
<?php
echo'<div class="step-' . $currentStep . ' text-center">';
$header = ['项目', '要求', '当前', '结果'];
$header = [
'label' => '项目',
'require' => '要求',
'current'=> '当前',
'result'=> '结果'
];
if ($currentStep == 1) {
echo $update->renderTable($header, $requirements['table_rows']);
} elseif ($currentStep == 2) {
} elseif ($currentStep == 3) {
echo $update->renderTable($header, $tableRows);
echo '<div class="text-gray-700 p-4 text-red-400">若 Redis 不启用,相关项目留空</div>';
echo $update->renderForm($envFormControls);
} elseif ($currentStep == 3) {
echo '<h1 class="mb-4 text-lg font-bold">需要修改或创建以下数据表(字段)</h1>';
} elseif ($currentStep == 2) {
echo '<h1 class="mb-4 text-lg font-bold">选择目标版本(注意必须选择比当前版本(' . VERSION_NUMBER. ')高的)</h1>';
if (empty($tableRows)) {
echo '<div class="text-green-600 text-center">恭喜,需要的表(字段)均符合要求!</div>';
echo '<div class="text-green-600 text-center">抱歉,暂无任何版可以选择!</div>';
} else {
echo $update->renderTable($header, $tableRows);
echo $update->renderTable($versionHeader, $tableRows);
}
} elseif ($currentStep == 4) {
echo $update->renderTable($header, $tableRows);