Modern task runner for PHP

Related tags

Task Runners Robo
Overview

RoboTask

Modern and simple PHP task runner inspired by Gulp and Rake aimed to automate common tasks:

Gitter Latest Stable Version Latest Unstable Version Total Downloads

ci scrutinizer codecov license

  • writing cross-platform scripts
  • processing assets (less, sass, minification)
  • running tests
  • executing daemons (and workers)
  • watching filesystem changes
  • deployment with sftp/ssh/docker

Branches

Branch Support Level Symfony Versions League Container PHP Versions
3.x Stable 4 & 5 ^3 7.1 - 8.0
2.x Not recommended 4 & 5 ^2 7.1 - 7.4
1.x Not recommended 2 - 4 ^2 5.5 - 7.4

The pre-build robo.phar is built with Symfony 5, and requires PHP 7.2+. Robo also works with Symfony 4 and PHP 7.1.3+ if packaged as a library in another application. For Symfony 2 or 3 support, or PHP versions prior to 7.1, please use the Robo 1.x branch.

All three branches of Robo are currently supported, although the 2.x and 1.x branches receive minimum support. All versions are roughly compatible; the breaking changes introduced at each major version are fairly minor, and typically only affect classes that are not used by most clients.

Installing

Phar

Download robo.phar >

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

To install globally put robo.phar in /usr/bin. (/usr/local/bin/ in OSX 10.11+)

chmod +x robo.phar && sudo mv robo.phar /usr/bin/robo

OSX 10.11+

chmod +x robo.phar && sudo mv robo.phar /usr/local/bin/robo

Now you can use it simply via robo.

Composer

  • Run composer require consolidation/robo:^3 # Use ^2 for stable
  • Use vendor/bin/robo to execute Robo tasks.

Usage

All tasks are defined as public methods in RoboFile.php. It can be created by running robo init. All protected methods in traits that start with task prefix are tasks and can be configured and executed in your tasks.

Examples

The best way to learn Robo by example is to take a look into its own RoboFile or RoboFile of Codeception project. There are also some basic example commands in examples/RoboFile.php.

Here are some snippets from them:


Run acceptance test with local server and selenium server started.

<?php

use Robo\Symfony\ConsoleIO;

class RoboFile extends \Robo\Tasks
{

    function testAcceptance(ConsoleIO $io, $seleniumPath = '~/selenium-server-standalone-2.39.0.jar')
    {
       // launches PHP server on port 8000 for web dir
       // server will be executed in background and stopped in the end
       $this->collectionBuilder($io)->taskServer(8000)
            ->background()
            ->dir('web')
            ->run();

       // running Selenium server in background
       $this->collectionBuilder($io)->taskExec('java -jar ' . $seleniumPath)
            ->background()
            ->run();

       // loading Symfony Command and running with passed argument
       $this->collectionBuilder($io)->taskSymfonyCommand(new \Codeception\Command\Run('run'))
            ->arg('suite','acceptance')
            ->run();
    }
}

If you execute robo you will see this task added to list of available task with name: test:acceptance. To execute it you should run robo test:acceptance. You may change path to selenium server by passing new path as a argument:

robo test:acceptance "C:\Downloads\selenium.jar"

Using watch task so you can use it for running tests or building assets.

<?php
class RoboFile extends \Robo\Tasks {

    function watchComposer(ConsoleIO $io)
    {
        // when composer.json changes `composer update` will be executed
        $this->collectionBuilder($io)->taskWatch()->monitor('composer.json', function() {
            $this->collectionBuilder($io)->taskComposerUpdate()->run();
        })->run();
    }
}

Cleaning logs and cache

<?php
class RoboFile extends \Robo\Tasks
{
    public function clean(ConsoleIO $io)
    {
        $this->collectionBuilder($io)->taskCleanDir([
            'app/cache',
            'app/logs'
        ])->run();

        $this->collectionBuilder($io)->taskDeleteDir([
            'web/assets/tmp_uploads',
        ])->run();
    }
}

This task cleans app/cache and app/logs dirs (ignoring .gitignore and .gitkeep files) Can be executed by running:

robo clean

Creating Phar archive

function buildPhar(collectionBuilder $io)
{
    $files = Finder::create()->ignoreVCS(true)->files()->name('*.php')->in(__DIR__);
    $packer = $this->collectionBuilder($io)->taskPackPhar('robo.phar');
    foreach ($files as $file) {
        $packer->addFile($file->getRelativePathname(), $file->getRealPath());
    }
    $packer->addFile('robo','robo')
        ->executable('robo')
        ->run();
}

