Merge #16584 - Improve the version handling

Signed-off-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
William Desportes 2021-02-23 15:44:22 +01:00
commit 0a55b43adc
No known key found for this signature in database
GPG Key ID: 90A0EF1B8251A889
9 changed files with 402 additions and 25 deletions

View File

@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Command;
use RangeException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function file_put_contents;
use function preg_match;
use function sprintf;
final class SetVersionCommand extends Command
{
/** @var string */
protected static $defaultName = 'set-version';
/** @var string */
private static $generatedClassTemplate = <<<'PHP'
<?php
declare(strict_types=1);
namespace PhpMyAdmin;
/**
* This class is generated by scripts/console.
*
* @see \PhpMyAdmin\Command\SetVersionCommand
*/
final class Version
{
// The VERSION_SUFFIX constant is defined at libraries/vendor_config.php
public const VERSION = '%1$u.%2$u.%3$u%4$s' . VERSION_SUFFIX;
public const SERIES = '%1$u.%2$u';
public const MAJOR = %1$u;
public const MINOR = %2$u;
public const PATCH = %3$u;
public const ID = %1$u%2$02u%3$02u;
public const PRE_RELEASE_NAME = '%5$s';
public const IS_DEV = %6$s;
}
PHP;
protected function configure(): void
{
$this->setDescription('Sets the version number');
$this->setHelp('This command generates the PhpMyAdmin\Version class based on the version number provided.');
$this->addArgument('version', InputArgument::REQUIRED, 'The version number');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
/** @var string $version */
$version = $input->getArgument('version');
$generatedClass = $this->getGeneratedClass($version);
if (! $this->writeGeneratedClassFile($generatedClass)) {
// failure
return 1;
}
$output->writeln('PhpMyAdmin\Version class successfully generated!');
// success
return 0;
}
private function getGeneratedClass(string $version): string
{
// Do not allow any major below 5
$return = preg_match('/^([5-9]+)\.(\d{1,2})\.(\d{1,2})(-([a-z0-9]+))?$/', $version, $matches);
if ($return === false || $return === 0) {
throw new RangeException('The version number is in the wrong format: ' . $version);
}
return sprintf(
self::$generatedClassTemplate,
$matches[1],
$matches[2],
$matches[3],
$matches[4] ?? '',
$matches[5] ?? '',
($matches[5] ?? '') === 'dev' ? 'true' : 'false'
);
}
private function writeGeneratedClassFile(string $generatedClass): bool
{
$result = file_put_contents(
ROOT_PATH . 'libraries/classes/Version.php',
$generatedClass
);
return $result !== false;
}
}

View File

@ -136,12 +136,9 @@ class Config
*/
public function checkSystem(): void
{
$this->set('PMA_VERSION', '5.1.0-rc2');
/* Major version */
$this->set(
'PMA_MAJOR_VERSION',
implode('.', array_slice(explode('.', $this->get('PMA_VERSION'), 3), 0, 2))
);
// All the version handling is now done in the Version class
$this->set('PMA_VERSION', Version::VERSION);
$this->set('PMA_MAJOR_VERSION', Version::SERIES);
$this->checkWebServerOs();
$this->checkWebServer();

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin;
/**
* This class is generated by scripts/console.
*
* @see \PhpMyAdmin\Command\SetVersionCommand
*/
final class Version
{
// The VERSION_SUFFIX constant is defined at libraries/vendor_config.php
public const VERSION = '5.1.0-dev' . VERSION_SUFFIX;
public const SERIES = '5.1';
public const MAJOR = 5;
public const MINOR = 1;
public const PATCH = 0;
public const ID = 50100;
public const PRE_RELEASE_NAME = 'dev';
public const IS_DEV = true;
}

View File

@ -79,3 +79,8 @@ define('LOCALE_PATH', ROOT_PATH . 'locale' . DIRECTORY_SEPARATOR);
* Define the cache directory for routing cache an other cache files
*/
define('CACHE_DIR', ROOT_PATH . 'libraries' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR);
/**
* Suffix to add to the phpMyAdmin version
*/
define('VERSION_SUFFIX', '');

View File

@ -20,3 +20,5 @@ parameters:
- tmp/*
- twig-templates/*
- vendor/*
dynamicConstantNames:
- VERSION_SUFFIX

View File

@ -2,6 +2,7 @@
<?php
use PhpMyAdmin\Command\CacheWarmupCommand;
use PhpMyAdmin\Command\SetVersionCommand;
use PhpMyAdmin\Config;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Tests\Stubs\DbiDummy;
@ -65,5 +66,6 @@ $application = new Application('phpMyAdmin Console Tool');
$application->add(new CacheWarmupCommand());
$application->add(new LintCommand($twig));
$application->add(new SetVersionCommand());
$application->run();

View File

@ -238,24 +238,24 @@ delete_phpunit_sandbox() {
# Ensure we have tracking branch
ensure_local_branch $branch
# Check if we're releasing older
if git cat-file -e $branch:libraries/classes/Config.php 2> /dev/null ; then
CONFIG_LIB=libraries/classes/Config.php
elif git cat-file -e $branch:libraries/Config.php 2> /dev/null ; then
CONFIG_LIB=libraries/Config.php
else
CONFIG_LIB=libraries/Config.class.php
fi
VERSION_FILE=libraries/classes/Version.php
fetchReleaseFromFile() {
php -r "define('VERSION_SUFFIX', ''); require_once('libraries/classes/Version.php'); echo \PhpMyAdmin\Version::VERSION;"
}
echo "The actual configured release is: $(fetchReleaseFromFile)"
if [ $do_ci -eq 0 -a -$do_daily -eq 0 ] ; then
cat <<END
Please ensure you have incremented rc count or version in the repository :
- in $CONFIG_LIB Config::__constructor() the line
" \$this->set('PMA_VERSION', '$version'); "
- run ./scripts/console set-version $version
- in $VERSION_FILE Version class:
- check that VERSION, MAJOR, MINOR and PATCH are correct.
- in doc/conf.py the line
" version = '$version' "
- in README
- in README the "Version" line
- in package.json the line
" "version": "$version", "
- set release date in ChangeLog
@ -269,6 +269,8 @@ END
fi
fi
echo "The actual configured release is now: $(fetchReleaseFromFile)"
# Create working copy
mkdir -p release
git worktree prune
@ -290,8 +292,8 @@ fi
# Check release version
if [ $do_ci -eq 0 -a -$do_daily -eq 0 ] ; then
if ! grep -q "'PMA_VERSION', '$version'" $CONFIG_LIB ; then
echo "There seems to be wrong version in $CONFIG_LIB!"
if ! grep -q "VERSION = '$version'" $VERSION_FILE ; then
echo "There seems to be wrong version in $VERSION_FILE!"
exit 2
fi
if ! grep -q "version = '$version'" doc/conf.py ; then
@ -601,11 +603,13 @@ Todo now:
based on documentation.
7. increment rc count or version in the repository :
- in $CONFIG_LIB Config::__constructor() the line
" \$this->set( 'PMA_VERSION', '2.7.1-dev' ); "
- in Documentation.html (if it exists) the 2 lines
" <title>phpMyAdmin 2.2.2-rc1 - Documentation</title> "
" <h1>phpMyAdmin 2.2.2-rc1 Documentation</h1> "
- run ./scripts/console set-version $version
- in $VERSION_FILE Version class:
- check that VERSION, MAJOR, MINOR and PATCH are correct.
- in README the "Version" line
" Version 2.7.1-dev "
- in package.json the line
" "version": " 2.7.1-dev", "
- in doc/conf.py (if it exists) the line
" version = '2.7.1-dev' "
@ -615,6 +619,6 @@ Todo now:
10. in case of a new major release ('y' in x.y.0), update the pmaweb/settings.py in website repository to include the new major releases
11. update the Dockerfile in the docker repository to reflect the new version and create a new annotated tag (such as with git tag -s -a 4.7.9-1 -m "Version 4.7.9-1"). Remember to push the tag with git push origin --tags
11. update the Dockerfile in the docker repository to reflect the new version and create a new annotated tag (such as with git tag -s -a 4.7.9-1 -m "Version 4.7.9-1"). Remember to push the tag with git push origin {tagName}
END

View File

@ -0,0 +1,208 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Tests\Command;
use PhpMyAdmin\Command\SetVersionCommand;
use PhpMyAdmin\Tests\AbstractTestCase;
use Symfony\Component\Console\Command\Command;
use RangeException;
use function sprintf;
use function class_exists;
class SetVersionCommandTest extends AbstractTestCase
{
/** @var SetVersionCommand */
private $command;
public function setUp(): void
{
if (! class_exists(Command::class)) {
return;
}
$this->command = new SetVersionCommand();
}
/**
* @return array[]
*/
public function dataProviderBadVersions(): array
{
return [
[''],
['4.9.0.1'],
['4.9'],
['4-9-0-1'],
['4-9-0'],
['0-0-0'],
['0.0.0'],
['1.0.0'],
['2.0.0'],
['3.0.0'],
['4.0.0'],
['0.0.-1'],
['5.000.0'],
['5.0.000'],
['5.0.0-'],
['5.0.0-foo bar'],
];
}
/**
* @dataProvider dataProviderBadVersions
*/
public function testGetGeneratedClassInvalidVersion(string $version): void
{
if (! class_exists(Command::class)) {
$this->markTestSkipped('The Symfony Console is missing');
}
$this->expectException(RangeException::class);
$this->expectExceptionMessage('The version number is in the wrong format: ' . $version);
$this->callFunction(
$this->command,
SetVersionCommand::class,
'getGeneratedClass',
[$version]
);
}
/**
* @return array[]
*/
public function dataProviderGoodVersions(): array
{
return [
[
'5.0.0-rc1',
' public const VERSION = \'5.0.0-rc1\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'5.0\';' . "\n"
. ' public const MAJOR = 5;' . "\n"
. ' public const MINOR = 0;' . "\n"
. ' public const PATCH = 0;' . "\n"
. ' public const ID = 50000;' . "\n"
. ' public const PRE_RELEASE_NAME = \'rc1\';' . "\n"
. ' public const IS_DEV = false;',
],
[
'5.0.0-beta',
' public const VERSION = \'5.0.0-beta\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'5.0\';' . "\n"
. ' public const MAJOR = 5;' . "\n"
. ' public const MINOR = 0;' . "\n"
. ' public const PATCH = 0;' . "\n"
. ' public const ID = 50000;' . "\n"
. ' public const PRE_RELEASE_NAME = \'beta\';' . "\n"
. ' public const IS_DEV = false;',
],
[
'5.0.0-beta1',
' public const VERSION = \'5.0.0-beta1\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'5.0\';' . "\n"
. ' public const MAJOR = 5;' . "\n"
. ' public const MINOR = 0;' . "\n"
. ' public const PATCH = 0;' . "\n"
. ' public const ID = 50000;' . "\n"
. ' public const PRE_RELEASE_NAME = \'beta1\';' . "\n"
. ' public const IS_DEV = false;',
],
[
'5.0.0-alpha',
' public const VERSION = \'5.0.0-alpha\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'5.0\';' . "\n"
. ' public const MAJOR = 5;' . "\n"
. ' public const MINOR = 0;' . "\n"
. ' public const PATCH = 0;' . "\n"
. ' public const ID = 50000;' . "\n"
. ' public const PRE_RELEASE_NAME = \'alpha\';' . "\n"
. ' public const IS_DEV = false;',
],
[
'5.0.0-alpha1',
' public const VERSION = \'5.0.0-alpha1\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'5.0\';' . "\n"
. ' public const MAJOR = 5;' . "\n"
. ' public const MINOR = 0;' . "\n"
. ' public const PATCH = 0;' . "\n"
. ' public const ID = 50000;' . "\n"
. ' public const PRE_RELEASE_NAME = \'alpha1\';' . "\n"
. ' public const IS_DEV = false;',
],
[
'5.0.0-alpha1',
' public const VERSION = \'5.0.0-alpha1\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'5.0\';' . "\n"
. ' public const MAJOR = 5;' . "\n"
. ' public const MINOR = 0;' . "\n"
. ' public const PATCH = 0;' . "\n"
. ' public const ID = 50000;' . "\n"
. ' public const PRE_RELEASE_NAME = \'alpha1\';' . "\n"
. ' public const IS_DEV = false;',
],
[
'5.1.0-dev',
' public const VERSION = \'5.1.0-dev\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'5.1\';' . "\n"
. ' public const MAJOR = 5;' . "\n"
. ' public const MINOR = 1;' . "\n"
. ' public const PATCH = 0;' . "\n"
. ' public const ID = 50100;' . "\n"
. ' public const PRE_RELEASE_NAME = \'dev\';' . "\n"
. ' public const IS_DEV = true;',
],
[
'9.99.99-dev',
' public const VERSION = \'9.99.99-dev\' . VERSION_SUFFIX;' . "\n"
. ' public const SERIES = \'9.99\';' . "\n"
. ' public const MAJOR = 9;' . "\n"
. ' public const MINOR = 99;' . "\n"
. ' public const PATCH = 99;' . "\n"
. ' public const ID = 99999;' . "\n"
. ' public const PRE_RELEASE_NAME = \'dev\';' . "\n"
. ' public const IS_DEV = true;',
],
];
}
/**
* @dataProvider dataProviderGoodVersions
*/
public function testGetGeneratedClassValidVersion(string $version, string $content): void
{
if (! class_exists(Command::class)) {
$this->markTestSkipped('The Symfony Console is missing');
}
$output = $this->callFunction(
$this->command,
SetVersionCommand::class,
'getGeneratedClass',
[$version]
);
$template = <<<'PHP'
<?php
declare(strict_types=1);
namespace PhpMyAdmin;
/**
* This class is generated by scripts/console.
*
* @see \PhpMyAdmin\Command\SetVersionCommand
*/
final class Version
{
// The VERSION_SUFFIX constant is defined at libraries/vendor_config.php
%s
}
PHP;
$this->assertSame(
sprintf($template, $content),
$output
);
}
}

View File

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Tests;
use PhpMyAdmin\Version;
use function defined;
class VersionTest extends AbstractTestCase
{
/**
* Validate the current version
*/
public function testValidateVersion(): void
{
$this->assertIsString(Version::VERSION);
$this->assertNotEmpty(Version::VERSION);
$this->assertStringContainsString(Version::SERIES, Version::VERSION, 'x.y must be found in x.y.z');
$this->assertIsInt(Version::MAJOR);
$this->assertIsInt(Version::MINOR);
$this->assertIsInt(Version::PATCH);
$this->assertTrue(Version::MAJOR >= 5);// @phpstan-ignore-line Just checking
$this->assertTrue(Version::MINOR >= 0);// @phpstan-ignore-line Just checking
$this->assertTrue(Version::PATCH >= 0);// @phpstan-ignore-line Just checking
$this->assertTrue(Version::ID >= 50000);// @phpstan-ignore-line Just checking
if (defined('VERSION_SUFFIX')) {
$this->assertIsString(VERSION_SUFFIX);
}
$this->assertIsInt(Version::ID);
$this->assertIsString(Version::PRE_RELEASE_NAME);
$this->assertIsBool(Version::IS_DEV);
}
}