uuf6429 / elder-brother
Set up and manage contribution policies for your PHP-based projects.
Installs: 13
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 2
Forks: 0
Open Issues: 8
Type:application
Requires
- php: ^5.5.0 || ^7.0
- psr/log: ^1.0
- symfony/console: ^3.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^1.11
- phpunit/phpunit: ^4.8
Suggests
- friendsofphp/php-cs-fixer: Needed for PhpCsFixer action
This package is auto-updated.
Last update: 2020-01-22 21:38:13 UTC
README
Elder Brother automatically regulates contributions before reaching your project.
Using events such as Git-hooks, one can ease development in various ways, such as:
- ensure code style conformity before committing changes
- run tools whose output should be a part of the commit
- performing roll-backs when checking-out old commits
- compiling sources or performing migrations when checking-out newer commits
This tools makes it easy to set up these tasks, as well as putting such policies under version control.
Table Of Contents
Installation
-
Add the library to your project with Composer:
$ composer require neronmoon/scriptsdev $ composer require uuf6429/elder-brother "~1.0" --dev
Notes:
- in this way, Elder Brother will only be installed during development (Composer should be run with
--no-dev
in production). scriptsdev
package will make installation work during development and not break during production.- you may still have to install additional packages (detailed below) to use some particular actions.
- in this way, Elder Brother will only be installed during development (Composer should be run with
-
Add the following entry to your
composer.json
:{ "scripts-dev": { "post-install-cmd": "vendor/bin/elder-brother install", "post-update-cmd": "vendor/bin/elder-brother install" } }
-
Create a
.brother.php
config file (as described below) and add.brother.local.php
to your.gitignore
file (this allows for user-level config).
Usage
Elder Brother by default reads configuration from two files, .brother.php
and .brother.local.php
(which should be ignored by your VCS).
A typical configuration file will be structured like this:
<?php use uuf6429\ElderBrother\Action; use uuf6429\ElderBrother\Event; use uuf6429\ElderBrother\Change\GitChangeSet; return [ Event\Git::PRE_COMMIT => [ 1 => new Action\PhpLinter( GitChangeSet::getAddedCopiedModified() ->name('/\\.php$/') ), 2 => new Action\PhpCsFixer( GitChangeSet::getAddedCopiedModified() ->name('/\\.php$/') ), ] ];
Basically, the configuration is an array of actions grouped by event.
In the above example, PhpLinter
and PhpCsFixer
actions will check all files (GitChangeSet::getAddedCopiedModified()
) in the commit before it takes place (Event\Git::PRE_COMMIT
).
It is recommended that you give each action a defined numeric index, so that they can be easily overridden by user config.
Note that no matter how the items look like in the array, action execution starts from the smallest index.
Available Actions
Execute Custom Code (ExecuteCode)
new ExecuteCode( string $description, // Description of the intention of the callback callable $callback // The callback to execute. It will receive $config, $input and $output as parameters )
Executes the passed callback, function or static method.
Execute External Program (ExecuteProgram)
new ExecuteProgram( string $description, // Description of the intention of the program string $command, // Program command line (with parameters) bool $breakOnFailure, // (Optional, default is true) Stop execution if program returns non-0 exit code array|null $environment, // (Optional, default is null / current vars) Environment variables to pass to program string|null $currentDir, // The current directory to use for program int $timeout // (Optional, default is 60) The time to wait for program to finish (in seconds) )
Executes an external program.
Disallow Files (ForbiddenFiles)
new ForbiddenFiles( \FileList $files, string $reason )
Will stop process if $files
is not empty, for the reason specified in $reason
.
PHP Code Style Fixer (PhpCsFixer)
new PhpCsFixer( \FileList $files, // The files to check int|null $level, // (Optional, defaults to NONE_LEVEL) Fixer level to use string[] $fixers, // (Optional, default is empty) Set the fixers to use bool $addAutomatically // (Optional, default is true) Whether to add modified files to commit or not )
Runs all the provided files through PHP-CS-Fixer, fixing any code style issues.
PHP Code Style Fixer (PhpCsFixerOld)
new PhpCsFixerOld( \FileList $files, // The files to check string|null $binFile, // (Optional, default is from vendor) File path to PHP-CS-Fixer binary string|null $configFile, // (Optional, default is project root) File path to PHP-CS-Fixer config bool $addAutomatically // (Optional, default is true) Whether to add modified files to commit or not )
Deprecated: Use PhpCsFixer class instead.
Runs all the provided files through PHP-CS-Fixer, fixing any code style issues.
PHP Syntax Check (PhpLinter)
new PhpLinter( \FileList $files // The files to check )
Ensures that all the provided files are valid PHP files, terminating the process with an error and non-zero exit code, if not.
Show Warning For Files (RiskyFiles)
new RiskyFiles( \FileList $files, string $reason )
Will show a warning if $files
is not empty, for the reason specified in $reason
.
FAQ
What is the main motivation behind this tool?
Projects with a considerable amount of collaborators usually ends up with policies of what kind of patches are accepted. This is usually enforced through code-reviews (which can be very time-consuming), custom tools (difficult to set up) or shell scripts in pre-commit hooks (difficult to maintain and not really scalable).
The main idea here is to have a framework on the client side to enforce project contribution policies even before the source code reaches the main repository - saving developer time and maintenance costs.
Why in PHP?
Why not? There are two alternatives: shell scripts and other languages. Shell scripts have many disadvantages for this use - they're not cross-platform compatible, nor easily understandable. Other languages might be suitable, but it means requiring your collaborators to know them. We're basically using what's already available in the ecosystem.