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

Version Checker Laravel Package

roadrunner-php/version-checker

Checks the installed RoadRunner version against required constraints. Provides greaterThan, lessThan, and equal methods, throwing UnsupportedVersionException or RoadrunnerNotInstalledException on mismatch. Requires PHP 8.0+.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation (package renamed in v1.4.0; v1.4.1 is a patch):

    composer require roadrunner/version-checker
    

    The package was renamed from roadrunner-php/version-checker to roadrunner/version-checker in v1.4.0. If you're adding it for local-only checks:

    "require-dev": {
        "roadrunner/version-checker": "^1.4"
    }
    

    If you already have the old package installed, run composer remove roadrunner-php/version-checker before requiring the new name — otherwise you can end up with two copies of the same classes in the autoloader.

    Upgrading 1.4.0 → 1.4.1 is a straight composer update roadrunner/version-checker; it's a bug fix, not an API change.

  2. Where to look first:

    • composer.json → confirm the vendor is now roadrunner/ and the constraint is ^1.4 (1.4.1 needs no constraint change).
    • composer.lock / composer show roadrunner/roadrunner (new in v1.4.1) — the installed version is now detected from the roadrunner/roadrunner package. Confirm it's actually in your dependency tree before trusting getInstalledVersion().
    • The README (v1.4.0 rewrote the header, badges and examples) — it remains the current reference for the public API surface. Note the GitHub repo still lives at roadrunner-php/version-checker even though the Packagist name is roadrunner/version-checker; don't let that mismatch convince you the rename didn't happen.
    • vendor/roadrunner/version-checker/src to confirm the namespace is still RoadRunner\VersionChecker (the vendor rename does not automatically imply a namespace change, but verify before doing a mass find-and-replace).
  3. Basic Usage:

    use RoadRunner\VersionChecker\VersionChecker;
    
    $checker = new VersionChecker();
    $latestVersion    = $checker->getLatestVersion();    // e.g. "v1.0.0"
    $installedVersion = $checker->getInstalledVersion(); // resolved from roadrunner/roadrunner (v1.4.1)
    $isLatest         = $checker->isLatest();
    
  4. First Use Case:

    • Local development guard — warn before you spend an hour debugging a mismatch between your RoadRunner binary and the worker SDK:
      if (!$checker->isLatest()) {
          echo "⚠️ Outdated RoadRunner version. Latest: {$checker->getLatestVersion()}";
      }
      
    • CI gate — fail the pipeline early rather than at deploy time.

Implementation Patterns

Workflow Integration

  1. Warn from a service provider (non-blocking, log-only):

    public function boot()
    {
        $checker = new VersionChecker();
    
        if (!$checker->isLatest()) {
            Log::warning('RoadRunner version outdated', [
                'installed' => $checker->getInstalledVersion(),
                'latest'    => $checker->getLatestVersion(),
            ]);
        }
    }
    

    Keep this out of the hot path — see the caching tip below. Log both versions: as of v1.4.1 the installed side is derived from roadrunner/roadrunner, and a null/empty installed version is itself a useful signal (see Gotchas).

  2. Artisan command as the team-facing entry point — far more discoverable than a boot-time log line:

    php artisan rr:check-version
    
    protected function handle()
    {
        $checker = new VersionChecker();
        $latest  = $checker->getLatestVersion();
    
        $this->info("Latest RoadRunner version: {$latest}");
        $this->line('Installed: ' . ($checker->getInstalledVersion() ?: 'unknown'));
    
        return $checker->isLatest()
            ? $this->info('Up to date.')
            : $this->warn('Update recommended!');
    }
    
  3. Scheduled check with notification:

    $schedule->call(function () {
        $checker = new VersionChecker();
    
        if (! $checker->isLatest()) {
            Notification::route('slack', config('services.slack.webhook'))
                ->notify(new RoadRunnerOutdated(
                    $checker->getInstalledVersion(),
                    $checker->getLatestVersion()
                ));
        }
    })->daily()->environments(['staging', 'production']);
    
  4. Custom comparison logic — if you only care about minor/major drift:

    // Illustrative: check the exact method name against the v1.4 README,
    // since the API is not contractually stable across 1.x.
    $checker->setVersionComparator(
        fn ($installed, $latest) => version_compare($installed, $latest, '>=')
    );
    
  5. Explicit installed version for non-Composer runtimes — if your worker image gets RoadRunner from a tarball/curl installer rather than from Composer, roadrunner/roadrunner won't be present and detection will come up empty. Feed the version you already know from your image build:

    $checker = new VersionChecker();
    // e.g. from an env var baked into the image at build time
    $checker->setInstalledVersion(env('RR_VERSION', 'v2025.1.0'));
    

