Skip to content

Stages Composer commands so they can be safely run on a codebase in production.

License

Notifications You must be signed in to change notification settings

alexpott/composer-stager

 
 

Repository files navigation

Composer Stager

Latest stable version Tests status Coverage PHPStan Psalm PHPMD

Composer Stager makes long-running Composer commands safe to run on a codebase in production by "staging" them--performing them on a non-live copy of the codebase and syncing back the result for the least possible downtime.

Installation

The library is installed via Composer:

composer require php-tuf/composer-stager

Usage

It is invoked via its PHP API. Given a configured service container (see below), its services can be used like the following, for example:

class Updater
{
    public function __construct(
        BeginnerInterface $beginner,
        StagerInterface $stager,
        CommitterInterface $committer,
        CleanerInterface $cleaner
    )
    {
        $this->beginner = $beginner;
        $this->stager = $stager;
        $this->committer = $committer;
        $this->cleaner = $cleaner;
    }

    public function update(): void
    {
        $activeDir = PathFactory::create('/var/www/public');
        $stagingDir = PathFactory::create('/var/www/staging');
        $exclusions = new PathList([
            'cache',
            'uploads',
        ]);

        // Copy the codebase to the staging directory.
        $this->beginner->begin($activeDir, $stagingDir, $exclusions);

        // Run a Composer command on it.
        $this->stager->stage([
            'require',
            'example/package',
            '--update-with-all-dependencies',
        ], $stagingDir);

        // Sync the changes back to the active directory.
        $this->committer->commit($stagingDir, $activeDir, $exclusions);

        // Remove the staging directory.
        $this->cleaner->clean($stagingDir);
    }
}

Configuring services

Composer Stager uses the dependency injection pattern, and its services are best accessed via a container that supports autowiring, e.g., Symfony's. A basic implementation could look something like this:

---
services:

    _defaults:
        autoconfigure: true
        autowire: true
        public: false

    PhpTuf\ComposerStager\:
        resource: '../vendor/php-tuf/composer-stager/src/*'
        public: true
        exclude:
            - '../vendor/php-tuf/composer-stager/src/Domain/Exception'
            - '../vendor/php-tuf/composer-stager/src/Infrastructure/Value'

    PhpTuf\ComposerStager\Infrastructure\Factory\FileSyncer\FileSyncerFactory:
        arguments:
            $phpFileSyncer: '@PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\PhpFileSyncer'
            $rsyncFileSyncer: '@PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\RsyncFileSyncer'
    PhpTuf\ComposerStager\Domain\Service\FileSyncer\FileSyncerInterface:
        factory: [ '@PhpTuf\ComposerStager\Infrastructure\Factory\FileSyncer\FileSyncerFactory', 'create' ]

    Symfony\Component\Filesystem\Filesystem: ~
    Symfony\Component\Process\ExecutableFinder: ~

Example

A complete, functioning example implementation of Composer Stager can be found in the Composer Stager Console repository.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Observe the coding standards, and if you're able, add and update tests as appropriate.


More info in the Wiki.

About

Stages Composer commands so they can be safely run on a codebase in production.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%