symplify/changelog-linker
Automatically links issue and pull request references in your changelog to GitHub (and similar) URLs. Cleans up release notes by turning #123, GH-123 or full references into clickable links, with configurable patterns and formatting for consistent, readable changelogs.
Installation Add the package via Composer:
composer require symplify/changelog-linker --dev
Register the package in composer.json under extra:
{
"extra": {
"symplify": {
"changelog-linker": {
"file": "CHANGELOG.md",
"format": "markdown"
}
}
}
}
First Use Case
Run the CLI command to generate links in your CHANGELOG.md:
vendor/bin/changelog-linker
This will automatically link:
#123 → [#123](https://github.com/your/repo/issues/123)).v1.0.0 → [v1.0.0](https://github.com/your/repo/releases/tag/v1.0.0)).Where to Look First
composer.json under extra.symplify.changelog-linker.vendor/bin/changelog-linker --help for options.#123, GH-456, v1.2.3).Automated CI Integration Add to your CI pipeline (e.g., GitHub Actions) to auto-link changelogs post-release:
- name: Link CHANGELOG
run: vendor/bin/changelog-linker
Trigger after git tag or git push.
Custom Link Formats
Extend via extra.symplify.changelog-linker:
{
"custom_patterns": [
{
"pattern": "/\\b(?:fix|feat)\\/([a-f0-9]+)\\b/",
"replacement": "[\\0](https://your-tracker.com/issues/\\1)"
}
]
}
Dry Run Mode Test changes without modifying files:
vendor/bin/changelog-linker --dry-run
Multi-File Support
Process additional changelog files (e.g., UPGRADING.md):
{
"files": ["CHANGELOG.md", "UPGRADING.md"]
}
Pre-Release Workflow:
CHANGELOG.md manually.changelog-linker to auto-link references.Post-Merge Workflow:
Use Git hooks (e.g., post-merge) to auto-link changelogs when merging PRs.
Laravel Artisan Command:
Create a custom Artisan command to wrap changelog-linker:
// app/Console/Commands/LinkChangelog.php
namespace App\Console\Commands;
use Symfony\Component\Process\Process;
class LinkChangelog extends Command {
protected function handle() {
$process = new Process(['vendor/bin/changelog-linker']);
$process->run();
$this->info($process->getOutput());
}
}
Register in app/Console/Kernel.php and run via php artisan changelog:link.
GitHub Actions Example:
name: Changelog Linker
on: [push]
jobs:
link-changelog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install --dev
- run: vendor/bin/changelog-linker
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "chore: auto-link CHANGELOG.md"
Case Sensitivity in GitHub Links
github.com/YourRepo vs. github.com/yourrepo).extra.symplify.changelog-linker.repo matches your repo’s exact case.Custom Patterns Overwriting Defaults
custom_patterns may break existing links.--dry-run first.Non-Markdown Files
.txt), set "format": "plain".GitHub Enterprise/SSH URLs
https://github.com. For Enterprise or SSH:
{
"github_url": "https://github.yourcompany.com",
"use_ssh": true
}
Performance with Large CHANGELOGs
Verbose Output:
vendor/bin/changelog-linker -v
Shows skipped entries and regex matches.
Log File: Redirect output to a file for debugging:
vendor/bin/changelog-linker > changelog-linker.log 2>&1
Common Errors:
Invalid repo URL: Verify repo in config matches your Git remote.No matches found: Check if your changelog uses supported patterns (e.g., #123).Dynamic Repo Detection
The package auto-detects the repo from .git/config. Override with:
{
"repo": "your-org/your-repo"
}
Branch-Specific Links Link to branch-specific issues/PRs:
{
"branch": "dev",
"github_url": "https://github.com/your-org/your-repo/issues/{issue}?branch={branch}"
}
Excluding Sections
Skip certain changelog sections (e.g., ## Uncategorized):
{
"exclude_sections": ["Uncategorized"]
}
Custom Replacement Logic Extend via a PHP service provider:
// app/Providers/ChangelogLinkerServiceProvider.php
namespace App\Providers;
use Symplify\ChangelogLinker\ValueObject\Configuration;
class ChangelogLinkerServiceProvider extends \Illuminate\Support\ServiceProvider {
public function register() {
$this->app->extend(Configuration::class, function ($config) {
$config->addCustomPattern('/\b(?:BUG|TASK)-(\d+)\b/', '[\\0](https://jira.example.com/browse/\\1)');
return $config;
});
}
}
Post-Processing Hooks
Use Laravel’s finished event to run additional logic after linking:
// app/Providers/EventServiceProvider.php
protected $listen = [
\Symplify\ChangelogLinker\Application::class => [
\App\Listeners\PostChangelogLink::class,
],
];
GitLab/Bitbucket Support
Override the github_url template:
{
"github_url": "https://gitlab.com/{repo}/issues/{issue}",
"use_ssh": false
}
How can I help you explore Laravel packages today?