Search by

syp / drun

stefanpetrov

Robo-based task runner for Drupal 11 projects: site install/update, QA and git hooks.

1.1.0 2026-10-02 14:30 UTC

This package is auto-updated.

Last update: 2026-10-02 14:31:40 UTC


README

A small Robo-based task runner for Drupal 11 projects. It adds the things Drush lacks: installing from a DB dump, running commands on the host or in a container, QA tooling, git hooks and project defaults.

Install

composer require --dev syp/drun
vendor/bin/run drun:init            # runner.yml, phpcs.xml.dist, phpstan.neon.dist, settings
vendor/bin/run git:hooks-install
echo runner.local.yml >> .gitignore

The project must allow these Composer plugins:

"allow-plugins": {
  "dealerdirect/phpcodesniffer-composer-installer": true,
  "phpstan/extension-installer": true
}

Run vendor/bin/run from the project root.

Commands

CommandDoes
site:install-cleandrush site:install with drun.site settings
site:install-dump [--download] [--no-update]Drop the DB, import drun.dump.path (.sql / .sql.gz), run the deploy steps
site:updateRun drun.deploy.steps (default: drush deploy)
qa:lint / qa:phpcs / qa:phpstanRun the tool on existing drun.qa.paths
qa:auditcomposer audit --locked
qa:allRun every QA check and report all failures
git:hooks-install [--force]Write hooks from drun.git.hooks
drun:init [--force] [--docker]Copy the config templates to the project root and wire the settings files

Global options come from Robo: --simulate prints the commands without running them, and -D key=value overrides a config value for one run.

Configuration

vendor/syp/drun/config/default.yml documents every key. It is merged with runner.yml (committed) and then runner.local.yml (not committed).

  • Maps merge recursively. Lists replace the default list, so a deploy.steps override must contain every step you want.
  • ${dotted.key} tokens are expanded, e.g. ${drun.drush} deploy -y.

Exec prefix

drun.exec.prefix is prepended to commands that need PHP, Drupal or the database. Git, curl/scp and reading the dump always run on the host.

  • The runner runs where the app does (both on the host, or both inside the container): leave it empty. This is the default.
  • The runner runs on the host and the app runs in Docker: set prefix: 'docker compose exec -T web'. -T is required for dump imports. drun:init --docker writes it to a new runner.yml. Set it in runner.yml for the whole team or in runner.local.yml for one machine; -D drun.exec.prefix= clears it for one run.

Deploy steps

site:update runs drun.deploy.steps in order and stops at the first failure. Keep this list in line with the hosting deploy pipeline.

drun:
  deploy:
    steps:
      - ${drun.drush} deploy -y
      - ${drun.drush} locale:update

Settings

drun:init sets up drun.settings.dir (default web/sites/default) so production can override settings with environment variables:

FileOwnerHolds
settings.phpprojectCreated from default.settings.php if missing. drun appends one block: a fallback hash_salt, then the includes below.
settings.drun.phpdrunDB_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_PREFIX, DB_DRIVER, HASH_SALT. Replaced by drun:init --force.
settings.project.phpprojectThe project's own variables, e.g. $config['smtp.settings']['smtp_host'] = getenv('SMTP_HOST');. Never overwritten.
settings.local.phpmachineOptional, not committed; loaded last.

Commit the first three. $databases is only set when DB_NAME is set, so an existing settings.php keeps working without the variables. Set HASH_SALT in production; the fallback salt is committed.

The variables must reach PHP in web requests as well as on the command line. php-fpm drops the environment unless clear_env = no, so getenv() would work in drush but not in web requests. In Docker, pass them to the web container (e.g. env_file: .env) and reuse the same names for the database container (MARIADB_PASSWORD: ${DB_PASSWORD}).

The install and update commands need nothing extra: drush loads settings.php, which reads the environment.

Dumps

If drun.dump.path is missing, or --download is passed, the dump is fetched from drun.dump.source. http(s):// sources use curl; anything else uses scp. The file is downloaded to a .part file first. site:install-dump only needs settings.php with DB credentials; the database can be empty.

Project commands

drun:
  commands:
    - App\Robo\ProjectCommands

The class must be autoloadable by the project's composer.json. Extend Robo\Tasks and use Syp\Drun\Robo\Traits\ExecTrait to get the exec prefix.

Git hooks

drun.git.hooks maps each hook name to a list of shell commands. Run git:hooks-install again after changing it. Hooks that drun did not write are left alone unless you pass --force.

Development

composer install
bin/run qa:lint && bin/run qa:phpcs && bin/run qa:phpstan   # paths from ./runner.yml
vendor/bin/phpunit

The command tests run each case in tests/fixtures/commands/*.yml. They use a sandbox project directory under the system temp directory, and most run with --simulate. tests/CommandsTestCase.php documents the fixture keys. Most new tests need only a new YAML case, no PHP.

GitLab CI (.gitlab-ci.yml) runs these checks on PHP 8.3, 8.4 and 8.5, with both the highest and the lowest allowed dependency versions.