Installation:
composer require atoolo/deployment-bundle
Add the bundle to config/bundles.php:
return [
// ...
Atoolo\DeploymentBundle\AtooloDeploymentBundle::class => ['all' => true],
];
First Use Case:
Trigger a deployment event by creating a symlink in your project's root (e.g., current pointing to the new release directory). The bundle will automatically detect the change and execute registered listeners.
Configuration:
Define listeners in config/packages/atoolo_deployment.yaml:
atoolo_deployment:
listeners:
- App\EventListener\CacheClearListener
- App\EventListener\DatabaseMigrateListener
Deploy/Undeploy Events:
Extend Atoolo\DeploymentBundle\Event\DeploymentEvent and implement DeploymentListenerInterface:
use Atoolo\DeploymentBundle\Event\DeploymentEvent;
use Atoolo\DeploymentBundle\Event\DeploymentListenerInterface;
class CacheClearListener implements DeploymentListenerInterface
{
public function onDeploy(DeploymentEvent $event): void
{
if ($event->isDeploy()) {
$this->clearCache();
}
}
public function onUndeploy(DeploymentEvent $event): void
{
// Handle rollback logic
}
}
Symlink-Based Triggers:
The bundle detects symlink changes (e.g., current symlink updates) via SCRIPT_FILENAME. Use this for zero-downtime deployments:
ln -sf /path/to/new/release current
Messenger Integration: Dispatch async tasks via Symfony Messenger:
use Symfony\Component\Messenger\MessageBusInterface;
class AsyncDeployListener implements DeploymentListenerInterface
{
public function __construct(private MessageBusInterface $bus) {}
public function onDeploy(DeploymentEvent $event): void
{
$this->bus->dispatch(new WarmupCacheMessage());
}
}
Environment Awareness: Skip listeners in non-production environments:
public function onDeploy(DeploymentEvent $event): void
{
if ($event->getEnvironment() !== 'prod') {
return;
}
// Production-only logic
}
Symlink Detection:
SCRIPT_FILENAME to detect symlink changes. Ensure your web server (e.g., Nginx/Apache) passes the correct path.fastcgi_param SCRIPT_FILENAME $document_root/current$fastcgi_script_name; in Nginx.Race Conditions:
mv current current.bak && ln -sf new-release current
Listener Order:
services:
App\EventListener\CriticalListener:
tags: [atoolo_deployment.listener, { priority: 100 }]
Enable Verbose Logging:
Add to config/packages/monolog.yaml:
handlers:
deployment:
type: stream
path: "%kernel.logs_dir%/deployment.log"
level: debug
Check Hash File:
The bundle reads a .atoolo-deployment-hash file to detect changes. If missing, create it manually:
echo "initial" > .atoolo-deployment-hash
Test Locally: Simulate deployments with:
touch .atoolo-deployment-hash && echo "new-hash" > .atoolo-deployment-hash
Custom Triggers:
Extend Atoolo\DeploymentBundle\Detector\DeploymentDetectorInterface to support non-symlink triggers (e.g., Git hooks).
Post-Deploy Commands: Chain listeners with Symfony commands:
use Symfony\Component\Console\Command\Command;
class PostDeployCommand extends Command
{
protected static $defaultName = 'atoolo:post-deploy';
public function __construct(private DeploymentListenerInterface $listener) {}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->listener->onDeploy(new DeploymentEvent(true, 'prod'));
return Command::SUCCESS;
}
}
Rollback Support:
Implement onUndeploy to reverse changes:
public function onUndeploy(DeploymentEvent $event): void
{
$this->restoreBackup();
}
How can I help you explore Laravel packages today?