syp / drun
Robo-based task runner for Drupal 11 projects: site install/update, QA and git hooks.
Requires
- php: >=8.3
- consolidation/robo: ^5.1
- drupal/coder: ^8.3.28
- drush/drush: ^13.6
- mglaman/phpstan-drupal: ^2.0
- php-parallel-lint/php-parallel-lint: ^1.4
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.1.22
- phpstan/phpstan-deprecation-rules: ^2.0
Requires (Dev)
- phpunit/phpunit: ^12.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
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
| Command | Does |
|---|---|
site:install-clean | drush 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:update | Run drun.deploy.steps (default: drush deploy) |
qa:lint / qa:phpcs / qa:phpstan | Run the tool on existing drun.qa.paths |
qa:audit | composer audit --locked |
qa:all | Run 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.stepsoverride 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'.-Tis required for dump imports.drun:init --dockerwrites it to a newrunner.yml. Set it inrunner.ymlfor the whole team or inrunner.local.ymlfor 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:
| File | Owner | Holds |
|---|---|---|
settings.php | project | Created from default.settings.php if missing. drun appends one block: a fallback hash_salt, then the includes below. |
settings.drun.php | drun | DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_PREFIX, DB_DRIVER, HASH_SALT. Replaced by drun:init --force. |
settings.project.php | project | The project's own variables, e.g. $config['smtp.settings']['smtp_host'] = getenv('SMTP_HOST');. Never overwritten. |
settings.local.php | machine | Optional, 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.