laravel-release-manager maintained by sunnynath
Laravel Release Manager
Enterprise-ready application release metadata and version governance for Laravel applications.
sunnynath/laravel-release-manager is a standalone Laravel package for exposing, resolving, caching, and automating application release metadata. It is designed for teams that need a reliable way to answer simple but important production questions:
- What version is currently deployed?
- Which build, branch, and commit produced this runtime?
- Where should release metadata come from in CI/CD?
- How can APIs and operational tooling expose release details safely?
- How can Git tags and version files stay in sync?
The package follows Semantic Versioning for application release versions and supports Laravel package auto-discovery.
Requirements
- PHP 8.2 or higher
- Laravel 10, 11, or 12
- Composer
- Git, only when using Git-backed release automation commands
Installation
Install the package with Composer:
composer require sunnynath/laravel-release-manager
Laravel auto-discovers the service provider and facade. Publish the configuration file:
php artisan vendor:publish --tag=release-manager-config
This publishes:
config/release-manager.php
Quick Start
Set a release version in your environment:
RELEASE_VERSION=1.2.3
RELEASE_BUILD_NUMBER=20260517.1
RELEASE_COMMIT_HASH=abc1234
RELEASE_BRANCH=main
Show the current release metadata:
php artisan release:show
Use the helper functions anywhere in your Laravel app:
$version = release_version();
$metadata = release_metadata();
Render the application version in Blade:
@appVersion
Use the facade:
use Sunnynath\LaravelReleaseManager\Facades\Release;
$version = Release::version();
$metadata = Release::metadata();
Configuration
After publishing the config file, configure release metadata in config/release-manager.php.
Common environment variables:
RELEASE_VERSION=1.2.3
RELEASE_FALLBACK_VERSION=0.1.0
RELEASE_VERSION_FILE=/absolute/path/to/VERSION
RELEASE_BUILD_NUMBER=20260517.1
RELEASE_COMMIT_HASH=abc1234
RELEASE_BRANCH=main
RELEASE_CHANNEL=stable
RELEASE_CHANGELOG_URL=https://example.com/changelog
APP_ENV=production
Cache configuration:
RELEASE_CACHE_ENABLED=true
RELEASE_CACHE_TTL=300
RELEASE_CACHE_STORE=array
Optional metadata endpoint configuration:
RELEASE_METADATA_ENDPOINT_ENABLED=false
RELEASE_METADATA_ENDPOINT_PATH=release
Git automation configuration:
RELEASE_GIT_PATH=/path/to/application
RELEASE_GIT_BINARY=git
RELEASE_GIT_TIMEOUT=30
RELEASE_GIT_TAG_PATTERN=v*
RELEASE_GIT_TAG_PREFIX=v
RELEASE_GIT_INCLUDE_UNPREFIXED_TAGS=true
Compatibility governance configuration:
RELEASE_COMPATIBILITY_ENABLED=true
RELEASE_MIN_CLIENT_VERSION=2.0.0
RELEASE_CLIENT_VERSION_HEADER=X-Client-Version
RELEASE_ALLOW_MISSING_CLIENT_VERSION=false
RELEASE_INCOMPATIBLE_STATUS=426
Audit logging configuration:
RELEASE_AUDIT_ENABLED=true
Version Resolution
Versions are resolved from configured sources in deterministic priority order. The first source that returns a non-empty valid Semantic Version wins.
'sources' => [
'priority' => [
'env',
'config',
'file',
'git',
],
],
Available sources:
| Source | Description |
|---|---|
env |
Reads the configured environment key, usually RELEASE_VERSION. |
config |
Reads a Laravel config key, usually release-manager.version. |
file |
Reads a version string from a configured file. |
git |
Reads the latest valid Semantic Version from Git tags. |
If no configured source returns a version, the package uses fallback_version.
Supported version examples:
1.2.3
v1.2.3
1.2.3-beta.1
1.2.3+build.42
1.2.3-rc.1+build.42
The leading v is accepted and normalized away.
Release Metadata
release_metadata() and Release::metadata() return a ReleaseMetadata value object with:
| Field | Description |
|---|---|
version |
Resolved Semantic Version. |
build_number |
Build identifier from config/env. |
commit_hash |
Git commit hash from config/env. |
branch |
Branch name from config/env. |
environment |
Laravel application environment. |
channel |
Release channel: stable, beta, or rc. |
changelog_url |
Optional changelog reference URL. |
Example:
$metadata = release_metadata();
$metadata->version();
$metadata->buildNumber();
$metadata->commitHash();
$metadata->branch();
$metadata->environment();
$metadata->channel();
$metadata->changelogUrl();
$metadata->toArray();
Compatibility Governance
API client compatibility checks. Configure a minimum supported client version:
'compatibility' => [
'enabled' => true,
'minimum_client_version' => '2.0.0',
'client_version_header' => 'X-Client-Version',
'allow_missing_client_version' => false,
'incompatible_status' => 426,
'message' => 'Client version is no longer supported.',
],
Attach the middleware to API routes:
use Illuminate\Support\Facades\Route;
Route::middleware('release.compatible')->group(function () {
Route::get('/api/profile', ProfileController::class);
});
Compatible clients pass through when their header satisfies the configured minimum:
X-Client-Version: 2.1.0
Incompatible clients receive a structured JSON response:
{
"error": {
"code": "incompatible_client",
"details": {
"compatible": false,
"reason": "minimum_version_not_satisfied",
"message": "Client version is no longer supported.",
"client_version": "1.9.9",
"minimum_client_version": "2.0.0",
"app_version": "1.2.3",
"channel": "stable",
"changelog_url": "https://example.com/changelog"
}
}
}
You can also use the service directly:
use Sunnynath\LaravelReleaseManager\Services\CompatibilityManager;
$result = app(CompatibilityManager::class)->check('2.1.0');
$result->compatible();
$result->toArray();
Artisan Commands
release:show
Displays the resolved application release metadata.
php artisan release:show
php artisan release:show --json
release:bump
Bumps the resolved version and writes it to the configured version file.
php artisan release:bump patch
php artisan release:bump minor
php artisan release:bump major
php artisan release:bump patch --pre-release=beta.1
php artisan release:bump patch --build=20260517.1
php artisan release:bump patch --dry-run
php artisan release:bump patch --json
php artisan release:bump patch --ci
Supported bump parts:
| Part | Example |
|---|---|
patch |
1.2.3 to 1.2.4 |
minor |
1.2.3 to 1.3.0 |
major |
1.2.3 to 2.0.0 |
release:sync
Finds the latest valid Semantic Version from Git tags and writes it to the configured version file.
php artisan release:sync
php artisan release:sync --dry-run
php artisan release:sync --json
php artisan release:sync --ci
release:tag
Previews or creates a Git tag for a release version.
php artisan release:tag
php artisan release:tag 1.2.3
php artisan release:tag 1.2.3 --create
php artisan release:tag 1.2.3 --create --lightweight
php artisan release:tag 1.2.3 --create --message="Release 1.2.3"
php artisan release:tag 1.2.3 --dry-run
php artisan release:tag 1.2.3 --json
php artisan release:tag 1.2.3 --ci
By default, release:tag is a preview. Pass --create to actually create the Git tag. The options --create and --dry-run cannot be used together.
release:doctor
Checks release manager configuration and Git automation readiness. This is the fastest way to catch malformed source priority, invalid Semantic Versions, invalid release channels, missing Git state, and command setup issues.
php artisan release:doctor
php artisan release:doctor --json
php artisan release:doctor --ci
All release automation commands support --json and --ci for CI/CD pipelines. The --ci option implies machine-readable JSON output and deterministic exit codes.
In CI mode, release:doctor fails only for critical problems such as invalid configuration or an unresolvable release version. Non-critical readiness warnings, such as optional Git details not being available, are reported in JSON without failing the process.
Laravel About Command
The package registers release details with Laravel's built-in about command:
php artisan about
php artisan about --json
The Laravel Release Manager section includes:
- Package name and package version
- Resolved application version
- Release channel
- Build number, commit hash, and branch
- Minimum supported client version
- Cache and metadata endpoint status
Audit Logging
Release-changing commands write compact audit log entries after real changes:
| Command | Audit action |
|---|---|
release:bump |
release.bumped |
release:sync |
release.synced |
release:tag --create |
release.tagged |
Dry runs are not logged. Disable logging with:
RELEASE_AUDIT_ENABLED=false
HTTP Headers
Attach the middleware to routes that should expose release headers:
use Illuminate\Support\Facades\Route;
Route::middleware('release.headers')->group(function () {
Route::get('/health', HealthCheckController::class);
});
The middleware adds:
| Header | Value |
|---|---|
X-App-Version |
Resolved application version. |
X-App-Build |
Configured build number. |
X-Git-Commit |
Configured commit hash. |
You may also reference the middleware class directly:
use Sunnynath\LaravelReleaseManager\Http\Middleware\AddReleaseHeaders;
Route::middleware(AddReleaseHeaders::class)->get('/health', HealthCheckController::class);
Optional Metadata Endpoint
The JSON metadata endpoint is disabled by default because release metadata can be operationally sensitive.
Enable it in config/release-manager.php:
'http' => [
'endpoint' => [
'enabled' => true,
'path' => 'release',
'middleware' => [],
],
],
Then request:
GET /release
Example response:
{
"data": {
"version": "1.2.3",
"build_number": "20260517.1",
"commit_hash": "abc1234",
"branch": "main",
"environment": "production",
"channel": "stable",
"changelog_url": "https://example.com/changelog"
}
}
For production APIs, protect this endpoint with your own middleware when needed:
'middleware' => ['auth:sanctum'],
Blade Usage
Render the current application version:
@appVersion
Example footer:
<footer>
Version @appVersion
</footer>
Facade And Helpers
Helpers:
release_version(); // string
release_metadata(); // ReleaseMetadata
Facade:
use Sunnynath\LaravelReleaseManager\Facades\Release;
Release::version();
Release::metadata();
CI/CD Examples
Bump a patch version and create a tag:
php artisan release:bump patch --ci
php artisan release:tag --create --ci
Sync the application version from Git tags:
php artisan release:sync --ci
Read machine-friendly metadata:
php artisan release:show --json
php artisan release:doctor --json
Contributing
Contributions are welcome through pull requests.
The usual workflow is to fork the repository, create a branch in your fork, make the change, and open a pull request back to this repository. Contributors do not need branches inside the main repository.
git clone https://github.com/metaphorized-soul/laravel-release-manager.git
cd laravel-release-manager
git checkout -b fix/some-bug
# make changes
composer test
composer validate --strict
git add .
git commit -m "Fix some bug"
git push origin fix/some-bug
Then open a pull request from your fork. Please include a short explanation of the change and tests when the change affects behavior.
Testing
From the package root:
composer install
composer test
Run Composer validation before tagging a release:
composer validate --strict
License
Laravel Release Manager is open-sourced software licensed under the MIT license.