ezappslab/laravel-evolver
Laravel Evolver by ezappslab gives Laravel teams a structured, version-aware way to manage evolutionary application and database changes, keeping deployments repeatable, auditable, and rollback-friendly without adding workflow overhead.
X-API-Version header, with 400 on missing and 404 on unsupported). This is the decision input for "do we version by URL, by header, or not at all" and for how long old versions stay alive. Header versioning in particular is a product decision — it constrains clients and caching/CDN behaviour — and this package makes it cheap to implement once the decision is made.composer update. It affects release tooling, action authoring conventions, config, and API routing — all of which have downstream docs, runbooks, and on-call implications. Treat it as a roadmap item with an owner.down() before it is allowed to deploy, since irreversible actions fail clearly at rollback time; and (b) whether safety.fail_on_changed_action stays on, which means editing an already-executed action file blocks deploys. Both are policy that determines whether "rollback" is a real incident tool or a nominal one.Evolver::fake(), assertExecuted, assertRolledBack, add/touch/forget) plus 100% line/type coverage and PHPStan in CI reduces the cost of regression-testing release logic and improves confidence in the rollback path — which is exactly the code path you never want to exercise for the first time during an incident.Adopt when:
lock.store is genuinely shared across all deployers. Validate this before promising "no concurrent deploys."Route::apiVersion() macro and header resolver make this a small, testable amount of code.ActionExecutionException names the failing action and what already completed) are the features you would spec anyway.evolver:action emits snake_case), and executed action files must not be edited.Look elsewhere when:
migrations table; Evolver is a superset you would be paying attention-cost for.down() methods your team writes — it will refuse or fail on irreversible actions. If the business expectation is "rollback always works," this package will not deliver that without an authoring policy behind it.php artisan migrate plus CI.To executives: We currently apply code and data changes with migrations and hand-written scripts, which means the riskiest part of a release — the data change — has no standard history, no ordering guarantee, and no reliable undo. Laravel Evolver v3 adds exactly those three things: a lock so two deploys can't interleave, a checksummed record of every change that ran, and a evolver:rollback command that reverses a release batch in reverse order. It also gives us one consistent way to serve two API versions at once, which is on our roadmap anyway. The upside is measurable in incident cost and in release confidence; the cost is a one-time upgrade project plus a runtime upgrade to PHP 8.4 and Laravel 12+.
To engineering: v3 is a rewrite of the deployment engine and is a breaking upgrade — action base class moves to Infinity\Evolver\Deployment\Action, handle() becomes up(), requiredUntil() becomes expiresAt(), down() is new and optional, action filenames are now identities in snake_case, config is restructured and must be republished, ApiVersionRouteRegistrar::routes() is replaced by the Route::apiVersion() macro with a globally registered ResolveApiVersion middleware, and the Api\*, Deploy\*, Version\*, Models\Evolution namespaces are gone. The evolutions table and its SHA-256 checksums are unchanged, so v2 history carries over — but actions v2 already executed must never be edited, because a checksum mismatch is treated as "changed" and blocks deploys under safety.fail_on_changed_action, and those old actions cannot be rolled back. Plan it as: config republish, convert-only-not-yet-run actions, swap the route registrar, then flip the lock store to something shared (Redis/database) before relying on locking in production.
Trade-off to state plainly: the safety features are opt-in in practice. Rollback works only where we write down(); the lock works only with a shared cache store; changed-action protection works only if we accept the block. Ship it with a policy — which action classes must be reversible, and who approves an irreversible one — or the headline feature is marketing rather than capability.
How can I help you explore Laravel packages today?