marcocesarato/php-conventional-changelog
Automatically generate changelogs and release notes from your Git history using Conventional Commits and SemVer. CLI tool with configurable templates and options to extract releases and output Markdown changelogs, suitable for Composer scripts and CI workflows.
Installation:
composer require --dev marcocesarato/php-conventional-changelog
First Run (for a new project):
php vendor/bin/conventional-changelog --first-release
This generates a CHANGELOG.md with the initial version 1.0.0 and all commits since the project's start.
Daily Workflow:
feat: add user auth, fix: login bug).composer changelog
php vendor/bin/conventional-changelog --help for CLI options.Pre-Release Changelog Generation:
composer changelog --minor # Auto-bumps to MINOR version (e.g., 1.0.0 → 1.1.0)
--major, --patch, or --rc to control versioning.composer.json scripts:
"scripts": {
"release": "conventional-changelog --commit --annotate-tag",
"release:patch": "conventional-changelog --patch --commit"
}
Custom Config for Laravel Projects:
Create .changelog in project root:
return [
'headerTitle' => 'Laravel Project Releases',
'types' => ['feat', 'fix', 'docs', 'refactor'], // Override defaults
'packageBump' => true, // Auto-update `composer.json` version
'packageBumps' => [
'ConventionalChangelog\PackageBump\ComposerJson',
'ConventionalChangelog\PackageBump\PackageJson' // If using npm
],
'prettyScope' => true, // Convert `auth:login` → `Auth: Login`
'urlProtocol' => 'https',
'issueUrlFormat' => 'https://github.com/{host}/{owner}/{repository}/issues/{number}'
];
CI/CD Integration:
- name: Generate Changelog
run: composer changelog --minor --commit --annotate-tag
git push to main with commit messages like release: v1.2.0.Partial History: Generate changelog for a specific range (e.g., last 3 versions):
composer changelog --from-tag="v1.0.0" --to-tag="v1.3.0"
Artisan Command Wrapper: Create a custom Artisan command to wrap the changelog generator:
// app/Console/Commands/GenerateChangelog.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Process\Process;
class GenerateChangelog extends Command
{
protected $signature = 'changelog:generate
{--type= : Release type (major|minor|patch)}
{--commit : Auto-commit changes}';
public function handle()
{
$process = new Process([
'php', 'vendor/bin/conventional-changelog',
'--' . ($this->option('type') ?: 'patch'),
$this->option('commit') ? '--commit' : null
]);
$process->run();
$this->output->write($process->getOutput());
}
}
Register in app/Console/Kernel.php:
protected $commands = [
\App\Console\Commands\GenerateChangelog::class,
];
Now run with:
php artisan changelog:generate --type=minor --commit
Package Version Sync:
Use packageBump: true in .changelog to auto-update composer.json version. For Laravel packages, ensure version in composer.json is updated before publishing.
Commit Message Format:
fix login bug → missing :).commit-msg hook in .git/hooks/commit-msg:
#!/bin/sh
php artisan commit:validate $1 || exit 1
(Use a package like laravel-commit-msg.)Version Bump Conflicts:
composer.json version edits conflict with auto-bumps.packageBump in .changelog and manually bump versions:
'packageBump' => false,
Or use --ver="1.2.0" to specify the version.Git History Gaps:
--history overwrites CHANGELOG.md but may miss merged branches.--merged to include only commits reachable from HEAD:
composer changelog --history --merged
Annotated Tags:
--annotate-tag fails if git tag permissions are restricted.composer changelog --no-tag
composer changelog --no-commit --no-tag
strace or wrap in a script to log process output)..changelog syntax with:
php -r 'include ".changelog"; var_dump($config);'
Custom Templates:
Override the Markdown template by extending the package’s ChangelogGenerator:
// app/Providers/AppServiceProvider.php
use ConventionalChangelog\ChangelogGenerator;
public function boot()
{
$generator = new ChangelogGenerator();
$generator->setTemplate('custom-template.md'); // Path to your template
}
Pre/Post Hooks:
Use preRun and postRun in .changelog to integrate with Laravel events:
'preRun' => function () {
// Run before changelog generation (e.g., validate commits)
\Log::info('Running pre-changelog hooks...');
},
'postRun' => function () {
// Run after (e.g., notify Slack)
\Artisan::call('notify:release');
},
Custom Commit Parsing:
Extend the CommitParser to handle Laravel-specific commit types (e.g., laravel: migrate):
// app/Providers/AppServiceProvider.php
use ConventionalChangelog\CommitParser;
public function boot()
{
$parser = new CommitParser();
$parser->addType('laravel', [
'label' => 'Laravel Updates',
'description' => 'Changes to Laravel-specific components'
]);
}
types vs. ignoreTypes:
types: [] → Only show commits with these types.ignoreTypes: [] → Show all types (overrides defaults like chore).path in .changelog is relative to root. Use absolute paths if needed:
'path' => '/full/path/to/CHANGELOG.md',
dateFormat to match Laravel’s config('app.datetime_format'):
'dateFormat' => 'Y-m-d H:i:s',
--from-tag to limit history:
composer changelog --from-tag="v1.0.0"
How can I help you explore Laravel packages today?