Welcome to Bldr’s documentation!

Bldr, in the simplest terms, is a task runner, and an awesome one at that. It was written with simpler configs in mind. If you are used to build systems, you’ve probably seen some pretty complicated build files, and they were probably written in xml that is clunky and a pain to maintain.

Well, here’s one written for Bldr using yaml (json and php are also supported):

This is a sample configuration. Your project may not have the dependencies required to run this configuration.

bldr:
    name: bldr-io/bldr
    description: Super Extensible and Awesome Task Runner

    profiles:
        default:
            description: Development Profile
            jobs:
                - prepare
                - lint
                - phpcs
                - test

    jobs:
        prepare:
            description: Cleans up old builds and prepares the new one
            tasks:
                -
                    type: filesystem:remove
                    continue
                    files: [build/coverage, build/logs]
                -
                    type: filesystem:mkdir
                    files: [build/coverage, build/logs]
                -
                    type: filesystem:touch
                    files: [build/coverage/index.html]
                -
                    type: exec
                    executable: composer
                    arguments: [install, --prefer-dist]
        lint:
            description: Lints the files of the project
            tasks:
                -
                    type: apply
                    src:
                        - { path: [src, tests], files: *.php, recursive: true } # Checks src and tests directories for *.php files recursively
                    executable: php
                    arguments: [-l]

        phpcs:
            description: Runs the PHP Code Sniffer
            tasks:
                -
                    type: exec
                    executable: php
                    arguments:
                        - bin/phpcs
                        - -p
                        - --standard=build/phpcs.xml
                        - --report=checkstyle
                        - --report-file=build/logs/checkstyle.xml
                        - src/
        test:
            description: Runs the PHPUnit Tests
            tasks:
                -
                    type: exec
                    executable: php
                    arguments:
                        - bin/phpunit
                        - --testdox
                        - --coverage-text=php://stdout

And here’s the output:

_images/demo1.png _images/demo2.png

For now (while we are still working on the documentation), this will hopefully serve as ample documentation.

Content

Installation

This should be installed via composer, for now. You can either install it globally, or in your own project. If it is the first time you globally install a dependency then make sure you include ~/.composer/vendor/bin in $PATH as shown here.

Global Setup

$ composer global require bldr-io/bldr=~7.0.0 dflydev/embedded-composer=dev-master@dev composer/composer=dev-master@dev

# Or

$ curl -sS http://bldr.io/installer | php
$ mv bldr.phar /usr/bin/bldr

# You can also install specific versions (Anything greater or equal to 5.0.0)
# Example: 5.0.0, 5.0.1, stable (latest tag in github), dev (last commit in master)
$ curl -sS http://bldr.io/installer | php -- --version=dev # Stable by default

Project Setup

It is suggested that you use the phar, as you can get conflicts with dependencies by including it in your project or globally!

$ curl -sS http://bldr.io/installer | php

# Or

$ composer require bldr-io/bldr "~7.0.0"

And that’s it! From here, you should be able to run bldr if you set it up globally, or ./bin/bldr or php ./vendor/bin/bldr if you set it up in your project.

Usage

To start, you are going to want to generate a .bldr.yml file for your project. This (for now) has to be done manually, but it’s pretty simple.

Create a .bldr.yml(.dist) file:

bldr:
    name: some/name
    description:  A description about the project # (Not Required)
    profiles: # A list of profiles that can be ran with `./bldr.phar run`
        someJob:
            description: Gets ran when `./bldr.phar run someJob` is called
            jobs:
                - foo
        someOtherJob:
            jobs:
                - bar
        inheritanceExample:
            description: Will run the tasks from `someJob` and then `someOtherJob`.
            uses:
                before: [someJob]
                after: [someOtherJob]
    jobs:
        foo:
            description: Foo job
            tasks:
                -
                    type: exec
                    executable: echo
                    arguments: [Hello World]
        bar:
            description: Bar job
            tasks:
                -
                    type: exec
                    executable: sleep
                    arguments: [1]

To view a list of available task types, run:

./bldr.phar task:list

And to get more information on a particular task, run:

./bldr.phar task:info <task name>

To run your profiles: (This has changed since version 7)

./bldr.phar run <profile name>

Extensions

When starting Bldr, I wanted it to be highly extensible, and because of that, I decided to use the Symfony2 Dependency Injection component, but Bldr takes it a step further. Its mostly just a rename with a little added functionality for ease of use.

