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

Laravel Selfupdater Laravel Package

codedge/laravel-selfupdater

codedge/laravel-selfupdater adds self-update capabilities to Laravel apps, letting them check for, download, and install new releases from sources like GitHub—ideal for keeping applications current without manual file replacement.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you install: the package is archived. Pin the last release (2025-04-12) in composer.json, or fork it into your own VCS. Treat any future Laravel/PHP compatibility work as your responsibility.

composer require codedge/laravel-selfupdater
php artisan vendor:publish --provider="Codedge\Updater\UpdaterServiceProvider"

Published config lives at config/self-updater.php. Look there first — it is the map of the whole package. Then read Codedge\Updater\UpdaterManager, the source classes under src/Sources/ (Github, Http), and the Artisan commands (self-update, self-update:check). Those four places explain 90% of behavior.

Minimum .env for a public GitHub repo:

SELF_UPDATER_SOURCE=github
SELF_UPDATER_REPOSITORY_VENDOR=your-org
SELF_UPDATER_REPOSITORY_NAME=your-app
SELF_UPDATER_VERSION_INSTALLED=1.4.0

First use case: tag a release in GitHub, attach (or rely on) the source archive, then run php artisan self-update:check to confirm version detection and php artisan self-update to exercise the copy. Do this on a throwaway VM or container, never on production as your first run.

The package's job is narrow: fetch a release archive, extract it, and copy files over the current install. It is not a deployer. Everything else — backups, migrations, cache clears, queue restarts, opcache — is yours.

Implementation Patterns

Release-artifact pipeline (the pattern that actually works). Build a zip in CI that is a complete, runnable app: composer install --no-dev --optimize-autoloader, compiled frontend assets, and no .env, no storage/, no vendor/ you don't intend to ship. Publish it as a GitHub release asset, or serve it from your own endpoint for the http source. Tag semver; the package compares against version_installed.

Gate the command behind an environment check. Never expose self-update on a host where a random operator can trigger it. Wrap it:

// app/Console/Commands/AppUpdate.php
if (! app()->isProduction() || ! $this->confirm('Apply update?')) {
    return self::FAILURE;
}
Artisan::call('down');
$this->call('self-update');
$this->call('migrate', ['--force' => true]);
$this->call('optimize:clear');
$this->call('queue:restart');
Artisan::call('up');

Programmatic checks in a dashboard or health endpoint. Use the facade rather than shelling out:

use Codedge\Updater\Facades\Updater;

$available = Updater::source('github')->isNewVersionAvailable();
$latest    = Updater::source('github')->getVersionAvailable();

This is the nicest part of the package: isNewVersionAvailable() is cheap and easy to surface in an admin panel, a scheduled Slack digest, or a /health route.

Scheduled notification, manual application. The pragmatic split most teams land on: run self-update:check on a schedule, alert when a release exists, and keep self-update human-triggered. Fully automatic self-modifying deploys are hard to reason about when they fail at 3am.

Private repos. For GitHub private repositories, set private_access_token (a PAT with repo read scope). For an arbitrary HTTP host, switch default to http, set repository_url, and use use_basic_auth / basic_auth_username / basic_auth_password if the endpoint is protected. Keep the token in .env and out of the artifact you ship — otherwise every update carries the credential that authorizes the next update.

Hook the events. The package emits update lifecycle events (see Codedge\Updater\Events). Register a listener for success/failure and push to Slack or your log aggregator. This is the clean extension point for post-update steps you don't want buried in a custom command.

Exclusions are your safety net. exclude_folders and exclude_files decide what a release zip is allowed to overwrite. At minimum exclude .env, storage, and anything instance-specific (uploaded files, local SQLite, generated keys). Whitelist thinking beats blacklist thinking here.

Gotchas and Tips

Archived means frozen. No fixes for new PHP versions, no Laravel 12/13 compatibility patches, no security response. Budget for a fork. If your update needs are modest, Deployer, Envoy, Laravel Cloud, or a plain git pull + composer install release script is a better long-term bet than a self-modifying app directory.

It writes into the live application directory. There is no atomic swap and no rollback. A failed copy mid-way leaves you with a half-updated app. Mitigations: snapshot the instance before running, keep the previous artifact on disk, and be ready to re-extract it. Symlink-based release directories (the Deployer/Envoyer pattern) do not compose with this package — it overwrites in place.

Filesystem permissions are the #1 failure. The PHP user (often www-data) must be able to write to the app root, which is exactly the permission you normally do not grant. Running the command as the deploy user via SSH is safer than triggering it through a web route.

.env and config:cache. If .env is not excluded, an update silently replaces your production secrets with whatever shipped in the zip. Separately, if config is cached, SELF_UPDATER_VERSION_INSTALLED and related values are frozen until you re-run config:cache — after which version_installed must reflect the new version or you'll re-download the same release forever.

Version bookkeeping is manual. version_installed does not update itself. Have your build step stamp the new version into .env or a version file as part of the release, or accept that you'll be editing config on every deploy.

No migrations, no cache clears, no queue restarts. Assume the package does only file copying unless you've verified otherwise in the source. Wrap it (see the pattern above) or you'll ship schema changes that never run.

OPcache and PHP-FPM. New files on disk don't mean new code in memory. Reload PHP-FPM or call opcache_reset() after the copy, or you'll spend an hour debugging "the fix isn't there." Same for long-running queue workers.

Zip structure matters. GitHub's auto-generated source archive has a wrapping top-level directory; a hand-rolled asset may not. If files land in the wrong place, inspect what was extracted under download_path before assuming a config bug — that directory is also your best debugging surface.

Rate limits and token scope. Unauthenticated GitHub API calls are rate-limited per IP; a token fixes it and is required for private repos. If self-update:check starts returning stale or empty versions, check rate-limit responses before touching config.

log_events is on by default — use it. Bump log verbosity during rollout, watch the update events in storage/logs, and only then quiet it down. Debugging a silent half-update without those logs is miserable.

Test the failure path, not just the happy path. Deliberately corrupt the archive URL, remove write permission, and interrupt a copy on a staging box. The package gives you success/failure signals; make sure something actually listens to them.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource