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
This commit is contained in:
Roman Kelesidis 2025-06-09 15:21:17 +03:00 committed by GitHub
parent c9aff2a152
commit 6adde35849
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 297 additions and 164 deletions

View file

@ -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;
}
}

118
_release.php Normal file
View file

@ -0,0 +1,118 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
define('BB_ROOT', __DIR__ . DIRECTORY_SEPARATOR);
define('BB_PATH', BB_ROOT);
// Check CLI mode
if (php_sapi_name() !== 'cli') {
die('Please run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php ' . basename(__FILE__) . '</code> 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');

View file

@ -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 = """
<!-- generated by git-cliff -->
"""
# remove the leading and trailing whitespace from the templates
trim = true

View file

@ -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 <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php ' . basename(__FILE__) . '</code> 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 {

View file

@ -0,0 +1,161 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (!defined('BB_ROOT')) {
die(basename(__FILE__));
}
/**
* Remove target file
*
* @param string $file Path to file
* @param bool $withoutOutput Hide output
*/
function removeFile(string $file, bool $withoutOutput = false): void
{
if (unlink($file)) {
if ($withoutOutput === false) {
echo "- File removed: $file" . PHP_EOL;
}
} else {
if ($withoutOutput === false) {
echo "- File cannot be removed: $file" . PHP_EOL;
}
exit;
}
}
/**
* Remove folder (recursively)
*
* @param string $dir Path to folder
* @param bool $withoutOutput Hide output
*/
function removeDir(string $dir, bool $withoutOutput = false): 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(), $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);
}