Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Deployment Tasks Bundle Laravel Package

c0ntax/deployment-tasks-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle

    composer require c0ntax/deployment-tasks-bundle
    
  2. Configure Gaufrette Storage Add the required knp_gaufrette.yaml configuration (as per the README) to store task execution state. Ensure the var/memory directory exists:

    mkdir -p var/memory
    
  3. First Use Case: Run a One-Time Task Define a task in a service (e.g., src/Command/DeployTaskCommand.php):

    use c0ntax\DeploymentTasksBundle\Task\TaskInterface;
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    
    class DeployTaskCommand extends Command implements TaskInterface
    {
        public function isTask(): bool
        {
            return true; // Marks this as a task
        }
    
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            // Your one-time logic (e.g., database migrations, cache clearing)
            $output->writeln('Running one-time task...');
            return Command::SUCCESS;
        }
    }
    

    Register the command in services.yaml:

    services:
        App\Command\DeployTaskCommand:
            tags: ['console.command']
    

    Run the task via CLI:

    php bin/console app:deploy-task
    

    The task will execute only once (subsequent runs are skipped).


Implementation Patterns

Workflow Integration

  1. Deployment Hooks Use the bundle in CI/CD pipelines (e.g., GitHub Actions, GitLab CI) to run tasks once per deployment:

    # .github/workflows/deploy.yml
    jobs:
        deploy:
            steps:
                - run: php bin/console app:deploy-task
    
  2. Task Grouping Group related tasks (e.g., PreDeployTask, PostDeployTask) by prefixing command names or using tags:

    # config/services.yaml
    services:
        App\Command\PreDeployTask:
            tags: ['console.command', 'deploy.pre']
    
  3. Conditional Execution Extend TaskInterface to add logic for environment-specific tasks:

    public function isTask(): bool
    {
        return $this->getEnvironment() === 'production';
    }
    

Laravel-Specific Adaptations

  1. Artisan Command Wrapper Create a Laravel Artisan command to proxy Symfony commands:

    // app/Console/Commands/RunDeploymentTasks.php
    namespace App\Console\Commands;
    
    use Illuminate\Console\Command;
    use Symfony\Component\Process\Process;
    
    class RunDeploymentTasks extends Command
    {
        protected $signature = 'deploy:tasks';
        protected $description = 'Run one-time deployment tasks';
    
        public function handle()
        {
            $process = new Process(['php', 'bin/console', 'app:deploy-task']);
            $process->run();
            $this->output->writeln($process->getOutput());
        }
    }
    
  2. Service Provider Integration Register the bundle in config/app.php (Symfony bundles require manual registration in Laravel):

    'providers' => [
        // ...
        c0ntax\DeploymentTasksBundle\c0ntaxDeploymentTasksBundle::class,
    ],
    
  3. Task Storage Customization Override the default Gaufrette adapter in Laravel’s config:

    // config/filesystems.php
    'disks' => [
        'tasks' => [
            'driver' => 'local',
            'root' => storage_path('framework/tasks'),
        ],
    ],
    

Gotchas and Tips

Pitfalls

  1. Gaufrette Dependency

    • Issue: The bundle requires knp-gaufrette-bundle, which may conflict with Laravel’s filesystem abstractions.
    • Fix: Use Laravel’s Storage facade to mock the local adapter if needed:
      // src/Service/TaskStorageAdapter.php
      use League\Flysystem\Local\LocalFilesystemAdapter;
      use Symfony\Component\DependencyInjection\ContainerInterface;
      
      class TaskStorageAdapter
      {
          public function __construct(private ContainerInterface $container)
          {
          }
      
          public function getAdapter(): LocalFilesystemAdapter
          {
              return new LocalFilesystemAdapter(
                  $this->container->getParameter('kernel.project_dir') . '/storage/framework/tasks'
              );
          }
      }
      
  2. Task Idempotency

    • Issue: Tasks may run unintentionally if isTask() logic is flawed (e.g., always returns true).
    • Fix: Add debug output to verify task state:
      public function isTask(): bool
      {
          $this->logger->debug('Checking task execution status...');
          return $this->taskManager->wasExecuted($this->getTaskId());
      }
      
  3. Symfony vs. Laravel CLI

    • Issue: Laravel’s Artisan may not resolve Symfony commands by default.
    • Fix: Use the full command name with namespace:
      php bin/console c0ntax_deployment_tasks:run App\Command\DeployTaskCommand
      

Debugging Tips

  1. Check Task Execution State Inspect the var/memory directory for JSON files tracking executed tasks:

    cat var/memory/*.json
    
  2. Clear Task State (Dev Only) Delete the var/memory directory to reset all tasks:

    rm -rf var/memory/*
    
  3. Log Task Execution Enable Symfony’s debug mode to log task lifecycle:

    # config/packages/dev/debug.yaml
    framework:
        profiler: { only_exceptions: false }
    

Extension Points

  1. Custom Task Storage Implement a custom TaskStorageInterface to use Laravel’s cache or database:

    // src/Service/DatabaseTaskStorage.php
    use c0ntax\DeploymentTasksBundle\Task\TaskStorageInterface;
    
    class DatabaseTaskStorage implements TaskStorageInterface
    {
        public function wasExecuted(string $taskId): bool
        {
            return \DB::table('deployed_tasks')->where('task_id', $taskId)->exists();
        }
    
        public function markExecuted(string $taskId): void
        {
            \DB::table('deployed_tasks')->insert(['task_id' => $taskId]);
        }
    }
    
  2. Event-Driven Tasks Trigger tasks via Laravel events (e.g., Deployed event):

    // app/Providers/EventServiceProvider.php
    use c0ntax\DeploymentTasksBundle\Task\TaskManagerInterface;
    
    class EventServiceProvider extends ServiceProvider
    {
        public function boot(TaskManagerInterface $taskManager)
        {
            event('deployed', function () use ($taskManager) {
                $taskManager->run('App\Command\PostDeployTask');
            });
        }
    }
    
  3. Parallel Task Execution Use Symfony’s Process component to run tasks concurrently (advanced):

    // src/Command/ParallelDeployCommand.php
    use Symfony\Component\Process\Process;
    
    class ParallelDeployCommand extends Command
    {
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            $processes = [
                new Process(['php', 'bin/console', 'app:task1']),
                new Process(['php', 'bin/console', 'app:task2']),
            ];
    
            foreach ($processes as $process) {
                $process->start();
            }
    
            foreach ($processes as $process) {
                $process->wait();
                $output->writeln($process->getOutput());
            }
    
            return Command::SUCCESS;
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium