/Beard

Primary LanguagePHP

What is Beard?

Beard is a tool that allows to patch Flow applications during deployment. This can be used to apply changes that are still under review to your deployments, e.g. if you tested something and need the bugfix or feature before a release containing it is made available.

Installation

Download to local directory

curl -s http://beard.famelo.com/ > beard.phar
chmod +x beard.phar

Now Beard can be used by calling it like this:

./beard.phar

Move to global location

You can move the phar file to a location in your path to use it more conveniently:

mv beard.phar /usr/local/bin/beard

Updating Beard

Beard has self-update built in, you can call this to update to the latest release:

beard update

Beard in your workflow

For the use of Beard to patch your project the following is recommended.

Make sure you use the development collections of Flow and Neos in your project

The changes you will apply will be PRs most of the time, and those are made against the development collections of Flow and Neos. To be able to apply them, the local repository must also be a clone of those collections.

Since the collections replace the single packages they contain transparently, this is not a big deal.

Keep your beard.json up-to-date

Beard will tell you if changes in your beard.json are merged or closed unmerged. In both cases you should probably remove the change from beard.json as soon as possible: Either it is not needed as soon as a new release is available or it has been considered unfit for merging. In the latter case it probably just adds problems to your project.

Treat patching like schema migrations

Whenever you update a working copy from git, run beard patch (as you should do with flow doctrine:migrate) to make sure you have the latest required patches.

Make patching part of the deployment

Always patch when deploying a new version. In case you use Surf, this can be done like this in your deployment descriptor:

$workflow->defineTask(
    'x:beardpatch',
    'typo3.surf:localshell',
    array('command' => 'cd "{workspacePath}" && php beard.phar patch')
);
$workflow->beforeStage('transfer', 'x:beardpatch');

The above example assumes you use local packaging with git and rsync for transfer. If you don't, the stage needs to be adjusted. Also, adjust the way beard can be called (the example assumes it is checked in with your project).

Configuration

To use Beard for patching your project, you need to create a beard.json file in the root directory of your project. There you can specify patches, GitHub PRs and gerrit changes that you need to pull in for your project. This makes it easier to distribute development instances to other developers, that depend on pending gerrit changes or other patches.

beard.json

{
    "defaults": {
        "gerrit_api_endpoint": "https://review.typo3.org/",
        "gerrit_git": "git.typo3.org"
    },
    "changes": [
        {
            "name": "all commits of a github pull-request",
            "type": "github",
            "repository": "neos/neos-development-collection",
            "pull_request": "8",
            "path": "Packages/Neos"
        },
        {
            "name": "some specific github commit",
            "type": "github",
            "repository": "kitsunet/neos-development-collection",
            "commit": "cef11fdc9c9094ddaa204bd5a8b47005283817b5",
            "ref": "fix-foobar",
            "path": "Packages/Framework"
        },
        {
            "name": "Some changes out of a diff file",
            "type": "diff",
            "path": "Packages/Framework/TYPO3.Flow",
            "file": "Patches/TYPO3.Flow.diff"
        },
        {
            "name": "Simple gerrit change",
            "type": "gerrit",
            "path": "Packages/Framework/TYPO3.Flow",
            "change_id": "16392"
        },
        {
            "name": "Using a specific change patch set",
            "type": "gerrit",
            "path": "Packages/Framework/TYPO3.Flow",
            "change_id": "16392"
        },
        {
            "name": "Pull in a complete Gerrit Topic into all existing package directories",
            "type": "gerrit",
            "topic": "acl",
            "branch": "master",
            "paths": {
                "Packages/TYPO3.Neos": "Packages/Application/TYPO3.Neos"
            }
        }
    ]
}

GitHub changes:

  • Before cherry picking commits, the working directory is changed to path in a change, relative to the project root
  • The ref on a GH commit is optional, if not given, all heads of the repository will be fetched

Patch files:

  • For patch files, the file path is relative to the project root. To create a patchable *.diff file you might have to use the option for no color: git diff --no-color > TYPO3.Flow.diff

Gerrit changes:

  • The defaults for gerrit_api_endpoint and gerrit_git can be overridden for each change by supplying new values for those keys.
  • You can append the patch set number with a comma after the change id to use the specific patch set instead of the latest: "change_id": "16392,2"
  • For topics, the paths specify the exact path for each gerrit project name. If a path is missing here and the project is in the form of Packages/<PackageName> Beard will loop through the directories in Packages looking for a matching folder (Packages/(Application|Framework|Site|...)/<PackageName>).

Note: with the move of Neos and Flow to GitHub applying Gerrit patches no longer makes sense and will probably not work at all.

Commands

Running beard list will list all available commands. Help for a command can be displayed with beard help <command>.

lock - Lock package to currently used commit

Adjusts the composer manifest to lock the given package to the SHA1 that is currently installed according to composer.lock.

beard lock <vendor/package>

Note: This will only work correctly of the package dependency is pointing to a branch.

patch - Patch and update repositories based on beard.json

Reads the beard.json file and applies all patches as needed.

beard patch

reset - Reset all repositories beneath this directory, removing any unpushed changes and applied patches

This command resets all repositories beneath the main directory to it's remote state.

beard reset

Warning: This will remove any non-pushed changes from the local repositories, so be careful!

setup - Add commit hooks and gerrit push remotes to all repositories

Since Flow and Neos moved to GitHub, this is no longer needed.

status - Show the current status of all git repositories inside this directory

The status command helps you to get an overview over all repositories beneath this directory.

beard status

Similarity to Famelo.Gerrit

If you know Famelo.Gerrit, the TYPO3.Flow package you might think this is already covered by that, which is true. Actually this tool is an evolution of Famelo.Gerrit, which i choose to make standalone. Main pro's to make it standalone are:

  • it works even with completely broken Flow project/installations
  • you can use it for almost any kind of project

And just one more thing. "beard patch" will look and process your old "gerrit.json" for now as well :)

Bash/ZSH autocomplete

You can enable cli autocomplete for commands like this:

# BASH ~4.x, ZSH
source <(beard _completion --generate-hook)

# BASH ~3.x, ZSH
beard _completion --generate-hook | source /dev/stdin

# BASH (any version)
eval $(beard _completion --generate-hook)

If you want the completion to apply automatically for all new shell sessions, add the command from step 3 to your shell's profile (eg. ~/.bash_profile or ~/.zshrc)

Based on: https://github.com/stecman/symfony-console-completion