We need more tasks!

Create your own tasks and send them as Pull Requests or create packages with "type": "robo-tasks" in composer.json on Packagist.

Credits

Follow @robo_php for updates.

Brought to you by Consolidation Team and our awesome contributors.

License

MIT

Comments
  • Add task collections to Robo to support rollbacks and transient objects.

    Add task collections to Robo to support rollbacks and transient objects.

    Motivation

    Robo provides a very useful way to create quick scripts that are easy to write, and easy to read. Exception handling is avoided, so the script flow is generally linear and free from unnecessary conditionals.

    What if you wanted to ensure that a script always cleaned up its transient objects, and did not continue execution after one phase failed? Robo has a useful stop-on-fail mechanism, supported in the Result class (hard exit after any task fails), and some stacks (taskFileSystemStack) also have a stop-on-fail switch. This does not always give the opportunity to clean up easily. More complicated solutions run the risk of adding a lot of conditionals to scripts. We want to keep things simple and linear, even as scripts become more complex.

    Task Collections

    This PR expands on the idea of a task stack (which currently only works for operations that are all of the same kind) to also allow the creation of task collections. Multiple tasks of different types can be queued up in a single collection, and then executed. If one task fails, the rest of the tasks in the chain are not called. Rollback and completion tasks may also be provided to help clean up.

    Example

    $collection = $this->taskCollection();
    $this->taskFileSystemStack()
          ->mkdir('logs')
          ->touch('logs/.gitignore')
          ->chgrp('logs', 'www-data')
          ->symlink('/var/log/nginx/error.log', 'logs/error.log')
          ->collect($collection, $this->taskDeleteDir('logs'));
    /// ... collect other tasks
    $collection->run();
    

    The idea here is not to try to record every last chmod, and roll them back individually, but rather to collect operation results together in a target directory that can be cleaned up if the tasks do not finish, or left intact if all goes well. In the example above, collect() replaces the run() method; it serves the same purpose, except that execution is deferred, and a second task is provided to clean up in the event of a rollback. (n.b. Scripts that do not care about rollback can continue to use direct execution via the run() method.)

    collect() is provided via the Collectable trait, which is used by the BaseTask class, so all Robo tasks are collectable. If the collected task implements the RollbackInterface, then it will be called on any rollback. If the collected task implements the CompletionInterface, then it will be called if all tasks in a collection complete without errors, or if there is a rollback. Rollback and completion tasks are only called if the task itself was executed (or attempted to be executed).

    This PR also provides for transient objects, such as temporary directories, which are always cleaned up at the completion phase of a task collection. Simple single-threaded scripts may create temporary directories without using a collection, and these will be removed when the program terminates.

    Naming Things

    I put the collections in the Robo\TaskCollection namespace, although Robo\Task\Collection might have done as well. A collection of tasks technically isa task, and task collections can be nested; all the same, perhaps $collection = $this->taskCollection(); should just be $collection = new Collection();. Instead of collect(), I might have used defer(); other names might also do here. As it stands, everything fits in nicely with existing Robo code, which can continue to work as it currently does.

    Let me know if you have any suggestions or feedback here.

    WIP 
    opened by greg-1-anderson 41
  • Abstracting process execution logic into ExecTrait.php.

    Abstracting process execution logic into ExecTrait.php.

    • Moved process execution logic outside of ExecCommand.php and Exec.php into ExecTrait.php, which is now used by them both.
    • Added ProcessExecutor, which can be used outside of collection to execute arbitrary commands.
      • ProcessExecutor extends BaseTasks so that it is able to print messages to screen and log messages.
    • Added detectInteractive() method. $this->interactive now defaults to false.
    opened by grasmash 30
  • Recommendations for automated testing of Robo Scripts/Commands?

    Recommendations for automated testing of Robo Scripts/Commands?

    Hey Greg,

    What's the best way to go about testing custom Robo Scripts, or anything extending \Robo\Tasks?

    For example, say I wanted to assert the foo method said This is a Robo script, $name in https://github.com/consolidation/Robo/blob/master/examples/robo.script ?

    Or do any unit/functional tests exist that I can look at that test https://github.com/consolidation/Robo/blob/master/examples/src/Robo/Plugin/Commands/ExampleCommands.php ?

    Thanks!

    opened by defunctl 28
  • Add concept of build properties to Robo

    Add concept of build properties to Robo

    From #509:

    Most task runners incorporate the concept of a "build properties" file, which allows a set of key value pairs to be defined in a file and passed to the task runner at run time. One particularly useful feature of Ant and Phing is that they permit property expansion in such files, see build.yml for example. Additionally, there is a convention for overriding such properties via CLI arguments. E.g., robo -Dkey=value. Is there any precedent for using such a file with Robo?

    I've created a standalone tool that at least handles the property expansion feature: https://github.com/grasmash/yaml-expander

    Requirements:

    • [x] Look for YAML config file in default location and load prior to command execution. E.g., app/config.yml. Config should be parsed, expanded, and made available to commands through a service.
    • [x] Add ability to define runtime values for build properties. E.g., robo my:command --key=value. This would override values loaded from config file.
    opened by grasmash 22
  • Error installing: composer require henrikbjorn/lurker

    Error installing: composer require henrikbjorn/lurker

    Hi, I'm installing this composer require henrikbjorn/lurker, but I have this error:

    You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug
    Do not run Composer as root/super user! See https://getcomposer.org/root for details
    Using version ^1.1 for henrikbjorn/lurker
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - Installation request for henrikbjorn/lurker ^1.1 -> satisfiable by henrikbjorn/lurker[1.1.0].
        - Conclusion: remove symfony/event-dispatcher v3.1.3
        - Conclusion: don't install symfony/event-dispatcher v3.1.3
        - henrikbjorn/lurker 1.1.0 requires symfony/event-dispatcher ~2.2 -> satisfiable by symfony/event-dispatcher[v2.2.0, v2.2.1, v2.2.10, v2.2.11, v2.2.2, v2.2.3, v2.2.4, v2.2.5, v2.2.6, v2.2.7, v2.2.8, v2.2.9, v2.3.0, v2.3.1, v2.3.10, v2.3.11, v2.3.12, v2.3.13, v2.3.14, v2.3.15, v2.3.16, v2.3.17, v2.3.18, v2.3.19, v2.3.2, v2.3.20, v2.3.21, v2.3.22, v2.3.23, v2.3.24, v2.3.25, v2.3.26, v2.3.27, v2.3.28, v2.3.29, v2.3.3, v2.3.30, v2.3.31, v2.3.32, v2.3.33, v2.3.34, v2.3.35, v2.3.36, v2.3.37, v2.3.38, v2.3.39, v2.3.4, v2.3.40, v2.3.41, v2.3.42, v2.3.5, v2.3.6, v2.3.7, v2.3.8, v2.3.9, v2.4.0, v2.4.0-RC1, v2.4.1, v2.4.10, v2.4.2, v2.4.3, v2.4.4, v2.4.5, v2.4.6, v2.4.7, v2.4.8, v2.4.9, v2.5.0, v2.5.0-RC1, v2.5.1, v2.5.10, v2.5.11, v2.5.12, v2.5.2, v2.5.3, v2.5.4, v2.5.5, v2.5.6, v2.5.7, v2.5.8, v2.5.9, v2.6.0, v2.6.1, v2.6.10, v2.6.11, v2.6.12, v2.6.13, v2.6.2, v2.6.3, v2.6.4, v2.6.5, v2.6.6, v2.6.7, v2.6.8, v2.6.9, v2.7.0, v2.7.1, v2.7.10, v2.7.11, v2.7.12, v2.7.13, v2.7.14, v2.7.15, v2.7.16, v2.7.17, v2.7.18, v2.7.19, v2.7.2, v2.7.3, v2.7.4, v2.7.5, v2.7.6, v2.7.7, v2.7.8, v2.7.9, v2.8.0, v2.8.1, v2.8.10, v2.8.11, v2.8.12, v2.8.2, v2.8.3, v2.8.4, v2.8.5, v2.8.6, v2.8.7, v2.8.8, v2.8.9].
        - Can only install one of: symfony/event-dispatcher[v2.5.0, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.0-RC1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.10, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.11, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.12, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.2, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.3, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.4, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.5, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.6, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.7, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.8, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.5.9, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.0, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.10, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.11, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.12, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.13, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.2, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.3, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.4, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.5, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.6, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.7, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.8, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.6.9, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.0, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.10, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.11, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.12, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.13, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.14, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.15, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.16, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.17, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.18, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.19, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.2, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.3, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.4, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.5, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.6, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.7, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.8, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.7.9, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.0, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.10, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.11, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.12, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.2, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.3, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.4, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.5, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.6, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.7, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.8, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.8.9, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.0, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.10, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.11, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.2, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.3, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.4, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.5, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.6, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.7, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.8, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.2.9, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.0, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.10, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.11, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.12, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.13, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.14, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.15, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.16, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.17, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.18, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.19, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.2, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.20, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.21, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.22, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.23, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.24, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.25, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.26, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.27, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.28, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.29, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.3, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.30, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.31, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.32, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.33, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.34, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.35, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.36, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.37, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.38, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.39, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.4, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.40, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.41, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.42, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.5, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.6, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.7, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.8, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.3.9, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.0, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.0-RC1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.1, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.10, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.2, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.3, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.4, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.5, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.6, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.7, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.8, v3.1.3].
        - Can only install one of: symfony/event-dispatcher[v2.4.9, v3.1.3].
        - Installation request for symfony/event-dispatcher (locked at v3.1.3) -> satisfiable by symfony/event-dispatcher[v3.1.3].
    
    
    Installation failed, reverting ./composer.json to its original content.
    
    opened by orozco1582 21
  • How to use output from tasks in subsequent tasks

    How to use output from tasks in subsequent tasks

    Steps to reproduce

    1. Task gets the filename of the recent database dump in an AWS S3 bucket using the AWS CLI.
    2. Task downloads the most recent database dump.

    Expected behavior

    I am expecting to be able to read the output of the command to determine the latest database dump and then use it in a second task to download that file.

    $result = $this->taskExec("aws s3 ls $bucket | tail -1 | awk -F ' ' '{print \$4}'")
      ->printOutput(FALSE)
      ->storeState('db-filename')
      ->run();
    $dbFilename = $result->getState('db-filename');
    

    Actual behavior

    I have read the Robo's documentation on chained state but I was unable to piece together how an example like mine would be best implemented. The closest I got was by using storeState() but it is unclear how I would reference that state arbitrarily in a subsequent exec(). Maybe what I am trying to do is possible via this method but if so, I am missing it.

    In the meantime, I have implemented what I need by using the Symfony Process component directly, but that seems less elegant than the functionality that Robo provides in other use cases.

    System Configuration

    macOS 10.15.6 PHP 7.4.9

    opened by markdorison 19
  • Task assembly

    Task assembly

    This PR introduces the concept of task assembly, which is done by way of the TaskAssembler, a helper object that helps do dependency injection on tasks that are created at runtime (as opposed to during container initialization, where the DI container can be used for this purpose).

    The old way to build tasks looks like this:

        protected function taskExtract($filename)
        {
            return new Extract($filename);
        }
    

    With task assembly, it now looks like this:

        protected function taskExtract($filename)
        {
            return $this->taskAssembler()->assemble(
                '\Robo\Task\Archive\Extract',
                [$filename]
            );
        }
    

    The benefit of using the task assembler is threefold:

    1. It will call setLogger & c. as necessary on the task, after it is constructed, reducing coupling between the different areas of the code.
    2. It recognizes tasks that implement CompletionInterface, and ensures their complete() method will be called at shutdown time, if the task is run().
    3. It also supports 'simulated' tasks, which print out what they would do when run() without actually making any persistent changes.

    This PR does not break backwards compatibility with existing external Robo tasks. Existing tasks that continue to use the old builder pattern will still work; however, they will silently ignore the --simulate flag, and execute instead. To break backwards compatibility and force old tasks to update, all that needs to be done is remove one of the last references to the Config class, and then all task printing operations will fail for tasks that have not updated to the new mechanism.

    WIP 
    opened by greg-1-anderson 19
  • Symfony 5 compatibility

    Symfony 5 compatibility

    Steps to reproduce

    Add a Symfony 5 package to your composer.json file:

    {
      "require": {
        "symfony/process": "^5.0.0"
      }
    }
    

    Expected behavior

    The installation of the Symfony 5 package succeeds.

    Actual behavior

    $ composer update
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - consolidation/robo 2.0.0 requires symfony/process ^4 -> satisfiable by symfony/process[4.0.x-dev, 4.1.x-dev, 4.2.x-dev, 4.3.x-dev, 4.4.x-dev, v4.0.0, v4.0.0-BETA1, v4.0.0-BETA2, v4.0.0-BETA3, v4.0.0-BETA4, v4.0.0-RC1, v4.0.0-RC2, v4.0.1, v4.0.10, v4.0.11, v4.0.12, v4.0.13, v4.0.14, v4.0.15, v4.0.2, v4.0.3, v4.0.4, v4.0.5, v4.0.6, v4.0.7, v4.0.8, v4.0.9, v4.1.0, v4.1.0-BETA1, v4.1.0-BETA2, v4.1.0-BETA3, v4.1.1, v4.1.10, v4.1.11, v4.1.12, v4.1.2, v4.1.3, v4.1.4, v4.1.5, v4.1.6, v4.1.7, v4.1.8, v4.1.9, v4.2.0, v4.2.0-BETA1, v4.2.0-BETA2, v4.2.0-RC1, v4.2.1, v4.2.10, v4.2.11, v4.2.12, v4.2.2, v4.2.3, v4.2.4, v4.2.5, v4.2.6, v4.2.7, v4.2.8, v4.2.9, v4.3.0, v4.3.0-BETA1, v4.3.0-BETA2, v4.3.0-RC1, v4.3.1, v4.3.2, v4.3.3, v4.3.4, v4.3.5, v4.3.6, v4.3.7, v4.3.8, v4.4.0, v4.4.0-BETA1, v4.4.0-BETA2, v4.4.0-RC1] but these conflict with your requirements or minimum-stability.
        - Installation request for consolidation/robo ^2.0.0 -> satisfiable by consolidation/robo[2.0.0].
    

    It would be cool if the version constraint of Symfony packages was relaxed. Something like:

    {
      "require": {
        "symfony/console": "^4.3.5 || ^5",
        "symfony/event-dispatcher": "^4 || ^5",
        "symfony/filesystem": "^4 || ^5",
        "symfony/finder": "^4 || ^5",
        "symfony/process": "^4 || ^5"
      }
    }
    

    See the Symfony policy about backward compatibility: https://symfony.com/doc/current/contributing/community/releases.html#backward-compatibility

    bug 
    opened by cedx 18
  • Refactoring for 0.5.0. Comments needed!

    Refactoring for 0.5.0. Comments needed!

    Robo Changes

    1. Tasks are located by following PSR-4 standard
    2. Task loading by traits are removed - this is done to simplify loading of tasks. Instead of declaring tasks in traits you can just call them with static initialization methods. Also you won't need to include lots of traits into RoboFile. Usage of static class calls instead of traits is aimed for simplicity. One task = one class = one file.
    3. Tasks initialization syntax changed to
    <?php
    
    taskChangelog::init()
        ->change('refactored Robo')
        ->version('0.5.0')
        ->run();
    ?>
    

    For one-line tasks are simplified to:

    <?php
    taskExec::_run('cap production deploy');
    
    // equal to 
    taskExec::init()
        ->exec('cap production deploy')
        ->run();
    
    // also
    taskCopyDir::_run(['/var/log', '/backup/log']);
    taskCleanDir::_run(['web/assets','tmp/','log/']);
    taskRename::_run('Dockerfile', 'tmpDockerfile');
    ?>
    

    Those commands will initializa and invoke tasks;

    4 Stack tasks changes

    <?php
    // performs actions one by one
    taskGit::stack()
        ->add('-A')
        ->commit("auto-update")
        ->pull()
        ->push()
        ->run();
    
    // clones repo
    taskGit::_clone('[email protected]:php-vcr/php-vcr.git');
    
    // equal to
    taskGit::stack()
        ->clone('[email protected]:php-vcr/php-vcr.git')
        ->run();
    ?>
    

    This goes far well for Exec:

    <?php
    // run 1 command
    taskExec::_run('grunt test');
    
    // run 2 commands
    taskExec::stack()
        ->exec('grunt test')
        ->exec('phpunit')
        ->run();
    ?>
    

    5 RoboFile must contain a namespace so FQNs could be simplified by IDE to proposed variants. Namespace can be either:

    • robo
    • Robo
    • ????
    • Robo;

    6 Directory Structure would be following:

    src/
      Command
        RoboUpdate
        RoboGlobalInstall
    
      Interfaces
        TaskInterface
        RunnableInterface
    
      Exception
        TaskException
    
      Commons
        Executable
        DynamicConfig
        CommandStack
        Output
    
      Task
        BaseTask
        FileSystem
            taskCleanDir
            taskDeleteDir
            task....
        Codeception\
            taskCodeceptRun
        PhpUnit\
            taskPhpUnit
        Minify\
            taskMinify
        Docker\
            task....
        Npm\
            taskNpmInstall
            taskNpmUpdate
        Rsync\
            taskRsync
        Svn\
            taskSvnStack
        Watch\
            taskWatch
        Exec\
            taskExec
            taskExecStack
    
    question 
    opened by DavertMik 17
  • Lay the groundwork for Robo plugins #670

    Lay the groundwork for Robo plugins #670

    Overview

    This pull request:

    • [ ] Fixes a bug
    • [x] Adds a feature
    • [x] Breaks backwards compatibility
    • [x] Has tests that cover changes

    Summary

    PR related to #670, current plan is:

    • [x] Add class discovery service + tests
    • [x] Add command discovery to Runner:run()
    • [x] ~Add event subscribers discovery~ This will be discussed in a follow-up issue.
    opened by ademarco 16
  • Adding printMetadata() option to exec command.

    Adding printMetadata() option to exec command.

    This PR introduces two new abilities:

    • Use exec task without printing command, working directory, and timer. This allows the task to be truly silent.$this->taskExec("something")->silent(true)->run();
    • Use exec task to print output but not print metadata, like the timer. This makes the call a bit more "passthru". $this->taskExec("something")->printOutput(true)->printMetadata(false)->run();
    opened by grasmash 15
  • Fix Unable to delegate to a ReflectionContainer (#1137)

    Fix Unable to delegate to a ReflectionContainer (#1137)

    Overview

    This pull request:

    • [x] Fixes a bug
    • [ ] Adds a feature
    • [ ] Breaks backwards compatibility
    • [ ] Has tests that cover changes
    • [ ] Adds or fixes documentation

    Summary

    Fixed #1137 .

    Description

    Any additional information.

    opened by mikeshiyan 1
  • Unable to delegate to a ReflectionContainer

    Unable to delegate to a ReflectionContainer

    Steps to reproduce

    I created the following executable file and ran it in terminal without any arguments:

    #!/usr/bin/env php
    <?php
    
    use League\Container\ReflectionContainer;
    use NasAutomation\Commands\RoboFile;
    use Robo\Robo;
    use Robo\Runner;
    
    define('ROOT_DIR', dirname(__DIR__));
    
    $class_loader = require ROOT_DIR . '/vendor/autoload.php';
    
    $app_name = 'Nas Automation';
    $app_version = 'dev';
    
    $application = Robo::createDefaultApplication($app_name, $app_version);
    $container = Robo::createContainer($application, NULL, $class_loader);
    
    $container->delegate(new ReflectionContainer(TRUE));
    
    Robo::finalizeContainer($container);
    
    $runner = new Runner([RoboFile::class]);
    $runner
      ->setContainer($container);
    
    $status_code = $runner->execute($_SERVER['argv']);
    exit($status_code);
    

    Expected behavior

    I expected to get the standard output, kind of:

    Usage:
      command [options] [arguments]
    
    Options:
      -h, --help ...
    

    Actual behavior

    Instead I get the fatal error:

    PHP Fatal error:  Uncaught TypeError: Symfony\Component\Console\Style\SymfonyStyle::__construct(): Argument #1 ($input) must be of type Symfony\Component\Console\Input\InputInterface, League\Container\Argument\ResolvableArgument given in /home/m/Dropbox/dev/pets/nas_automation/vendor/symfony/console/Style/SymfonyStyle.php:48
    Stack trace:
    #0 [internal function]: Symfony\Component\Console\Style\SymfonyStyle->__construct()
    #1 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/ReflectionContainer.php(58): ReflectionClass->newInstanceArgs()
    #2 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(189): League\Container\ReflectionContainer->get()
    #3 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
    #4 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Argument/ArgumentResolverTrait.php(45): League\Container\Container->get()
    #5 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(218): League\Container\Definition\Definition->resolveArguments()
    #6 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(179): League\Container\Definition\Definition->invokeMethods()
    #7 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(154): League\Container\Definition\Definition->resolveNew()
    #8 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/DefinitionAggregate.php(79): League\Container\Definition\Definition->resolve()
    #9 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(161): League\Container\Definition\DefinitionAggregate->resolve()
    #10 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
    #11 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Argument/ArgumentResolverTrait.php(45): League\Container\Container->get()
    #12 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(218): League\Container\Definition\Definition->resolveArguments()
    #13 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(179): League\Container\Definition\Definition->invokeMethods()
    #14 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(154): League\Container\Definition\Definition->resolveNew()
    #15 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/DefinitionAggregate.php(79): League\Container\Definition\Definition->resolve()
    #16 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(161): League\Container\Definition\DefinitionAggregate->resolve()
    #17 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
    #18 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Argument/ArgumentResolverTrait.php(45): League\Container\Container->get()
    #19 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(218): League\Container\Definition\Definition->resolveArguments()
    #20 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(179): League\Container\Definition\Definition->invokeMethods()
    #21 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(154): League\Container\Definition\Definition->resolveNew()
    #22 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/DefinitionAggregate.php(79): League\Container\Definition\Definition->resolve()
    #23 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(161): League\Container\Definition\DefinitionAggregate->resolve()
    #24 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
    #25 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(352): League\Container\Container->get()
    #26 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(319): Robo\Runner->registerCommandClass()
    #27 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(279): Robo\Runner->registerCommandClasses()
    #28 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(158): Robo\Runner->run()
    #29 /home/m/Dropbox/dev/pets/nas_automation/bin/nas(27): Robo\Runner->execute()
    #30 {main}
      thrown in /home/m/Dropbox/dev/pets/nas_automation/vendor/symfony/console/Style/SymfonyStyle.php on line 48
    

    System Configuration

    Linux, PHP 8.2.0, robo 4.0.3, league/container 4.2.0.

    Proposed solution

    There is a code in \Robo\Robo::configureContainer:

    self::addShared($container, 'parameterInjection', \Consolidation\AnnotatedCommand\ParameterInjection::class)
        ->addMethodCall('register', ['Symfony\Component\Console\Style\SymfonyStyle', 'symfonyStyleInjector'])
        ->addMethodCall('register', ['Robo\Symfony\ConsoleIO', 'consoleIOInjector']);
    

    Because the Symfony\Component\Console\Style\SymfonyStyle is a real class, the ReflectionContainer tries to instantiate it and fails. Anyway this is undesirable behavior - the register method uses 1st argument as an array key.

    I propose to wrap these arguments (SymfonyStyle & ConsoleIO) in \League\Container\Argument\Literal\StringArgument objects. This way a container delegation works as expected.

    opened by mikeshiyan 0
  • PHP 8.2 support

    PHP 8.2 support

    According to the README.md non of the 3.x or 4.x branches support PHP 8.2, but I think sooner or later PHP 8.2 should be supported, at least by the 4.x branch.

    consolidation/robo:3.0.11 with PHP 8.2 the Exec task throws the following deprecation message:

    Deprecated: Use of "self" in callables is deprecated in /.../src/Task/Base/Exec.php on line 66

    There might be other problems as well.

    opened by Sweetchuck 3
  • Apigen integration is mostly outdated

    Apigen integration is mostly outdated

    Most of the parameters of Apigen seem to be failing. An open issue (#177) implies that some of these deprecated parameters were outdated seven years ago. Would it make sense to remove Apigen support maybe completely (so users of Robo will do a simple CLI call to the script)? Or maybe removing most of the parameters and leaving the config parameter to allow configuration via neon-config-file only?

    Basically, none of the current config parameters of Apigen are working or corresponding to existing Apigen parameters; only the config parameter (compared to the robo.li documentation) is doing its job.

    Maybe this is a version-related issue. I realized that composer require apigen/apigen will load a version 4+, and the latest version seems to be a version 7+.

    It's the only php-doc generator supported by robo.li. I think either fixing its implementation or create a more general inclusion (and adding tools like phpdox and phpdocumentor) would be useful/helpful.

    opened by davidsneighbour 0
  • Docs:

    Docs: "Edit on Github" links not working

    opened by davidsneighbour 0
  • Extended robo files are not parsed for commands for consolidation/annotated-command >= 4.5.7

    Extended robo files are not parsed for commands for consolidation/annotated-command >= 4.5.7

    Steps to reproduce

    1. Upgraded consolidation/annotated-command to a version >= 4.5.7 (4.6.0, in my case).
    2. Run vendor/bin/robo list

    I've tracked down the issue to this commit from this list of commits. I can see it skip over the command in my debugger because the class of the initially loaded robo file does not match the extended one.

    I believe it boils down to the way I've structured the RoboFile, which may be an anti-pattern, and I'm open to any suggestions.

    In the RoboFile, I extend another RoboFile. The original RoboFile is used to to override methods from the extended file. This wasn't done so much to completely replace a command but instead override the helper functions that were not commands but had full access to robo.

    RoboFile.php

    
    require_once 'RoboFileSite.php';
    
    class RoboFile extends \RoboFileSite
    {
        
    }
    

    RoboFileSite.php

    
    class RoboFileSite
    {
    
      function hello(\Robo\Symfony\ConsoleIO $io, array $world)
      {
        $io->say("Hello, " . implode(', ', $world));
      }
    }
    

    Expected behavior

    The 'hello' command is listed.

    Actual behavior

    The 'hello' command is not listed.

    System Configuration

    Linux PHP 8.1 wodby/php:8.1-dev-4.32.7

    opened by mattsqd 3
Releases(3.0.4)
Owner
Consolidation
Common projects for use by various command line / console tools.
Consolidation
Modern and simple PHP task runner inspired by Gulp and Rake aimed to automate common tasks

RoboTask Modern and simple PHP task runner inspired by Gulp and Rake aimed to automate common tasks: writing cross-platform scripts processing assets

Consolidation 2.6k Jan 3, 2023
Pure PHP task runner

task/task Got a PHP project? Heard of Grunt and Gulp but don't use NodeJS? Task is a pure PHP task runner. Leverage PHP as a scripting language, and a

null 184 Sep 28, 2022
A versatile and lightweight PHP task runner, designed with simplicity in mind.

Blend A versatile and lightweight PHP task runner, designed with simplicity in mind. Table of Contents About Blend Installation Config Examples API Ch

Marwan Al-Soltany 42 Sep 29, 2022
Awesome Task Runner

Bldr Simplified Build System/Task Runner Uses Yaml, JSON, XML, PHP, or INI for configs Quick Usage To develop, run ./script/bootstrap, and then ./scri

null 223 Nov 20, 2022
Yii application runner

Yii application runner The package defines Yii application runner. Requirements PHP 7.4 or higher. Installation The package could be installed with co

Yii Software 9 Oct 15, 2022
🐺 Asynchronous Task Queue Based on Distributed Message Passing for PHP.

?? Asynchronous Task Queue Based on Distributed Message Passing for PHP.

Ahmed 36 Aug 11, 2022
A PHP implementation of a bare task loop.

TaskLoop A PHP implementation of a bare task loop. Installation. $ composer require thenlabs/task-loop 1.0.x-dev Usage. The file example.php contains

ThenLabs 1 Oct 17, 2022
Flow Framework Task Scheduler

This package provides a simple to use task scheduler for Neos Flow. Tasks are configured via settings, recurring tasks can be configured using cron syntax. Detailed options configure the first and last executions as well as options for the class handling the task.

Flowpack 11 Dec 21, 2022
Manage your Laravel Task Scheduling in a friendly interface and save schedules to the database.

Documentation This librarian creates a route(default: /schedule) in your application where it is possible to manage which schedules will be executed a

Roberson Faria 256 Dec 21, 2022
Task Scheduling with Cron Job in Laravel

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Shariful Islam 1 Oct 16, 2021
Laravel-Tasks is a Complete Build of Laravel 5.2 with Individual User Task Lists

An app of tasks lists for each individual user. Built on Laravel 5.2, using 5.2 authentication and middleware. This has robust verbose examples using Laravel best practices.

Jeremy Kenedy 26 Aug 27, 2022
xcron - the souped up, modernized cron/Task Scheduler for Windows, Mac OSX, Linux, and FreeBSD server and desktop operating systems.

xcron is the souped up, modernized cron/Task Scheduler for Windows, Mac OSX, Linux, and FreeBSD server and desktop operating systems. MIT or LGPL.

CubicleSoft 7 Nov 30, 2022
Laravel Cron Scheduling - The ability to run the Laravel task scheduler using different crons

Laravel Cron Scheduling Laravel Task Scheduling is a great way to manage the cron. But the documentation contains the following warning: By default, m

Sergey Zhidkov 4 Sep 9, 2022
Reset the live preset for debug settings with a task

Debug Settings Task This TYPO3 extension resets TYPO3 debug settings to the »live« preset on production using a scheduler task. Vision “Better safe th

webit! Gesellschaft für neue Medien mbH 1 Aug 15, 2022
PHP cron job scheduler

PHP Cron Scheduler This is a framework agnostic cron jobs scheduler that can be easily integrated with your project or run as a standalone command sch

Giuseppe Occhipinti 698 Jan 1, 2023
PHP port of resque (Workers and Queueing)

php-resque: PHP Resque Worker (and Enqueue) Resque is a Redis-backed library for creating background jobs, placing those jobs on one or more queues, a

Chris Boulton 3.5k Jan 5, 2023
Elegant SSH tasks for PHP.

Laravel Envoy Introduction Laravel Envoy provides a clean, minimal syntax for defining common tasks you run on your remote servers. Using Blade style

The Laravel Framework 1.5k Jan 1, 2023
Crunz is a framework-agnostic package to schedule periodic tasks (cron jobs) in PHP using a fluent API.

Crunz Install a cron job once and for all, manage the rest from the code. Crunz is a framework-agnostic package to schedule periodic tasks (cron jobs)

Reza Lavarian 1.4k Dec 26, 2022
A PHP-based job scheduler

Crunz Install a cron job once and for all, manage the rest from the code. Crunz is a framework-agnostic package to schedule periodic tasks (cron jobs)

null 58 Dec 26, 2022