Robo PHP - A modern task runner

Written by Pim on Monday May 16, 2016 - Comment - Permalink
Category: php - Tags: php, robo

At work, I am responsible for version management and releasing software. The process of releasing a new version is always the same: creating a change log, adding this to the documentation and in GIT, update the version number, etc. etc. etc. This set me thinking, can I automate this process? And can I do that with my favorite language PHP? Yes I can, with Robo PHP!

Robo PHP is a modern task runner written in PHP and has already some built-in tasks to have a running start.

Getting started

The tasks are saved in a RoboFile in your project. So you have to require the Robo library with composer in your project.

Because I believe you don't need Robo in production, I have added it to the require-dev section of my composer.json file:

composer require --dev codegyre/robo 

If you don't want to add Robo as a dependency to your project, you can also install it globally:

composer global require codegyre/robo

Or without composer: (caution: outdated!)

wget http://robo.li/robo.phar

First use

If robo is installed, you can use it just like robo.

To begin you have to initialize a new RoboFile in your project:

robo init

This will create a new RoboFile.php with a RoboFile class which extends \Robo\Tasks. The \Robo\Tasks class includes all bundled tasks of Robo which can be used immediately.

First task

After completing reading the documentation on the Robo website (which is v1.0.0-beta1!), I began to create my first task: release version.

Something like this:

<?php
/**
 * This is project's console commands configuration for Robo task runner.
 *
 * @see http://robo.li/
 */
class RoboFile extends \Robo\Tasks
{
    use \Task\VersionManagement\LoadTasks;
    
    /**
     * Release a new  version.
     *
     * Releasing a new  version will execute the following tasks:
     *
     * 1. Create a new release branch
     * 2. Adding the changelog changes to the CHANGELOG.md file
     * 3. Change the version number in the src/Version.php and app/config/config.yml file to given version
     * 4. Merge the release branch into the version branch
     * 5. Tag the new version
     * 6. Change the version number in the src/Version.php and app/config/config.yml file to -DEV
     * 7. Push all changes to the server
     *
     * @param null|string $branch The VCS branch where the release will start from
     * @param null|string $version The new version number
     */
    public function releaseVersion($branch = null, $version = null)
    {
        if (!$this->doesGitRepositoryExists()) {
            $this->say('Current directory has no git repository. Are you in the correct directory?');
            $this->say('Exiting ...');
            return;
        }

        if (!$this->doesChangelogExists()) {
            $this->say('CHANGELOG.md file does not exist. Creating it ...');
            $this->_exec('touch CHANGELOG.md');
            file_put_contents(
                'CHANGELOG.md',
                [
                    'Changelog' . PHP_EOL,
                    '=========' . PHP_EOL,
                    PHP_EOL // Empty line
                ]
            );
        }

        $branch = $this->askBranch($branch);
        $version = $this->askVersion($version);
        $date = $this->askReleaseDate((new \DateTime())->format('d-m-Y'));
        $nextVersion = $this->askNextVersion();
        $changelog = $this->askChangelog();

        $this
            ->taskRelease()
            ->version($version)
            ->at($date)
            ->onBranch($branch)
            ->withChangelog($changelog) // array
            ->andNextVersion($nextVersion)
            ->run();
    }

First, I check if the project has an initialized GIT repository because I want to commit everything automatically. Then I check if there is already a CHANGELOG.md file, and if not, I create one.

The ask methods gather information from the user who runs the command, like which branch should be released (we have 2.0, 2.1, ... branches):

<?php
    /**
     * Ask branch to create the release on.
     *
     * @param null|string $branch
     *
     * @return string
     */
    private function askBranch($branch = null)
    {
        if (is_null($branch)) {
            $branch = $this->ask('Which branch you want to start a release from?');
        }

        if (!$this->confirm(sprintf('Is the branch %s the branch you want to start a new release from?', $branch))) {
            $branch = $this->askBranch();
        }

        return $branch;
    }

The ask and confirm methods are available in the default task sets of Robo.

When all information is gathered, I start the task Release (not yet published, maybe later after refactoring some things!) and execute it by calling the run method.

Wrapping up

You can automate every task with Robo PHP in your favorite language in "the OOP way". Created tasks can be reused because only the RoboFile.php is in your project. The actual tasks can be available in another composer package of yours which can be used in other projects too.

The stable version of Robo PHP is v0.7.x. I tried the v1.0.0-beta1 but this version isn't stable enough for me.

The GitHub repository: https://github.com/Codegyre/Robo
The Robo website: http://robo.li/
Twitter: @robo_php