With that, we’ve come up with the idea for Bldr Blocks. Bldr Blocks are basically Symfony Extensions (with a little difference), that add some functionality to bldr. There are a bunch of Bldr Blocks already in the core of bldr, and they are listed below. To find other blocks, we are working on a site where people will be able to upload links to their repositories. But in the mean time, just use the list below. If I missed anything, you can find it here: https://www.versioneye.com/php/bldr-io:bldr/references

  • Frontend Block - Used for tasks like CSS/JS Minification and Less/Sass/SCSS/Coffeescript compilation
  • Gush Block - Used for integrating with Gush
  • [Out Of Date] Symfony Block - Used for integrating with the Symfony2 Framework
  • [Out Of Date] Git Block - Used for integrating with git

To add your own task types to Bldr, you will have to write your own Bldr Block. By default, there are a couple blocks that already come with Bldr, but it is easy enough to add your own. For a quick baseline on how to write one, check out the documentation.

Adding third party blocks is a three step process. First, you need to create a bldr.json file (if you don’t have one):

{
    "require": {
        "acme/demo-block": "@stable"
    }
}

Then, install/update your bldr dependencies:

./bldr.phar install
# OR
./bldr.phar update

Then, add it to your .bldr.yml file:

bldr: ~

# If you have configs
acme_demo:
    some_setting: some_value

Below is some minor documentation on the core blocks.

Execute Block (Official)

The Execute Block (Included with Bldr)

This extension lets you run exec and apply tasks.

jobs:
    sample:
        tasks:
            -
                task: exec
                executable: php
                arguments: [bin/phpcs]
            -
                task: apply
                executable: php
                output: /dev/null
                src:
                    - { path: [src, tests], files: *.php, recursive: true } # Checks src and tests directories for *.php files recursively
                arguments: [-l]

Filesystem Block (Official)

The Filesystem Block (Included with Bldr)

This extension lets you run filesystem commands.

This one needs some work, as not all of the commands are there (mkdir, remove, touch, and dumpFile are).

Some examples:

jobs:
    sample:
        tasks:
            -
                task: filesystem:mkdir
                files: [testDir]
            -
                task: filesystem:remove
                files: [testDir]
            -
                task: filesystem:touch
                files: [test.tmp]

Notify Block (Official)

The Notify Block (Included with Bldr)

This extension lets you run the notify commands. It will either print to the screen, or email a message.

To use this:

jobs:
    sample:
        tasks:
            -
                task: notify
                message: Test Message
                email: test@gmail.com

When adding this extension, you can specify smtp connections:

notify:
    smtp:
        host: smtp.google.com
        port: 465
        security: ssl
        username: google
        password: is4wesome

Watch Block (Official)

The watch Block (Included with Bldr)

This extension lets you run the watch commands. It will let you watch the filesystem for changes.

This one needs some work. Right now, you can only have one watch task.

jobs:
    sample:
        tasks:
            -
                task: watch
                src:
                    - { path: [src, tests], files: *.php, recursive: true } # Checks src and tests directories for *.php files recursively
                    - { path: vendor/, files: [*.php, *.yml], recursive: true } # Checks vendor/ directory for *.php and *.yml files recursively
                profile: someProfile
    sample2:
        tasks:
            -
                task: watch
                src:
                    - { path: [src, tests], files: *.php, recursive: true } # Checks src and tests directories for *.php files recursively
                    - { files: *.yml } # Checks current directory, non-recursively
                task: someTask

Creating A Block

Creating a Bldr Block for Bldr is fairly similar to creating a Bundle for Symfony. Here’s a quick guide:

1. Create a repo

Try and stay with the naming convention used by the other blocks: <name>-block

2. Initialize composer in the repo

cd your-repo && composer init

3. Add Bldr as a dev dependency

In your composer.json file, you will want to add bldr-io/bldr as a require-dev dependency. Because embedded composer and composer are unstable packages by definition or they do not have a stable release you will have to add them too into your composer.json as below:

{
    "require-dev": {
        "bldr-io/bldr":              "~7.0.0",
        "dflydev/embedded-composer": "dev-master@dev",
        "composer/composer":         "dev-master@dev"
    }
}

4. Create a Block class

All of bldr, and the official extensions follow PSR-4 (as well as all the other applicable PSR’s, and most, if not all, of the bylaws). With that, create your directory structure and your Block class:

mkdir src && vim src/AcmeDemoBlock.php

All blocks must extend the BldrDependencyInjectionAbstractBlock, so your class, empty, will look something like this:

src/AcmeDemoBlock.php

<?php

/**
 * License Information
 */

namespace Acme\Block\Demo;

