uuf6429/elder-brother

This package is abandoned and no longer maintained. No replacement package was suggested.

Set up and manage contribution policies for your PHP-based projects.

v1.0.2 2016-12-11 13:39 UTC

This package is auto-updated.

Last update: 2020-01-22 21:38:13 UTC


README

Build Status Minimum PHP Version License Coverage Scrutinizer Code Quality Packagist

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

  1. 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.
  2. 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"
        }
    }
  3. 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.