When to Release a New Major Package Version
Laravel package maintainers should release a new major version when a change breaks something they promised users would keep working. Those promises…
Laravel package maintainers need upgrade notes that help users decide whether a major release affects their code and what to change before upgrading. A major release signals that backward-incompatible changes may exist. Upgrade notes identify those changes and give affected users a path to update and verify their applications.
A package’s public API is the set of interfaces users are expected to rely on. For a Laravel package, that includes PHP classes and methods, plus commands users run through Artisan. It also covers configuration keys and database migration files users publish in their applications, along with routes, middleware aliases, and events. Under Semantic Versioning, a backward-incompatible change to the declared public API requires a major version increment after version 1.0.0. That version number signals a compatibility break, but it does not tell each user whether the break applies to them.
Clear notes name the affected surface, explain who needs to act, and describe the action and a way to check the result. This structure gives users steps to follow and helps prevent avoidable support requests. No note format guarantees fewer support requests.
Open the upgrade guide with a short impact summary. Tell readers whether the release affects users who call a particular method, publish the package’s configuration, customize a model, implement a package contract, or have already copied a migration into their application. Readers who do not use an affected surface should be able to tell that they can skip the corresponding instruction.
Be precise about what the package treats as public. A method rename matters to users who call that method. A migration change matters to users whose database setup includes the earlier migration. A new default configuration value can affect users who rely on package defaults, while a renamed key can require an edit from users with a published configuration file. These are different changes with different audiences, even when they ship in the same major release.
The Laravel upgrade guide offers a useful model: it identifies specific changes and says which applications they affect. Apply that principle to a package by naming which users need each step, using wording such as “If your application implements this contract…” or “If you published this configuration file…”. This keeps conditional steps from sounding mandatory for everyone.
A useful breaking-change entry answers four questions: what changed, who is affected, what action they should take, and what happens if they do nothing when that consequence is known. “The API changed” answers none of them. “The package removed a method used by custom model implementations; update those implementations to use the replacement method” gives readers a way to assess and address the change.
Keep the change under a consistent changelog category, such as Changed or Removed, and mark it clearly as breaking. Keep a Changelog recommends identifying the broken interface rather than relying on the word “breaking” by itself. A prominent summary near the top of the upgrade guide can help readers scan, while categorized entries keep the full record organized.
When the consequence is not established, do not guess. State what the release changes and which users encounter it, then tell them what to inspect in their own integration with the package. For example, if a package changes a migration stub, explain whether users who already ran the previous migration need an application migration. The package’s actual schema and data changes determine the answer; “run migrations” is not a safe universal instruction.
For a renamed class, method, event, command, or namespace, give users a direct mapping and say where to update references. A compact table works well:
| Before | After | User action |
|---|---|---|
| Old class or symbol | Replacement class or symbol | Update the relevant import, listener, binding, or call site |
The action column matters. A class rename may require a change in an event listener or service-provider binding, while a method rename affects call sites. If the command’s PHP class changes but its Artisan name and options stay the same, say so. Readers should not infer that one name change implies another.
The Spatie laravel-permission upgrade guide demonstrates this approach with package-specific event and command renames. Its instructions also distinguish renamed classes from unchanged command signatures. Those details describe that package’s releases, but the documentation technique applies broadly: name the old and new symbols, identify likely integration points, and specify what remains unchanged when that distinction affects the user’s work.
For each configuration change, name the file and key. Explain whether the change added or removed the key, renamed or moved it, or gave it a new default. State who must edit it. A mapping table makes spelling and structure changes easy to compare:
| Existing configuration | New configuration | User action |
|---|---|---|
| Previous key or structure | Replacement key or structure | Edit the published file, if present |
Some users rely on package defaults; others publish a configuration file and customize it. Laravel package documentation explains that Laravel combines package defaults with application configuration at the first level of the configuration array, but does not merge nested arrays at deeper levels. The Laravel package development documentation is for Laravel 10.x, so maintainers should check the behavior against the Laravel versions their package supports.
State whether users with an unpublished default configuration need to act, and whether users with a published file should edit it or publish a fresh copy. If the new default changes behavior, explain how a user can preserve the previous behavior when the package supports that choice. When instructions involve environment variables, identify where the user should set them and what deployment step follows. Laravel documents that configuration caching changes when .env values are loaded, so users should not be left to assume that editing an environment file immediately changes a cached deployment’s behavior. See the Laravel configuration documentation.
A migration guide should separate package installation from application-specific changes. Give actions in the order users should perform them, and mark conditional work explicitly. For example:
composer.json and run the targeted Composer update.The Spatie upgrade guide provides package-specific examples of these tasks, including comparing migration stubs and checking custom models and contract signatures. Do not present every step as mandatory for every user. Write “If your application has already run the previous migration…” or “If you implement this contract…” so readers can skip work that does not match their setup.
Describe database changes carefully. If a release changes the database structure (its schema), explain whether users need a new application migration and what that migration changes. Do not tell users to run a database command without confirming the package’s migration behavior and the deployment context. The user needs enough detail to plan the change, especially when existing data is involved.
Use the changelog as the durable, complete record of notable release changes. Use the major-version upgrade guide as the focused path through compatibility breaks and migration work. A release announcement can summarize the headline changes and link to that guide. Keep a Changelog distinguishes the ongoing changelog from release notes that curate information and include upgrade instructions.
A short action can sit beside its changelog entry. When a change requires several steps, keep the entry brief and link to the detailed upgrade instructions. This lets users scan the release record without losing the steps they need to complete the upgrade.
Review generated notes before publishing. Commit history and automated summaries can help identify changes, but they do not reliably explain user impact. Check that the notes cover every break users encounter. For each renamed symbol, confirm that the notes name a replacement. Make sure they distinguish default configuration from published files and match the package’s actual database migration path. Finally, verify that the notes describe the released code.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com