use Bldr\DependencyInjection\AbstractBlock;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * @author John Doe <john@doh.com>
 */
class AcmeDemoBlock extends AbstractBlock
{
    /**
     * {@inheritDoc}
     */
    protected function assemble(array $config, ContainerBuilder $container)
    {
    }
}

The assemble function is where the magic happens. If you take a look at the AbstractBlock, there are some helper functions in there to make it easier to add new calls, services, and parameters to the Container.

5. Create your Task

As a demo, let’s say we want to make a task that will output a random number to the user when running the task.

First, lets create the task. Directory structure doesn’t really matter, but the core structure is normally src/Task/<Name>Task.php. Similar to blocks, all tasks should extend `Bldr\Block\Core\Task\AbstractTask`_ and must implement `Bldr\Task\TaskInterface`_.

Lets make the src/Task directory, and create the new task: .. code-block:: shell

mkdir src/Task && vim src/Task/OutputRandomNumberCall.php

Then, let’s build the task class! Extending the AbstractTask, suggests that we implement configure and requires that we implement run.

src/Task/OutputRandomNumberTask.php

<?php

/**
 * License Information
 */

namespace Acme\Block\Demo\Task;

use Bldr\Block\Core\Task\AbstractTask;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author John Doe <john@doh.com>
 */
class OutputRandomNumberTask extends AbstractTask
{
    /**
     * {@inheritDoc}
     */
    public function configure()
    {
        $this->setName('acme_demo:output_random_number')
            ->setDescription('This call outputs a random number. If min and max are specified, it will use those as the range')
            ->addParameter('min', true, 'Minimum number in range', 0)
            ->addParameter('max', true, 'Maximum number in range', 100)
        ;
    }

    /**
     * {@inheritDoc}
     */
    public function run(OutputInterface $output)
    {
        $random = rand($this->getParameter('min'), $this->getParameter('max'));
        $output->writeln(['', 'Random Number: '.$random, '']);
    }
}

Next, we need to add the task to the container, so we can use it in .bldr.yml(.dist) files:

src/AcmeDemoBlock.php

<?php

/**
 * License Information
 */

namespace Acme\Block\Demo;

use Bldr\DependencyInjection\AbstractBlock;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * @author John Doe <john@doh.com>
 */
class AcmeDemoBlock extends AbstractBlock
{
    /**
     * {@inheritDoc}
     */
    protected function assemble(array $config, ContainerBuilder $container)
    {
        // Here's one of the shortcut methods! This method will return a Symfony DI Definition
        // that is tagged as `bldr`. If you need to, you can easily add arguments to the constructor,
        // or calls to methods.
        $task = $this->addTask('acme_demo.output_random_number', 'Acme\Block\Demo\Task\OutputRandomNumberTask');

        // If you need dependencies, you could do the following:
        // $task->setArgument(0, new Reference('some_service'));
        // or
        // $arguments = array(new Reference('some_service'));
        // $task->addMethodCall('someMethodName', $arguments);

        // If you want to add a service, that isn't a task, you can also use:
        // $this->addService($name, $class);
        // Which will also return a Symfony DI Definition
    }
}

6. Register block with bldr

In the composer.json file, add the following:

{
    "extra": {
        "block-class": "Namespace\\To\\Your\\Block\\Class"
    }
}

With this, you should be able to install it with the bldr.json file and add it to a .bldr.yml file:

bldr:
    name: some/name
    profile:
        test:
            jobs:
                - randomize

    jobs:
        randomize:
            tasks:
                -
                    type: acme_demo:output_random_number
                    min: 0
                    max: 100000

And run it!

./bldr.phar run test

There’s some more advanced stuff, like being able to specify configuration:

src/AcmeDemoBlock.php

<?php

/**
 * License Information
 */

namespace Acme\Block\Demo;

use Bldr\DependencyInjection\AbstractBlock;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * @author John Doe <john@doh.com>
 */
class AcmeDemoBlock extends AbstractBlock
{
    // ...

    /**
     * {@inheritDoc}
     */
    protected function getConfigurationClass()
    {
        return 'Acme\Block\Demo\Configuration';
    }
}

7. Advanced Config

Then make a Configuration.php file. This config is the config from Symfony. You can read their docs for more information.

src/Configuration.php

<?php

/**
 * License Information
 */

namespace Acme\Block\Demo;

use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

/**
 * @author John Doe <john@doh.com>
 */
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritDoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode    = $treeBuilder->root('acme_demo');

        // here you will build the configuration tree

        return $treeBuilder;
    }
}