From 5259ff9862565f6b993653399a831df280a916fb Mon Sep 17 00:00:00 2001 From: xiaomlove <353856593@qq.com> Date: Thu, 17 Jun 2021 20:07:22 +0800 Subject: [PATCH] [update] auto download source code --- app/Console/Commands/Test.php | 5 +- nexus/Install/Install.php | 15 ++-- nexus/Install/Update.php | 83 +++++++++++++++++- nexus/Install/update/update.php | 149 ++++++++++++++++---------------- 4 files changed, 170 insertions(+), 82 deletions(-) diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index 415434a2..34b2f025 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -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()); } } diff --git a/nexus/Install/Install.php b/nexus/Install/Install.php index a4f7f1a7..73a455cc 100644 --- a/nexus/Install/Install.php +++ b/nexus/Install/Install.php @@ -287,16 +287,19 @@ class Install $table = '
'; $table .= '
'; $table .= '
'; - foreach ($header as $value) { - $table .= '
' . $value . '
'; + foreach ($header as $text) { + $table .= '
' . $text . '
'; } $table .= '
'; foreach ($data as $value) { $table .= '
'; - $table .= '
' . $value['label'] . '
'; - $table .= '
' . $value['required'] . '
'; - $table .= '
' . $value['current'] . '
'; - $table .= '
' . $value['result'] . '
'; + foreach ($header as $name => $text) { + $color = 'gray'; + if ($name == 'result' && in_array($value[$name], ['YES', 'NO'])) { + $color = $value[$name] == 'YES' ? 'green' : 'red'; + } + $table .= '
' . $value[$name] . '
'; + } $table .= '
'; } $table .= '
'; diff --git a/nexus/Install/Update.php b/nexus/Install/Update.php index af8782cc..d54d710c 100644 --- a/nexus/Install/Update.php +++ b/nexus/Install/Update.php @@ -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; + } + } diff --git a/nexus/Install/update/update.php b/nexus/Install/update/update.php index 2ce7dfe6..cfbe0dc9 100644 --- a/nexus/Install/update/update.php +++ b/nexus/Install/update/update.php @@ -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('', $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)) { '; - $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 '
若 Redis 不启用,相关项目留空
'; echo $update->renderForm($envFormControls); - } elseif ($currentStep == 3) { - echo '

需要修改或创建以下数据表(字段)

'; + } elseif ($currentStep == 2) { + echo '

选择目标版本(注意必须选择比当前版本(' . VERSION_NUMBER. ')高的)

'; if (empty($tableRows)) { - echo '
恭喜,需要的表(字段)均符合要求!
'; + echo '
抱歉,暂无任何版可以选择!
'; } else { - echo $update->renderTable($header, $tableRows); + echo $update->renderTable($versionHeader, $tableRows); } } elseif ($currentStep == 4) { echo $update->renderTable($header, $tableRows);