From df6d56d148e3c0bf4148b03daab5707fe716b28e Mon Sep 17 00:00:00 2001 From: demonspork Date: Thu, 21 Dec 2023 13:28:04 -0600 Subject: [PATCH] Support updating optional installed apps via git (#6513) * WIP: Support updating optional installed apps via git * support app source update via cli * Update app_languages.php * Update index.php * Refactor App Git updating Refactor Optional App Git updating for more resilience and better handling of ssh remotes and to only update each repository once. * git app updates fix gui updates for repo based updating --- core/upgrade/app_languages.php | 42 ++++++++++ core/upgrade/index.php | 147 ++++++++++++++++++++++++++------- core/upgrade/upgrade.php | 20 ++++- resources/functions.php | 103 +++++++++++++++++++++++ 4 files changed, 283 insertions(+), 29 deletions(-) diff --git a/core/upgrade/app_languages.php b/core/upgrade/app_languages.php index cc3772007c..3fff520796 100644 --- a/core/upgrade/app_languages.php +++ b/core/upgrade/app_languages.php @@ -350,6 +350,27 @@ $text['label-upgrade_source']['zh-cn'] = "源代码"; $text['label-upgrade_source']['ja-jp'] = "ソースコード"; $text['label-upgrade_source']['ko-kr'] = "소스 코드"; +$text['label-update_apps']['en-us'] = "App Source Code"; +$text['label-update_apps']['en-gb'] = "App Source Code"; +$text['label-update_apps']['ar-eg'] = ""; +$text['label-update_apps']['de-at'] = "Quellcode"; //copied from de-de +$text['label-update_apps']['de-ch'] = "Quellcode"; //copied from de-de +$text['label-update_apps']['de-de'] = "Quellcode"; +$text['label-update_apps']['es-cl'] = "Código Fuente"; +$text['label-update_apps']['es-mx'] = "Código Fuente"; //copied from es-cl +$text['label-update_apps']['fr-ca'] = "Code Source"; //copied from fr-fr +$text['label-update_apps']['fr-fr'] = "Code Source"; +$text['label-update_apps']['he-il'] = ""; +$text['label-update_apps']['it-it'] = "Codice Sorgente"; +$text['label-update_apps']['nl-nl'] = ""; +$text['label-update_apps']['pl-pl'] = "Kod źródłowy"; +$text['label-update_apps']['pt-br'] = "Código Fonte"; //copied from pt-pt +$text['label-update_apps']['pt-pt'] = "Source Code"; +$text['label-update_apps']['ro-ro'] = ""; +$text['label-update_apps']['ru-ru'] = "Исходный код"; +$text['label-update_apps']['sv-se'] = "Källkod"; +$text['label-update_apps']['uk-ua'] = "Вихідний код"; + $text['label-upgrade_schema']['en-us'] = "Schema"; $text['label-upgrade_schema']['en-gb'] = "Schema"; $text['label-upgrade_schema']['ar-eg'] = "مخطط"; @@ -850,6 +871,27 @@ $text['description-upgrade_source']['zh-cn'] = "从存储库更新FusionPBX源 $text['description-upgrade_source']['ja-jp'] = "FusionPBXソースファイルをリポジトリから更新します。"; $text['description-upgrade_source']['ko-kr'] = "저장소에서 Fusionpbx 소스 파일을 업데이트합니다."; +$text['description-update_apps']['en-us'] = "Updates optional app source files from the respository."; +$text['description-update_apps']['en-gb'] = "Updates optional app source files from the respository."; +$text['description-update_apps']['ar-eg'] = ""; +$text['description-update_apps']['de-at'] = "Aktualisiert den Quellcode aus dem Repository"; //copied from de-de +$text['description-update_apps']['de-ch'] = "Aktualisiert den Quellcode aus dem Repository"; //copied from de-de +$text['description-update_apps']['de-de'] = "Aktualisiert den Quellcode aus dem Repository"; +$text['description-update_apps']['es-cl'] = "Archivos de origen Actualizaciones del repositorio."; +$text['description-update_apps']['es-mx'] = "Archivos de origen Actualizaciones del repositorio."; //copied from es-cl +$text['description-update_apps']['fr-ca'] = "Mise à jour du code source de depuis le dépôt."; //copied from fr-fr +$text['description-update_apps']['fr-fr'] = "Mise à jour du code source de depuis le dépôt."; +$text['description-update_apps']['he-il'] = ""; +$text['description-update_apps']['it-it'] = "Aggiorna il files sorgente di dal repository."; +$text['description-update_apps']['nl-nl'] = ""; +$text['description-update_apps']['pl-pl'] = "Uaktualnia pliki źródłowe z przechowalni."; +$text['description-update_apps']['pt-br'] = "Atualiza o a partir dos arquivos de código fonte do repositório."; +$text['description-update_apps']['pt-pt'] = "Arquivos de origem Atualizações do repositório."; +$text['description-update_apps']['ro-ro'] = ""; +$text['description-update_apps']['ru-ru'] = "Обновляет исходные файлы из репозитория."; +$text['description-update_apps']['sv-se'] = "Uppdaterar källfiler från respository."; +$text['description-update_apps']['uk-ua'] = "Оновлення вихідних файлів з репозиторію Subversion ."; + $text['description-upgrade_schema']['en-us'] = "Checks to ensure table and field integrity in the database."; $text['description-upgrade_schema']['en-gb'] = "Checks to ensure table and field integrity in the database."; $text['description-upgrade_schema']['ar-eg'] = "تحقق من سلامة الطاولة والميدان في قاعدة البيانات"; diff --git a/core/upgrade/index.php b/core/upgrade/index.php index 52f7d6d52f..aac92c22b5 100644 --- a/core/upgrade/index.php +++ b/core/upgrade/index.php @@ -58,30 +58,46 @@ //run source update if (!empty($action["upgrade_source"]) && permission_exists("upgrade_source") && !is_dir("/usr/share/examples/fusionpbx")) { - $cwd = getcwd(); - chdir($_SERVER["PROJECT_ROOT"]); - exec("git pull 2>&1", $response_source_update); - $update_failed = true; - if (sizeof($response_source_update) > 0) { - $_SESSION["response"]["upgrade_source"] = $response_source_update; - foreach ($response_source_update as $response_line) { - if (substr_count($response_line, "Updating ") > 0 || substr_count($response_line, "Already up-to-date.") > 0 || substr_count($response_line, "Already up to date.") > 0) { - $update_failed = false; - } - - if (substr_count($response_line, "error") > 0) { - $update_failed = true; - break; - } - } - } - chdir($cwd); - if ($update_failed) { - message::add($text['message-upgrade_source_failed'], 'negative', $message_timeout); + + $project_update_status = git_pull($_SERVER["PROJECT_ROOT"]); + + $_SESSION["response"]["upgrade_source"] = $project_update_status['message']; + + if (!empty($project_update_status['result'])) { + message::add($text['message-upgrade_source'], null, $message_timeout); } else { + message::add($text['message-upgrade_source_failed'], 'negative', $message_timeout); + } + } + + //run app source updates + if (!empty($action["update_apps"]) && permission_exists("upgrade_source")) { + $app_updates = $_POST['app_list']; + + $updateable_repos = git_find_repos($_SERVER["PROJECT_ROOT"]."/app"); + + if (is_array($app_updates)) { + $apps_updated = true; + foreach ($updateable_repos as $repo => $apps) { + if (array_search(basename($repo), $app_updates) !== false) { + $git_result = git_pull($repo); + $_SESSION["response"]["update_apps"][basename($repo)] = $git_result['message']; + } + + if (!$git_result['result']) { + $apps_updated = false; + } + + } + } + + if ($apps_updated) { message::add($text['message-upgrade_source'], null, $message_timeout); } + else { + message::add($text['message-upgrade_source_failed'], 'negative', $message_timeout); + } } //load an array of the database schema and compare it with the active database @@ -155,7 +171,7 @@ echo "\n"; echo "\n"; echo " \n"; echo " \n"; echo "\n"; echo "
\n"; - echo "
".$step++."
"; + echo "
".$step."
"; echo " ".$text['label-upgrade_source']; echo "
\n"; @@ -179,6 +195,68 @@ echo "
\n"; + + $step++; + + // find and show apps + + $updateable_repos = git_find_repos($_SERVER["PROJECT_ROOT"]."/app"); + + echo "\n"; + echo "\n"; + echo " \n"; + echo " \n"; + echo "\n"; + echo "
\n"; + echo "
".$step."
"; + echo " ".$text['label-update_apps']; + echo "
\n"; + echo "  ".$text['description-update_apps']."\n"; + echo ""; + echo "
\n"; + + + echo "\n"; + + $step++; } if (permission_exists("upgrade_schema")) { @@ -198,7 +276,7 @@ echo "\n"; echo "\n"; echo " \n"; echo " \n"; echo "
\n"; - echo "
".$step++."B
"; + echo "
".$step."B
"; echo " ".$text['label-upgrade_data_types']; echo "
\n"; @@ -207,13 +285,14 @@ echo "
\n"; echo "\n"; + $step++; } if (permission_exists("upgrade_apps")) { echo "\n"; echo "\n"; echo " \n"; echo " \n"; echo "\n"; echo "
\n"; - echo "
".$step++."
"; + echo "
".$step."
"; echo " ".$text['label-upgrade_apps']; echo "
\n"; @@ -221,13 +300,14 @@ echo "
\n"; + $step++; } if (permission_exists("menu_restore")) { echo "\n"; echo "\n"; echo " \n"; echo " \n"; echo "\n"; echo "
\n"; - echo "
".$step++."
"; + echo "
".$step."
"; echo " ".$text['label-upgrade_menu']; echo "
\n"; @@ -252,13 +332,14 @@ echo "
\n"; + $step++; } if (permission_exists("group_edit")) { echo "\n"; echo "\n"; echo " \n"; echo " \n"; echo "\n"; echo "
\n"; - echo "
".$step++."
"; + echo "
".$step."
"; echo " ".$text['label-upgrade_permissions']; echo "
\n"; @@ -266,6 +347,7 @@ echo "
\n"; + $step++; } echo "\n"; @@ -273,9 +355,18 @@ echo "

"; if (!empty($_SESSION["response"]) && is_array($_SESSION["response"])) { foreach($_SESSION["response"] as $part => $response){ - echo "". $text["label-results"]." - ".$text["label-${part}"].""; - echo "

"; - if (is_array($response)) { + echo "".$text["label-results"]." - ".$text["label-${part}"]; + echo "

"; + if ($part == "update_apps") { + echo "
";
+				foreach ($response as $app_name => $app_response) {
+					foreach ($app_response as $response_line) {
+						echo $app_name.": ".htmlspecialchars($response_line) . "\n";
+					}
+				}
+				echo "
"; + } + elseif (is_array($response)) { echo "
";
 				echo implode("\n", $response);
 				echo "
"; diff --git a/core/upgrade/upgrade.php b/core/upgrade/upgrade.php index 1553f9716b..01bf78d7dc 100644 --- a/core/upgrade/upgrade.php +++ b/core/upgrade/upgrade.php @@ -286,4 +286,22 @@ } } -?> \ No newline at end of file +//upgrade optional apps + if ($upgrade_type == 'apps') { + + $app_list = git_find_repos($_SERVER["PROJECT_ROOT"]."/app"); + + if (!is_array($app_list)) { + exit; + } + print_r($app_list);exit; + foreach ($app_list as $repo => $apps) { + $path = $repo; + $git_result = git_pull($path); + foreach ($git_result['message'] as $response_line) { + echo $repo . ": " . $response_line . "\n"; + } + } + } + +?> diff --git a/resources/functions.php b/resources/functions.php index bb0f26533f..db6fad1a5e 100644 --- a/resources/functions.php +++ b/resources/functions.php @@ -2292,4 +2292,107 @@ } } + +//git pull +if (!function_exists('git_pull')) { + function git_pull($path) { + + $cwd = getcwd(); + chdir($path); + exec("GIT_SSH_COMMAND='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' git pull 2>&1", $response_source_update); + + $update_status = false; + + if (sizeof($response_source_update) == 0) { + return array('result' => false, 'message' => null); + } + + foreach ($response_source_update as $response_line) { + if (substr_count($response_line, "Updating ") > 0 || substr_count($response_line, "Already up to date.") > 0) { + $update_status = true; + } + + if (substr_count($response_line, "error") > 0) { + $update_status = false; + break; + } + } + chdir($cwd); + + return array('result' => $update_status, + 'message' => $response_source_update); + + } +} + +//git is repository +if (!function_exists('is_git_repo')) { + function is_git_repo($path) { + if(!is_dir($path)) {return false;} + $cwd = $_SERVER["PROJECT_ROOT"]; + chdir($path); + exec("git rev-parse --show-toplevel", $git_repo, $git_repo_response); + chdir($cwd); + if (($git_repo[0]) != $cwd && $git_repo_response == 0) { + return $git_repo[0]; + } + return false; + } +} + +//git repo version information +if (!function_exists('git_repo_info')) { + function git_repo_info($path) { + + if(!is_dir($path)) { + return false; + } + + $cwd = getcwd(); + chdir($path); + + //get current branch + exec("git rev-parse --abbrev-ref HEAD 2>&1", $git_branch, $git_branch_return); + $repo['branch'] = $git_branch[0]; + + //get current commit id + exec("git log --pretty=format:'%H' -n 1 2>&1", $git_commit, $git_commit_return); + $repo['commit'] = $git_commit[0]; + + //get remote origin url for updates + exec("git config --get remote.origin.url", $git_url); + $repo['url'] = preg_replace('/\.git$/', '', $git_url[0] ); + + $repo['path'] = $path; + + //to-do detect remote over ssh and reformat to equivalent https url + + chdir($cwd); + + if (!$git_branch_return && !$git_commit_return && $git_url) { + return $repo; + } + else { + return false; + } + + } +} + + +//git locate app repositories +if (!function_exists('git_find_repos')) { + function git_find_repos($path) { + $apps = scandir($path); + $git_repos = array(); + foreach ($apps as $app) { + $git_repo_name = is_git_repo($path."/".$app); + if ($git_repo_name != false && !empty($git_repo_name)) { + $git_repos[$git_repo_name][] = $app; + } + unset($git_repo_name); + } + return $git_repos; + } +} ?>