Weave 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

In Situ Updater Bundle Laravel Package

yucca/in-situ-updater-bundle

A Symfony bundle for performing in-situ updates, letting you apply changes directly in place without rebuilding or redeploying. Designed to integrate smoothly into existing Symfony applications and streamline update workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate expectations: yucca/in-situ-updater-bundle is a Symfony bundle, not a Laravel package. The Bundle suffix, the Yucca\ vendor prefix, and the maintainer (rjanot) all point to the Symfony ecosystem. It has 0 stars and 0 dependents, so treat the source code — not the README, not this assessment — as the specification. Read composer.json first: if it requires symfony/framework-bundle or symfony/http-kernel, you cannot composer require it into a Laravel app and expect a service provider to appear.

What it does (pattern-level): an "in-situ updater" runs dependency updates from inside the running application instead of over SSH. Typically that means: a controller renders the currently installed versions, lets you trigger a composer update (often scoped to specific packages), streams the output back, and sometimes snapshots files so you can roll back. Think "Composer's composer outdated + a button," not "Laravel Shift."

Where to look first (in the repo, in this order):

  1. composer.json — Symfony version constraints and the type: symfony-bundle declaration. This decides whether Laravel interop is even theoretical.
  2. DependencyInjection/*Extension.php and Resources/config/*.yaml — the services it registers and, critically, the routes it may or may not ship. If routes are auto-loaded, that is an attack surface you must find before installing.
  3. Controller/ or Action/ — the entry points. This is where the auth story lives (or doesn't).
  4. Command/ — the console commands. Most "web updater" bundles also expose a CLI equivalent, which is the only part you can reuse unchanged in Laravel via Artisan::call-style wiring or a standalone Symfony\Component\Console invocation.

Your first real use case: a staging or internal-tooling environment where a non-developer (PM, support lead) needs to pull the latest patch release without a deploy pipeline. Not production. Not production ever.

Laravel alternative you should seriously consider first: symfony/process + a queued job + a gated Filament/Nova page is roughly 150 lines and gets you 80% of this bundle's value with zero third-party trust. You already have Process, Schedule, Gate, and Horizon. The bundle's differentiators would be prebuilt UI and rollback — verify those actually exist before adopting.

Implementation Patterns

Pattern 1 — Symfony host, Laravel not involved. If you are running Symfony (or a Laravel app that already embeds a Symfony kernel for a legacy module), register the bundle in config/bundles.php, then check config/routes/ for whether the bundle ships routes or expects you to import them:

// config/routes/updater.php — only if the bundle ships a routing file
$updater = $loader->import('@YuccaInSituUpdaterBundle/Resources/config/routing.xml');
$updater->setPrefix('/_tools/updater');

Never rely on the bundle's default prefix. Put it behind an explicit prefix, an explicit firewall, and an IP allowlist. An update endpoint is RCE-adjacent by construction.

Pattern 2 — reimplement the behavior in Laravel. This is the realistic path and it is not hard:

// app/Jobs/RunComposerUpdate.php
public function handle(): void
{
    $process = new Process(
        ['composer', 'update', '--no-interaction', '--prefer-dist', ...$this->packages],
        base_path(),
        ['COMPOSER_HOME' => storage_path('composer'), 'HOME' => storage_path('app')],
        null,
        600
    );
    $process->run(fn ($type, $buf) => Cache::put("composer:{$this->id}", $buf, 3600));
}

Gate it with a policy (Gate::authorize('run-updates')), require a fresh password confirmation (password.confirm middleware), and log who ran it and against which commit.

Pattern 3 — diff-before-apply. The genuinely useful half of an in-situ updater is showing what changed before running anything. Wire composer outdated --format=json into a read-only screen, let a human tick packages, and only then dispatch the update job. This turns an all-or-nothing composer update into a reviewed operation.

Pattern 4 — snapshot for rollback. Do not trust the bundle's rollback, and do not run an updater without one. Before any apply step: git stash-free approach — commit or tag the tree, or copy composer.json/composer.lock/vendor/ into storage/backups/{timestamp}/. Rollback is then restoring the lock file and re-running composer install, which is deterministic. File-copy "rollback" of vendor/ is a trap on case-insensitive filesystems and long paths.

Pattern 5 — CLI-first, UI-second. Expose the same operation as php artisan app:update-dependencies and have the web UI merely dispatch a queued call to it. You keep auditability, you keep it testable ($this->artisan(...)), and you can run it from CI if the UI breaks.

Integration tips. If you must touch the Symfony bundle from Laravel, you can borrow pieces without the kernel: the classes under Command/ and any Process-wrapping services are usually plain PHP. Autoload them via a path repository or a classmap entry rather than installing the bundle. Skip anything referencing ContainerInterface, Request, or KernelInterface — those won't bind.

Gotchas and Tips

Framework mismatch is the headline. A Symfony bundle's Extension class, CompilerPasses, service tags, and configuration tree have no meaning to Laravel's container. There is no ServiceProvider, no config/ to publish, no facade. Any tutorial you find will assume bin/console. Budget a day for a bridging layer before you budget an hour — or, better, don't.

Running Composer as the web user is a permission minefield. PHP-FPM's user likely owns nothing in the project root, and has no HOME. Set COMPOSER_HOME and HOME explicitly to writable paths, and expect composer to fail silently with exit 0 in some wrappers if you don't check $process->getExitCode(). Always assert on exit code, never on output emptiness.

Request timeouts will bite you before anything else. A composer update on a cold cache takes minutes. Nginx fastcgi_read_timeout defaults to 60s; PHP max_execution_time is often 30s under FPM. If the bundle streams output via SSE or chunked responses, verify your proxy doesn't buffer it (proxy_buffering off, X-Accel-Buffering: no). Push the work into a queue regardless.

Opcache and realpath cache. After files in vendor/ change, the old code is still cached. You need opcache_reset() and clearstatcache(true) — and on FPM you need to signal workers unless opcache.validate_timestamps is on. The bundle almost certainly does not do this for you. Without it you will "update" and see no change, then conclude the update failed.

Locking and concurrency. Two clicks = two concurrent composer processes corrupting vendor/. Use an atomic lock (Cache::lock('composer-update', 900) in Laravel, or a PID/lock file if using the bundle directly) and make the second caller get a clear "already running" response rather than a stack trace.

Zero stars means zero security review. An endpoint that executes composer with parameters derived from a request is a remote code execution primitive if the parameter handling is sloppy. Before installing anything: grep for shell_exec, exec, passthru, system, and check whether package names are escaped (Process with an array avoids shell interpolation — a string command line does not). Also grep for csrf, is_granted, ROLE_, and any security.yaml fixture. If authorization is "the route is secret," you have your answer.

Version-drift hazard. composer update inside a running app can pull a package whose new version requires a PHP or framework version you don't have. You'll get a broken app and a half-written vendor/. Pin to composer update --with-dependencies --minimal-changes or --dry-run first, and only ever run it against a lock file you've committed.

Extension points worth checking (names are guesses — verify): an event dispatched after update, an interface for the "runner" service, and a config key for the composer binary path. If the composer binary path isn't configurable, it's hardcoded to composer and will fail on any host where it lives in ~/.composer/vendor/bin or vendor/bin.

Debugging. Log the full Process command line, exit code, getErrorOutput(), and environment. The single most common failure is "worked in my shell, fails in the app" — almost always HOME/COMPOSER_HOME, a missing git binary (Composer shells out to git for some sources), or PATH differing between your shell and FPM's.

Verdict. For a Laravel codebase in 2024+, adopt the pattern (gated, queued, locked, snapshot-first dependency updates) and skip the package. You get auditable, testable, framework-native code and you avoid handing an unvetted zero-star bundle the keys to vendor/. Revisit the bundle only if it turns out to ship a genuinely non-trivial rollback implementation you'd rather not rebuild — and even then, vendor it into your own namespace.

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.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk