misodrobny/application-versioning
Laravel package for application versioning that helps you manage and expose your app's version consistently. Configure version details, display them in views or API responses, and keep release information centralized across environments. Useful for release tracking, status pages, and support workflo...
Architecture fit. The package is a thin, conventional Laravel service provider package: a singleton binding (ApplicationVersioning), a facade, an artisan install command, and an increase command. That is the right shape for a version-metadata utility and it fits cleanly into a standard Laravel app without touching the framework's bootstrapping. The 0.2.0 release does not change that architecture; it tightens it. Routing all consumers through the container (getFormatedVersion(), install command, increase command) removes the previous pattern of ad-hoc new ApplicationVersioning(...) instances, which is a meaningful correctness improvement: a singleton that isn't actually used as a singleton is a latent config-drift bug, and it is now closed.
Integration feasibility. High for the core use case. The package's job — produce a version string from version.yaml plus an optional git hash, and let CI or a deploy step bump it — is a small, well-bounded responsibility. The new disk abstraction is the notable capability change: reading and writing version.yaml through any Laravel filesystem disk via APP_VERSIONING_DISK / APP_VERSIONING_DISK_PATH means the version file no longer has to live on the app server's local filesystem. This unlocks at least two real scenarios: (a) a version file committed to the repo and read via a mounted artifact or object-store disk in containerized/immutable-image deploys, and (b) a central version record written by a release pipeline and read by many app instances. Backwards compatibility is explicitly preserved — no disk configured means the local version_file_path behaves as before — so the default path carries no migration cost.
Technical risk. Low-to-moderate, concentrated in three places. First, the git-hash fixes address real production failure modes rather than hypotheticals: detached HEAD (ubiquitous in CI and in deployments that check out a commit SHA rather than a branch) previously raised Undefined array key 1, and refs present only in packed-refs (post-git gc, fresh clones) previously resolved to nothing. The new "swallow unreadable .git and return the default" behavior is the right trade for a version-display utility — a missing hash should degrade the string, not break the page — but it does mean git problems become silent. Second, the disk feature introduces a new class of runtime dependency: a misconfigured or unreachable disk now affects version reads/writes that previously could not fail that way, and error semantics for disk I/O are not described in the notes. Third, the dependency bump to symfony/yaml ^7.1|^8.0 is what enables Laravel 13, but it also raises the floor: environments pinned to Symfony 6 or early 7 cannot take this release. Laravel 11/12/13 test coverage is a good signal, though the matrix does not tell us which PHP versions are exercised.
Key questions. What are the failure semantics when a configured disk is unreachable or read-only — exception, cached value, or default? Is there any caching of the disk read, and if so what invalidates it? Does version_file_path still act as a fallback when a disk is configured but the object is absent? Is the git hash included in the formatted version by default, and can it be suppressed for public-facing output? Which PHP versions are supported alongside Laravel 11–13, and does the CI matrix actually exercise Symfony 8? Is the silent-default behavior on unreadable .git logged anywhere? And for the container-resolution change: does anything in our codebase currently new up the class or rely on constructor arguments that the container will now supply differently?
Stack fit. Assumes a Laravel 11–13 application on a supported PHP version. Nothing here conflicts with standard Laravel conventions; the singleton-plus-facade pattern is idiomatic, and app(ApplicationVersioning::class) inside our own services is a clean injection point. The disk option fits our filesystem abstraction rather than inventing a parallel one, which is the main reason I'd accept it without a design argument.
Migration path. The release notes state no breaking changes, and the evidence supports that: the constructor-style instantiation that changed was internal to the package, the config keys are additive with the local path as default, and the git fixes only change behavior in cases that previously threw or returned nothing. Upgrading is a composer constraint bump plus, optionally, publishing the config. The one caveat is the Symfony floor — if we are on Symfony 6 anywhere in the dependency graph, composer update will either fail or force a wider upgrade, so treat that as the gating check.
Compatibility. Verify three things before merging: the resolved symfony/yaml version in our lockfile after update, that no first-party code depends on the old non-singleton construction, and that our deployment's git checkout style (branch, tag, or detached SHA) produces the hash we expect — the detached-HEAD fix should make this strictly better, but it is worth confirming what string actually lands in the version output in our own pipeline.
Sequencing. (1) Bump the constraint in a branch and let CI resolve dependencies; stop if Symfony 7.1 cannot be satisfied. (2) Confirm existing behavior is unchanged with no disk configured — this is the zero-risk step and validates the "no breaking changes" claim in our own app. (3) Only then evaluate the disk feature against a concrete need. If version reading is purely local and single-instance, the disk feature is a capability we should note and not adopt; if we run ephemeral containers with immutable filesystems, pilot it on a non-production environment with a deliberately unreachable disk to observe failure behavior before relying on it. (4) Do not adopt the disk for writes (the increase command) until we understand concurrent-write behavior — two deploy pipelines bumping the same object store path is a lost-update race the notes do not address.
Maintenance. Low and falling. The package is small, the surface area is narrow, and this release fixes bugs rather than expanding scope. The dependency bump to allow Symfony 8 is exactly the kind of forward-compatibility maintenance we want to see from a package we depend on, since it means Laravel 13 adoption isn't blocked on this library. Owning the published config file is the only recurring maintenance item, and it is two keys.
Support. Straightforward. Failures will present as a wrong or truncated version string, not as an outage. The one supportability regression is the intentional swallowing of .git read errors: when a version string comes out without a hash, we will need to check config and git state rather than read an exception. Worth documenting internally once so on-call doesn't rediscover it.
Scaling. The local-file default scales exactly as far as the app server does, which for most deployments is fine — the file is small and read once per request at most. The disk option changes the scaling profile: a remote disk read on every getFormatedVersion() call would add latency and a network dependency to a hot path, so if we adopt it we should confirm whether reads are cached and, if not, memoize on our side rather than call the facade in a loop or a view partial rendered many times. Writes via the increase command do not scale to concurrent writers without coordination.
Failure modes. Unreachable or read-only disk when one is configured (new in this release). Missing or unreadable .git directory — now degrades to a version string without a hash rather than throwing. Detached HEAD and packed refs — previously broken, now fixed, which retires two failure modes we would otherwise have hit in CI. Misconfigured disk_path silently reading a nonexistent object, if the package falls back to default rather than erroring. Version drift between instances if the source of truth is a local file baked into differently-tagged images.
Ramp-up. Minimal. A developer can read the config, the facade, and the two commands in well under an hour; the upgrade itself is a composer bump. The only knowledge worth deliberately transferring is deployment-shaped, not code-shaped: where version.yaml actually comes from in our pipeline, whether the git hash is populated in our checkout style, and what happens when the disk is down. That is a short internal note, not training.
How can I help you explore Laravel packages today?