Don't forget to change Console Application version before publishing a new release
llaville opened this issue · comments
As lot of others application that provide a Symfony Console Application, PHPLint suffer to a hard-coded concept about Application versionning.
Look at https://github.com/overtrue/phplint/blob/9.1/src/Console/Application.php#L39
As maintainer of application, if we forgot to change VERSION value before publish a new version, we will keep an outdated version number on all official versions : including PHAR and Docker distributions.
To avoid such issue, here is my proposal :
Add a new PHP CS Fixer to check and fix Application::VERSION
on a git push hook via Composer.
composer.json
patch
diff --git a/composer.json b/composer.json
index 1d6d4e4..0c27795 100644
--- a/composer.json
+++ b/composer.json
@@ -54,6 +54,9 @@
"pre-commit": [
"composer style:fix",
"composer code:check"
+ ],
+ "pre-push": [
+ "composer qa:check"
]
},
"branch-alias": {
@@ -73,6 +76,8 @@
"@composer bin all install --ansi"
],
"cghooks": "vendor/bin/cghooks",
+ "qa:check": "vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.release.php --using-cache=no --verbose --ansi --diff --dry-run",
+ "qa:fix": "vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.release.php --using-cache=no --verbose --ansi",
"style:check": "vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php --using-cache=no --verbose --ansi --diff --dry-run",
"style:fix": "vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php --using-cache=no --verbose --ansi",
"tests:unit": "vendor/bin/phpunit --testsuite=cache,configuration,finder",
@@ -84,6 +89,8 @@
"minimum-stability": "dev",
"prefer-stable": true,
"scripts-descriptions": {
+ "qa:check": "Run QA style checks before pushing new tag and releasing a new version (only dry run - no fixing!).",
+ "qa:fix": "Run QA style checks and fix violations.",
"style:check": "Run style checks (only dry run - no fixing!).",
"style:fix": "Run style checks and fix violations.",
"tests:unit": "Run unit tests on following components: cache, configuration, finder",
With new PHP CS Fixer config file .php-cs-fixer.release.php
<?php
require_once 'vendor-bin/php-cs-fixer/src/ApplicationVersionFixer.php';
use Overtrue\CodingStandard\Fixer\ApplicationVersionFixer;
return (new PhpCsFixer\Config())
->registerCustomFixers([
new ApplicationVersionFixer(),
])
->setRules([
ApplicationVersionFixer::name() => true,
])
->setFinder(
PhpCsFixer\Finder::create()
->in([__DIR__.'/src/Console'])
)
;
And new Fixer
<?php
namespace Overtrue\CodingStandard\Fixer;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use SplFileInfo;
/**
* @link https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/cookbook_fixers.rst
* @link https://tomasvotruba.com/blog/2017/07/24/how-to-write-custom-fixer-for-php-cs-fixer-24
*
* @author Laurent Laville
* @since Release 9.1.0
*/
final class ApplicationVersionFixer extends AbstractFixer
{
/**
* @inheritDoc
*/
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isAllTokenKindsFound([T_CLASS, T_CONSTANT_ENCAPSED_STRING]);
}
/**
* @inheritDoc
*/
public function isRisky(): bool
{
return false;
}
protected function applyFix(SplFileInfo $file, Tokens $tokens): void
{
foreach ($tokens as $index => $token) {
if (!$token->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) {
continue;
}
if (!$this->isVersionConst($tokens, $index)) {
continue;
}
$tag = @exec('git describe --tags --abbrev=0 2>&1');
if ($token->getContent() !== $tag) {
$tokens[$index] = new Token([$token->getId(), "'$tag'"]);
}
}
}
private function isVersionConst(Tokens $tokens, int $index): bool
{
$prevTokenIndex = $tokens->getPrevMeaningfulToken($index);
if (!$tokens[$prevTokenIndex]->equals('=')) {
return false;
}
$constantNamePosition = $tokens->getPrevMeaningfulToken($prevTokenIndex);
return $tokens[$constantNamePosition]->equals([T_STRING, 'VERSION']);
}
/**
* @inheritDoc
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Application::VERSION constant value must match the current git tag.',
[]
);
}
/**
* @inheritDoc
*/
public function getName(): string
{
return self::name();
}
public static function name(): string
{
return 'OvertrueCsFixer/application_version';
}
/**
* @inheritDoc
*/
public function supports(SplFileInfo $file): bool
{
return $file->getBasename() === 'Application.php';
}
/**
* @inheritDoc
*/
public function getPriority(): int
{
return 0;
}
}
TIP When we still want to push additional code to repository before the final release, we can by pass the qa:check
failures if any, with the --no-verify
option of git push
command.
This is the same solution, if we want to by pass style:fix
on pre-commit git hook : git commit --no-verify
@overtrue Tell me if you're agree to add a such solution !