Skip to content

laravel-upgrade-major

Type Skill
Plugin awl-web · v0.0.6
Invoke /awl-web:laravel-upgrade-major
Tools Bash(composer:), Bash(php:)
Source plugins/awl-web/skills/laravel-upgrade-major/SKILL.md

Upgrades a Laravel application to the next major version following the official upgrade guide — bumps composer constraints, applies breaking changes, runs tests. Use when asked to “upgrade laravel”, “laravel 12”, “bump laravel major”, “migrate laravel version”, or when composer.json pins an outdated laravel/framework major. Not for minor/patch updates or Statamic (use statamic-upgrade-major).

Trigger phrases: upgrade laravel · laravel 12 · bump laravel major · migrate laravel version

Upgrades a Laravel application to the next major version following official upgrade guides.

  1. Read composer.json for Laravel version:

    Terminal window
    cat composer.json | grep -A1 '"laravel/framework"'
  2. Extract major version (e.g., ^10.0 → 10, ^11.48 → 11)

  3. Calculate target version: current + 1

    • Laravel 10 → 11
    • Laravel 11 → 12
    • NEVER skip versions

Step 2: Pre-Upgrade Gate (Tests Must Pass)

Section titled “Step 2: Pre-Upgrade Gate (Tests Must Pass)”

Tests must be green before proceeding. Run tests in quiet mode (exit code only, output omitted to save context):

Terminal window
php artisan test -q

Or if using PHPUnit directly:

Terminal window
./vendor/bin/phpunit -q

If tests fail: STOP. Report failures to user and do not proceed with upgrade.

  • Upgrading with failing tests makes it impossible to verify upgrade success
  • Ask user to fix tests first, then re-run /laravel-upgrade-major

If tests pass: Continue to Step 3.

Optionally run static analysis (informational, not blocking):

Terminal window
./vendor/bin/phpstan analyse -q

WebFetch the official upgrade documentation:

https://laravel.com/docs/{TARGET}.x/upgrade

Example for upgrading to Laravel 12:

https://laravel.com/docs/12.x/upgrade

IMPORTANT: Read the ENTIRE guide. Do not skim or assume changes don’t apply.

CRITICAL: Update ALL packages in composer.json FIRST, then run composer update ONCE.

Do NOT update packages one at a time. This causes dependency conflicts.

  1. Edit composer.json - Update ALL Laravel package versions in one edit
  2. Then run composer update - Only after all versions are set

Check which of these exist in composer.json and update them ALL at once:

  • laravel/framework^{TARGET}.0
  • laravel/tinker
  • laravel/sanctum
  • laravel/passport
  • laravel/horizon
  • laravel/telescope
  • laravel/cashier
  • laravel/scout
  • laravel/socialite
  • laravel/breeze
  • laravel/jetstream
  • laravel/fortify
  • laravel/pint
  • laravel/sail
  • laravel/dusk

Also check the upgrade guide for any additional packages that need version bumps.

CRITICAL: Check EVERY item in the upgrade guide against the project. No assumptions.

For EACH breaking change listed in the guide:

  1. Search the codebase for affected code (use Grep/Glob)
  2. Verify whether the project uses the affected feature
  3. Apply fix if affected, or confirm not affected if clean

Do NOT assume a breaking change doesn’t apply without searching the codebase first.

  • PHP Version - Update composer.json if required, ./update.sh if exists
  • Config Files - Compare with new defaults, update/publish as needed
  • Middleware - Search for middleware usage, apply changes
  • Service Providers - Check bootstrap/providers.php
  • Facades/Helpers - Search for deprecated methods
  • Database/Eloquent - Check for changed behavior
  • Routing - Verify route definitions still work
  • Validation - Check for rule changes

Use Edit tool for each change. Explain what’s changing and why.

Only run after ALL package versions are updated in composer.json.

Terminal window
composer update

Do NOT pre-check package compatibility. Just run composer update and let it report issues.

If conflicts occur:

  • Read the composer error output carefully
  • If Laravel package conflict: you likely missed updating it in Step 4 - go back and add it
  • If third-party blocker (CMS, etc.): STOP and report to user with exact error message
  • Do NOT search the web to check if the package supports Laravel {TARGET}
  • Do NOT try to force or work around the conflict

Clear all caches:

Terminal window
php artisan optimize:clear

Run tests (quiet mode, exit code only):

Terminal window
php artisan test -q

Run linting:

Terminal window
./vendor/bin/pint --test -q

Run static analysis:

Terminal window
./vendor/bin/phpstan analyse -q

Output summary:

## Laravel Upgrade Complete: {CURRENT} → {TARGET}
### Files Changed
- composer.json
- [list other changed files]
### Packages Updated
- laravel/framework: ^{CURRENT}.0 → ^{TARGET}.0
- [other packages]
### Blockers Encountered
- [package]: [reason]
### Test Results
- Passed: X
- Failed: X
- [failure details if any]
### Manual Steps Remaining
- [if any]
  • NEVER skip major versions - Always current + 1
  • NEVER force-update CMS packages - Report as blockers
  • NEVER assume a breaking change doesn’t apply - Search the codebase first
  • ALWAYS check EVERY item in the upgrade guide against the project
  • ALWAYS run tests before and after
  • ALWAYS explain changes - User should understand what changed
  • Backup first - Ensure git status is clean before starting
  • NO WEB SEARCHES for package compatibility - Do NOT search the web to check if third-party packages (Statamic, Filament, etc.) support the target Laravel version. Let composer determine compatibility:
    • Run composer update and let it fail if incompatible
    • Read error output to identify blocking packages
    • Report blockers to user with the exact composer error

User: /laravel-upgrade-major

  1. Read composer.json → Laravel 11.48
  2. Target: Laravel 12
  3. WebFetch laravel.com/docs/12.x/upgrade
  4. Update composer.json dependencies
  5. Apply breaking changes from guide
  6. Run composer update
  7. Clear caches, run tests
  8. Report results