Integration Tips

  • Cross-verify with the binary: rr get-version gives you the runtime version; since v1.4.1 the checker reads the installed version from the roadrunner/roadrunner Composer package. Comparing all three catches the case where your lockfile, your go/container image, and your vendor/ have drifted apart.
  • Cache the remote lookup — the check hits a remote API on every call, so wrap it once and share it:
    $latest = Cache::remember('rr_latest_version', now()->addHours(6), fn () =>
        (new VersionChecker())->getLatestVersion()
    );
    
    Only cache the remote half; the installed version comes from local Composer metadata and is cheap (and can change on deploy).
  • Pin the constraint, not the check: use ^1.4 in composer.json and let the package resolve; 1.3 → 1.4 was a rename, not an API break, and 1.4.1 is a bug fix — a caret constraint carries you across both. Review the changelog on each minor, since 1.x is still moving.
  • Keep the dependency in the right section: if it only runs locally or in CI, require-dev keeps it out of your production image.

Gotchas and Tips

Pitfalls

  1. Package rename (v1.4.0) — still the main migration risk:

    • roadrunner-php/version-checker → roadrunner/version-checker.
    • Update composer.json, any composer require lines in Dockerfiles/CI, and any docs or scripts that reference the old name.
    • Composer resolves by name, so an old constraint like "roadrunner-php/version-checker": "^1.0" will simply stop receiving v1.4+ updates — it won't error, which makes this a silent staleness bug.
    • If your code imports RoadRunner\VersionChecker\*, verify the namespace after upgrading with a quick grep -r "namespace" vendor/roadrunner/version-checker/src.
    • The GitHub repository URL is still roadrunner-php/version-checker (that's where the v1.4.1 changelog lives). Old-looking URLs are not evidence you're on the old package — check composer show.
  2. Installed-version detection now depends on roadrunner/roadrunner (v1.4.1):

    • Before 1.4.1 the installed version was detected incorrectly; after upgrading, re-run your check command and make sure getInstalledVersion() returns a real value rather than empty/null.
    • If you run RoadRunner from a standalone binary or a prepackaged Docker image without the Composer package, detection has nothing to read. Either add roadrunner/roadrunner to require/require-dev, or set the version explicitly (see Implementation Patterns #5).
    • If you were compensating for the 1.4.0 behaviour with your own version parsing, delete that workaround — otherwise you'll now have two sources of truth disagreeing.
  3. Network dependency: getLatestVersion() reaches out to a remote API. Always guard it:

    try {
        $latest = $checker->getLatestVersion();
    } catch (\Throwable $e) {
        Log::notice('RoadRunner version check skipped: ' . $e->getMessage());
    }
    

    Never let a version check fail a deploy. Treat it as advisory.

  4. Version format assumptions: the comparison presumes semver-ish tags (v1.2.3). Pre-release tags (-rc1, -dev), RoadRunner's v2025.x calendar-style tags, and custom schemes can produce surprising results — sanity-check with a fixture rather than trusting it blind.

  5. No built-in caching: repeated calls hit the network each time. One scheduled job and one command per machine is fine; putting it in boot() on every request is not.

  6. Documentation drift from the v1.4.0 refresh: the README examples were rewritten, so snippets copied from blog posts or older issues may reference methods that no longer exist — and 1.4.1's detection change means even recent 1.4.0-era snippets about reading the installed version may be stale. Trust the repo's README and changelog over anything else.

Debugging

  • Silent failures: a failed HTTP call can surface as an empty or "latest" result rather than an exception. Log the raw return values of both getInstalledVersion() and getLatestVersion() the first time you wire this up, not just the boolean.
  • Check the data source directly: composer show roadrunner/roadrunner in the same environment (same container, same vendor/) tells you whether detection can work at all. If that command fails, the checker cannot know your installed version.
  • Test doubles: in your own test suite, bind a fake so CI never touches the network:
    $this->app->instance(VersionChecker::class, new FakeVersionChecker('v1.4.1'));
    
    Constructor-inject VersionChecker rather than new-ing it inside a command for exactly this reason.
  • Verify the check works at all: temporarily hardcode an old version string and confirm the "outdated" branch fires before you trust it in a scheduled job. Do this again after the 1.4.1 bump — the branch you're exercising has changed underneath you.

Extension Points

  1. Custom version source — useful for air-gapped or mirrored environments:

    $checker->setVersionSource('https://internal.example.com/rr/latest.json');
    

    (Confirm the setter name against the v1.4 README; the API has shifted across 1.x.)

  2. Events over log lines — decouples detection from notification:

    if (! $checker->isLatest()) {
        event(new RoadRunnerOutdated(
            $checker->getInstalledVersion(),
            $checker->getLatestVersion()
        ));
    }
    

    Then a listener decides whether that's a Slack ping, a Jira ticket, or nothing at all.

  3. Wrap, don't fork: put a thin RoadRunnerVersionService around the checker and inject that into your commands and listeners. When the package renames or reshuffles its API again (the vendor rename in 1.4.0 and the detection change in 1.4.1 are two examples in as many patches), you fix one class instead of every call site.

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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
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