From 6adde35849811648bcb8fa1a72c3be0a886b7919 Mon Sep 17 00:00:00 2001 From: Roman Kelesidis Date: Mon, 9 Jun 2025 15:21:17 +0300 Subject: [PATCH] misc(cliff): Added automated script for releases creation (#1930) * misc(cliff): Added automated script for releases creation * Updated * Update functions_cli.php * Updated * Updated * Update functions_cli.php * Updated * Update _release.php * Update cliff.toml * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php * Update _release.php --- _cleanup.php | 51 ++------- _release.php | 118 +++++++++++++++++++++ cliff.toml | 3 - install.php | 128 ++--------------------- library/includes/functions_cli.php | 161 +++++++++++++++++++++++++++++ 5 files changed, 297 insertions(+), 164 deletions(-) create mode 100644 _release.php create mode 100644 library/includes/functions_cli.php diff --git a/_cleanup.php b/_cleanup.php index 3c30efdd0..928bc6cd9 100644 --- a/_cleanup.php +++ b/_cleanup.php @@ -9,6 +9,7 @@ if (!defined('BB_ROOT')) { define('BB_ROOT', __DIR__ . DIRECTORY_SEPARATOR); + define('BB_PATH', BB_ROOT); } // Check CLI mode @@ -16,12 +17,21 @@ if (php_sapi_name() !== 'cli') { exit; } +if (!function_exists('removeFile')) { + // Get all constants + require_once BB_ROOT . 'library/defines.php'; + + // Include CLI functions + require INC_DIR . '/functions_cli.php'; +} + $items = [ '.github', '.cliffignore', '.editorconfig', '.gitignore', '.styleci.yml', + '_release.php', 'CHANGELOG.md', 'cliff.toml', 'CODE_OF_CONDUCT.md', @@ -41,44 +51,3 @@ foreach ($items as $item) { removeDir($path); } } - -/** - * Remove target file - * - * @param string $file Path to file - */ -function removeFile(string $file): void -{ - if (unlink($file)) { - echo "- File removed: $file" . PHP_EOL; - } else { - echo "- File cannot be removed: $file" . PHP_EOL; - exit; - } -} - -/** - * Remove folder (recursively) - * - * @param string $dir Path to folder - */ -function removeDir(string $dir): void -{ - $it = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS); - $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST); - - foreach ($files as $file) { - if ($file->isDir()) { - removeDir($file->getPathname()); - } else { - removeFile($file->getPathname()); - } - } - - if (rmdir($dir)) { - echo "- Folder removed: $dir" . PHP_EOL; - } else { - echo "- Folder cannot be removed: $dir" . PHP_EOL; - exit; - } -} diff --git a/_release.php b/_release.php new file mode 100644 index 000000000..af4b9cfd3 --- /dev/null +++ b/_release.php @@ -0,0 +1,118 @@ +php ' . basename(__FILE__) . ' in CLI mode'); +} + +// Get all constants +require_once BB_ROOT . 'library/defines.php'; + +// Include CLI functions +require INC_DIR . '/functions_cli.php'; + +// Welcoming message +out("--- Release creation tool ---\n", 'info'); + +$configFile = BB_PATH . '/library/config.php'; + +if (!is_file($configFile)) { + out('- Config file ' . basename($configFile) . ' not found', 'error'); + exit; +} +if (!is_readable($configFile)) { + out('- Config file ' . basename($configFile) . ' is not readable', 'error'); + exit; +} +if (!is_writable($configFile)) { + out('- Config file ' . basename($configFile) . ' is not writable', 'error'); + exit; +} + +// Ask for version +fwrite(STDOUT, 'Enter version number (e.g, v2.4.0): '); +$version = trim(fgets(STDIN)); + +if (empty($version)) { + out("- Version cannot be empty. Please enter a valid version number", 'error'); + exit; +} else { + // Add 'v' prefix if missing + if (!str_starts_with($version, 'v')) { + $version = 'v' . $version; + } + + out("- Using version: $version", 'info'); +} + +// Ask for release date or use today's date +fwrite(STDOUT, "Enter release date (e.g. 25-05-2025), leave empty to use today's date: "); +$date = trim(fgets(STDIN)); + +if (empty($date)) { + $date = date('d-m-Y'); + out("- Using current date: $date", 'info'); +} else { + // Validate date format (dd-mm-yyyy) + $dateObj = DateTime::createFromFormat('d-m-Y', $date); + if (!$dateObj || $dateObj->format('d-m-Y') !== $date) { + out("- Invalid date format. Expected format: DD-MM-YYYY", 'error'); + exit; + } + + out("- Using date: $date", 'info'); +} + +// Read config file content +$content = file_get_contents($configFile); + +// Update version +$content = preg_replace( + "/\\\$bb_cfg\['tp_version'\]\s*=\s*'[^']*';/", + "\$bb_cfg['tp_version'] = '$version';", + $content +); + +// Update release date +$content = preg_replace( + "/\\\$bb_cfg\['tp_release_date'\]\s*=\s*'[^']*';/", + "\$bb_cfg['tp_release_date'] = '$date';", + $content +); + +// Save updated config +$bytesWritten = file_put_contents($configFile, $content); + +if ($bytesWritten === false) { + out("- Failed to write to config file", 'error'); + exit; +} + +if ($bytesWritten === 0) { + out("- Config file was not updated (0 bytes written)", 'error'); + exit; +} + +out("\n- Config file has been updated!", 'success'); + +// Git add & commit +runProcess('git add -A && git commit -m "release: ' . escapeshellarg($version) . '"'); + +$userName = 'belomaxorka'; +$userEmail = 'roman25052006.kelesh@gmail.com'; + +$tagCmd = "git -c user.name=\"$userName\" -c user.email=\"$userEmail\" tag -a \"$version\" -m \"Release $version\""; +runProcess($tagCmd); +runProcess("git tag -v \"$version\""); + +out("\n- Release $version has been successfully prepared and committed!", 'success'); diff --git a/cliff.toml b/cliff.toml index 456ae56fb..6cbe23512 100644 --- a/cliff.toml +++ b/cliff.toml @@ -14,8 +14,6 @@ repo = "torrentpier" header = """ [![TorrentPier](https://raw.githubusercontent.com/torrentpier/.github/refs/heads/main/versions/Cattle.png)](https://github.com/torrentpier)\n # 📖 Change Log\n -> [!NOTE] -> To view changelog from **v2.0.0** to **v2.4.5-rc.2** navigate to [HISTORY.md](HISTORY.md). """ # template for the changelog body # https://keats.github.io/tera/docs/#introduction @@ -75,7 +73,6 @@ body = """ """ # template for the changelog footer footer = """ - """ # remove the leading and trailing whitespace from the templates trim = true diff --git a/install.php b/install.php index ff88365d3..009098420 100644 --- a/install.php +++ b/install.php @@ -8,12 +8,19 @@ */ define('BB_ROOT', __DIR__ . DIRECTORY_SEPARATOR); +define('BB_PATH', BB_ROOT); // Check CLI mode if (php_sapi_name() !== 'cli') { die('Please run php ' . basename(__FILE__) . ' in CLI mode'); } +// Get all constants +require_once BB_ROOT . 'library/defines.php'; + +// Include CLI functions +require INC_DIR . '/functions_cli.php'; + /** * System requirements */ @@ -34,125 +41,6 @@ define('CHECK_REQUIREMENTS', [ ], ]); -/** - * Colored console output - * - * @param string $str - * @param string $type - * @return void - */ -function out(string $str, string $type = ''): void -{ - echo match ($type) { - 'error' => "\033[31m$str \033[0m\n", - 'success' => "\033[32m$str \033[0m\n", - 'warning' => "\033[33m$str \033[0m\n", - 'info' => "\033[36m$str \033[0m\n", - 'debug' => "\033[90m$str \033[0m\n", - default => "$str\n", - }; -} - -/** - * Run process with realtime output - * - * @param string $cmd - * @param string|null $input - * @return void - */ -function runProcess(string $cmd, string $input = null): void -{ - $descriptorSpec = [ - 0 => ['pipe', 'r'], - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - - $process = proc_open($cmd, $descriptorSpec, $pipes); - - if (!is_resource($process)) { - out('- Could not start subprocess', 'error'); - return; - } - - // Write input if provided - if ($input !== null) { - fwrite($pipes[0], $input); - fclose($pipes[0]); - } - - // Read and print output in real-time - while (!feof($pipes[1])) { - echo stream_get_contents($pipes[1], 1); - flush(); // Flush output buffer for immediate display - } - - // Read and print error output - while (!feof($pipes[2])) { - echo stream_get_contents($pipes[2], 1); - flush(); - } - - fclose($pipes[1]); - fclose($pipes[2]); - - proc_close($process); -} - -/** - * Remove directory recursively - * - * @param string $dir - * @return void - */ -function rmdir_rec(string $dir): void -{ - $it = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS); - $files = new RecursiveIteratorIterator($it, - RecursiveIteratorIterator::CHILD_FIRST); - foreach ($files as $file) { - if ($file->isDir()) { - rmdir($file->getPathname()); - } else { - unlink($file->getPathname()); - } - } - rmdir($dir); -} - -/** - * Setting permissions recursively - * - * @param string $dir - * @param int $dirPermissions - * @param int $filePermissions - * @return void - */ -function chmod_r(string $dir, int $dirPermissions, int $filePermissions): void -{ - $dp = opendir($dir); - while ($file = readdir($dp)) { - if (($file == '.') || ($file == '..')) { - continue; - } - - $fullPath = realpath($dir . '/' . $file); - if (is_dir($fullPath)) { - out("- Directory: $fullPath"); - chmod($fullPath, $dirPermissions); - chmod_r($fullPath, $dirPermissions, $filePermissions); - } elseif (is_file($fullPath)) { - // out("- File: $fullPath"); - chmod($fullPath, $filePermissions); - } else { - out("- Cannot find target path: $fullPath", 'error'); - return; - } - } - - closedir($dp); -} - // Welcoming message out("--- TorrentPier Installer ---\n", 'info'); @@ -207,7 +95,7 @@ if (is_file(BB_ROOT . '.env')) { } // composer dir if (is_dir(BB_ROOT . 'vendor')) { - rmdir_rec(BB_ROOT . 'vendor'); + removeDir(BB_ROOT . 'vendor', true); if (!is_dir(BB_ROOT . 'vendor')) { out("- Composer directory successfully removed!"); } else { diff --git a/library/includes/functions_cli.php b/library/includes/functions_cli.php new file mode 100644 index 000000000..d2adb0188 --- /dev/null +++ b/library/includes/functions_cli.php @@ -0,0 +1,161 @@ +isDir()) { + removeDir($file->getPathname(), $withoutOutput); + } else { + removeFile($file->getPathname(), $withoutOutput); + } + } + + if (rmdir($dir)) { + if ($withoutOutput === false) { + echo "- Folder removed: $dir" . PHP_EOL; + } + } else { + if ($withoutOutput === false) { + echo "- Folder cannot be removed: $dir" . PHP_EOL; + } + exit; + } +} + +/** + * Colored console output + * + * @param string $str + * @param string $type + * @return void + */ +function out(string $str, string $type = ''): void +{ + echo match ($type) { + 'error' => "\033[31m$str \033[0m\n", + 'success' => "\033[32m$str \033[0m\n", + 'warning' => "\033[33m$str \033[0m\n", + 'info' => "\033[36m$str \033[0m\n", + 'debug' => "\033[90m$str \033[0m\n", + default => "$str\n", + }; +} + +/** + * Run process with realtime output + * + * @param string $cmd + * @param string|null $input + * @return void + */ +function runProcess(string $cmd, ?string $input = null): void +{ + $descriptorSpec = [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + + $process = proc_open($cmd, $descriptorSpec, $pipes); + + if (!is_resource($process)) { + out('- Could not start subprocess', 'error'); + return; + } + + // Write input if provided + if ($input !== null) { + fwrite($pipes[0], $input); + fclose($pipes[0]); + } + + // Read and print output in real-time + while (!feof($pipes[1])) { + echo stream_get_contents($pipes[1], 1); + flush(); // Flush output buffer for immediate display + } + + // Read and print error output + while (!feof($pipes[2])) { + echo stream_get_contents($pipes[2], 1); + flush(); + } + + fclose($pipes[1]); + fclose($pipes[2]); + + proc_close($process); +} + +/** + * Setting permissions recursively + * + * @param string $dir + * @param int $dirPermissions + * @param int $filePermissions + * @return void + */ +function chmod_r(string $dir, int $dirPermissions, int $filePermissions): void +{ + $dp = opendir($dir); + while ($file = readdir($dp)) { + if (($file == '.') || ($file == '..')) { + continue; + } + + $fullPath = realpath($dir . '/' . $file); + if (is_dir($fullPath)) { + out("- Directory: $fullPath"); + chmod($fullPath, $dirPermissions); + chmod_r($fullPath, $dirPermissions, $filePermissions); + } elseif (is_file($fullPath)) { + // out("- File: $fullPath"); + chmod($fullPath, $filePermissions); + } else { + out("- Cannot find target path: $fullPath", 'error'); + return; + } + } + + closedir($dp); +}