terminal42/contao-build-tools
Experimental, highly opinionated build tools for Contao bundles/websites. Auto-configures code quality and style tooling (ECS/CS-Fixer, Rector, PHPStan, Stylelint) via Composer scripts, with CI workflow support. Not for production use.
Skip Installation (unless working on a Contao project):
app/ vs. src/) and namespace conventions (App\ vs. Contao\).For Contao Projects (Non-Laravel):
composer require --dev terminal42/contao-build-tools
composer run cs-fixer
composer run phpstan
.github/workflows/ci.yml (customize for Contao-specific paths).First Use Case:
phpstan/laravel, laravel-pint).Code Quality Workflow:
cs-fixer and phpstan via tools like Husky or Git hooks.
composer run cs-fixer --dry-run # Check without fixing
composer run phpstan --level=5 # Strict analysis
jobs:
phpstan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-php@v3
with:
php-version: '8.2'
- run: composer install
- run: composer run phpstan
Rector for Upgrades:
Contao\Backend to new APIs):
composer run rector --dry-run # Preview changes
composer run rector # Apply upgrades
rector.php to target Contao bundles:
return static::configure()
->withPaths([__DIR__.'/src'])
->withRule(ContaoUpgrade::class);
Deployer Integration:
deploy.php for Contao deployments (e.g., syncing assets/ and system/):
(new Deployer('example.com', 'user', '/usr/bin/php'))
->addTarget('prod', '/var/www/contao', 'https://example.com')
->includeSystemModules()
->addUploadPaths([
'assets/',
'files/',
])
->run();
Customization:
ecs.php
return static::setPath(__DIR__.'/vendor/drupal/coder/coder_sniffer/Contao')
->setRules([
'@Contao' => true,
'array_syntax' => ['syntax' => 'short'],
]);
phpstan.neon
includes:
- vendor/terminal42/contao-build-tools/phpstan.neon
level: max
src/ assumption conflicts with Laravel’s app/. Instead:
composer require --dev phpstan/phpstan laravel-pint
# phpstan.neon
includes:
- vendor/phpstan/extension-installer/phpstan.neon
- vendor/phpstan/phpstan-laravel/phpstan.neon
laravel-pint:
composer require --dev laravel/pint
vendor/bin/pint --test
Directory Structure Conflicts:
src/ directory not found (Laravel uses app/).
composer require --dev friendsofphp/php-cs-fixer
Then configure .php-cs-fixer.dist.php manually.Namespace Collisions:
App\ namespace as invalid (expects Contao\).
phpstan.neon:
excludeFiles:
- app/Providers/*
- app/Http/*
Deployer Irrelevance:
system/modules/).
// deploy.php (Laravel-specific)
task('deploy', [
'shared' => ['app/storage'],
'writable' => ['app/storage', 'bootstrap/cache'],
]);
Rector Misconfigurations:
Route::resource()).
// rector.php (Laravel-only)
return static::configure()
->withPaths([__DIR__.'/app'])
->withRule(\Rector\Set\LaravelSetList::PHP_80);
GitHub Action Overrides:
src/).
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-php@v3
with:
php-version: '8.2'
- run: composer install
- run: composer test
- run: vendor/bin/pint --test
PHPStan Errors:
--debug to identify misconfigured rules:
composer run phpstan --debug
phpstan.neon to ignore Contao-specific false positives:
arguments:
paths:
- src/
- vendor/terminal42/contao-build-tools
CS Fixer Conflicts:
vendor/terminal42/contao-build-tools/ecs.php) with your ecs.php:
diff vendor/terminal42/contao-build-tools/ecs.php ecs.php
laravel-pint instead:
composer require --dev laravel/pint
vendor/bin/pint --preset=laravel
Deployer Issues:
--verbose output:
php deploy.php deploy --verbose
artisan deploy or Envoyer.Custom PHPStan Rules:
phpstan.neon:
includes:
- vendor/terminal42/contao-build-tools/phpstan.neon
services:
Contao\PageModel:
methods:
findById:
returnType: Contao\PageModel|null
Rector Custom Rules:
// src/Rector/ContaoUpgradeRector.php
final class ContaoUpgradeRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Fixes Contao legacy code.', []);
}
public function refactor(ContaoLegacyNode $node): ?Node
{
// Custom logic
}
}
rector.php:
->withRule(ContaoUpgradeRector::class)
Stylelint Extensions:
.stylelintrc:
{
"extends": "stylelint-config-standard",
"rules": {
"selector-class-pattern": ["^([a-z][a-z0-
How can I help you explore Laravel packages today?