Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Composer Changelog Bundle Laravel Package

idlab/composer-changelog-bundle

A Symfony bundle that brings Composer package changelogs into your application. It reads changelog data for installed dependencies and exposes it through services and Twig helpers, letting you display release notes, versions, and recent changes without leaving your project.

View on GitHub
Deep Wiki
Context7

Getting Started

Read composer.json before you run composer require. The single decision that shapes everything else is the type field:

  • "type": "composer-plugin" → it hooks into Composer's install/update lifecycle. Do not install it into a Laravel app casually; audit scripts and the plugin class first.
  • "type": "symfony-bundle" → it expects symfony/framework-bundle, a kernel, and a DI container. Laravel ships Symfony components but not framework-bundle.
  • "type": "library" → the good case. The generator is likely a plain service you can new up or resolve from Laravel's container.

Constraint check first (five minutes, no install):

composer require --dev idlab/composer-changelog-bundle --dry-run
composer why-not idlab/composer-changelog-bundle

If it wants symfony/framework-bundle, stop and take the extraction path (see Implementation Patterns) rather than the install path.

Then read src/. There is no docs site, no Stack Overflow corpus, and no issue history worth mining. Assume source-first onboarding: spend half a day finding the class that actually builds the changelog and note its constructor dependencies. Everything downstream depends on whether that class is container-free.

First use case — the one that pays for itself immediately: you're bumping a batch of dependencies on a release branch and need a human-readable "what changed in our dependency tree" note for the release ticket. Point the generator at the current composer.lock, capture the output, and diff it against the output from the previous tag. If the diff is accurate enough that you'd paste it into a customer-facing release note, the tool has earned its keep. If it's a wall of noise, you've spent a day and learned something.

If and only if the package is framework-bundle-coupled, fork it. It's small enough to review in an afternoon and MIT makes the fork clean:

git clone https://github.com/idlab-geneve/composer-changelog-bundle vendor-src/changelog
# strip the DependencyInjection/ and Command/ layers, keep the generator + templates

Commit the stripped generator under app/Support/Changelog/ with an attribution header. You now own ~200 lines instead of a dependency — which, per the adoption profile, is where this ends up anyway.

Implementation Patterns

Pattern 1: CI-only artifact job (lowest friction, recommended default)

Never install it into the application. Run it as a build step against the repo checkout. This eliminates every framework-bundle, container, and upgrade-blocker risk.

# .github/workflows/changelog.yml
- name: Generate dependency changelog
  run: |
    composer install --no-interaction --no-scripts --prefer-dist
    php vendor/bin/<the-generator-binary> --output=build/DEPENDENCY_CHANGELOG.md || true
  continue-on-error: true   # non-blocking during the pilot

- uses: actions/upload-artifact@v4
  with:
    name: dependency-changelog
    path: build/DEPENDENCY_CHANGELOG.md
    retention-days: 90

The continue-on-error: true plus artifact retention is the whole mitigation strategy: if the tool silently emits nothing, you still have two releases of artifacts to diff and catch the regression.

Pattern 2: Standalone runner without a Symfony app

If the generator is container-wired but you don't want a full Symfony kernel, boot a micro-kernel in a throwaway script:

// tools/changelog.php — run in CI only, never autoloaded by the app
require __DIR__.'/../vendor/autoload.php';

$kernel = new \Symfony\Component\HttpKernel\Kernel('dev', true); // or a bare ContainerBuilder
// register only the bundle's generator service, then pull it out:
$generator = $container->get(/* generator service id from src/Resources/config/services.yaml */);

file_put_contents(
    $argv[1] ?? 'DEPENDENCY_CHANGELOG.md',
    $generator->generate()
);

Read src/Resources/config/services.yaml to get the service id and any required parameters. This is the "I want the feature without adopting the framework" escape hatch.

Pattern 3: Artisan command wrapper (only after the pilot passes)

Once output quality is proven, wrap it so developers can run it locally without remembering CI incantations:

// app/Console/Commands/Changelog.php
class Changelog extends Command
{
    protected $signature = 'changelog:deps
                            {--since= : Git tag or commit to diff the lockfile against}
                            {--include=* : Only these packages}
                            {--exclude=* : Never these packages}';

    public function handle(ChangelogGenerator $generator): int
    {
        $packages = $this->option('since')
            ? $this->lockfileDiff($this->option('since'))
            : null;

        $this->line($generator->render(
            packages: $packages,
            include:  $this->option('include'),
            exclude:  $this->option('exclude'),
        ));

        return self::SUCCESS;
    }

    private function lockfileDiff(string $ref): array
    {
        // git show "$ref:composer.lock" vs current, key-diff on packages[].name/version
    }
}

Bind ChangelogGenerator in a service provider to a thin adapter around the forked class. Keep this in app/Console/Commands behind an internal namespace — no facades, no public API.

Pattern 4: Lockfile-diff release note

The genuinely useful workflow: the generator tells you what's installed; the release note needs what changed. Drive that with the lockfile diff, not with a full regeneration:

git show "$PREV_TAG:composer.lock" > /tmp/old.lock
php artisan changelog:deps --since="$PREV_TAG" | tee release-notes/DEPENDENCIES.md

Feed the resulting list to the generator's include filter so the output contains only the packages that actually moved. This is where configurable package filtering earns its place — without it you get a 300-line wall of unchanged dependencies.

Pattern 5: Template override for your house style

The bundle's templating is the integration point that matters most, because release-note automation lives or dies on format control. Override the template file in your fork (or config path, if exposed) and keep it under version control:

{# templates/changelog.md.twig — adjust to the actual template engine in src/ #}
## Dependency changes

{% for package in packages %}
- **{{ package.name }}** `{{ package.from }}` → `{{ package.to }}` — [compare](https://github.com/{{ package.repo }}/compare/{{ package.from }}...{{ package.to }})
{% else %}
_No dependency changes._
{% endfor %}

The {% else %} branch is not cosmetic — it turns silent-empty-output into a visible, greppable sentence.

Pattern 6: Filter policy as config, not code

Keep include/exclude lists in config/changelog.php so the list survives a fork or an upstream swap:

return [
    'exclude' => [
        'laravel/framework', 'symfony/*', 'phpunit/phpunit', 'mockery/*',
        // noise: internal version churn nobody reads in a release note
    ],
    'include' => [
        // high-signal vendors you actually want to surface to support/CS
    ],
    'sections' => ['Added', 'Changed', 'Fixed', 'Removed'],
];

Exclude the framework and the test toolchain by default. A changelog that lists every symfony/* patch bump is one nobody reads.

Gotchas and Tips

Framework-bundle is a hard blocker, not a friction point. Laravel doesn't ship symfony/framework-bundle, and installing it drags a competing kernel, container, and config model into your app for one report. Never install this into the application if that's the constraint — fork, extract the generator class, or run it CI-only.

Audit for composer-plugin and scripts before install. A plugin-type package runs code during composer install/update on every developer machine and every CI run. Given zero adoption and a single-org upstream, read the plugin class line by line. If you can't justify it, --no-scripts on CI and don't install locally.

Silent empty output is the failure mode that bites. Blank release notes ship and nobody notices until an audit or a customer asks. Guard it explicitly:

test -s build/DEPENDENCY_CHANGELOG.md || { echo "::warning::changelog was empty"; exit 1; }

Better: assert a minimum line count, since a one-line placeholder file passes -s.

Composer internals drift between 2.x minors. Anything introspecting lockfile shape or shelling out to composer can break on upgrade without an upstream version bump. Pin Composer in CI:

COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer

Pin the package to an exact version. "idlab/composer-changelog-bundle": "1.2.3", not ^1.2. Floating constraints against an inactive upstream is how you get silent pipeline breakage on a random Tuesday. Zero dependents means zero people reporting the breakage before you hit it.

Confirm the data source — local lockfile vs. remote API. If it reads composer.lock locally, you're fine. If it queries Packagist/GitHub per package, you've introduced network dependency, token management, and rate limits into CI — and it will fail entirely on air-gapped or restricted runners. Check src/ for Guzzle/HTTP clients before rollout.

No service provider, no config publish, no facade. Don't go looking for php artisan vendor:publish. Nothing about this package follows Laravel conventions; that's the whole integration cost.

Output format drift breaks downstream parsers. If anything (a Slack notifier, a docs build, a ticket template) parses the changelog, a template tweak or an upstream formatting change silently breaks it. Pin the template in your repo and treat the output format as an internal contract.

Watch the PHP constraint at every upgrade. An unmaintained dev dependency with a php: ^8.1 constraint becomes your upgrade blocker when you move to 8.4. Check composer why-not php 8.4 before scheduling framework upgrades — forking to relax one constraint is usually a five-minute fix, but you want to find it before the upgrade branch, not during.

The --dry-run conflict check is worth more than it looks. Run it against the exact Laravel version you're on. A conflict with illuminate/support at install time saves you a confusing autoload failure later.

Debug by reading source, not by searching. No Stack Overflow corpus, no issue history. When output is wrong, the answer is in src/ — usually in how it resolves package versions or what it treats as a "change." Budget half a day for this once and write your findings into the repo's engineering docs.

Non-blocking in CI, always. During the pilot, the job must not gate merges. Two or three release cycles of artifacts is enough evidence to decide between adopt, fork-and-own, and a ~200-line in-house lockfile differ. Set that decision gate up front so the tool doesn't quietly become infrastructure.

Fork-and-own is the likely endpoint — plan for it optimistically. The generator is not large software. If the pilot shows the output is accurate, keep it; if it shows the problem is real but the implementation is thin, write the lockfile differ yourself and cite this package as the reference design. That's a win either way, and framing it that way stops the evaluation from turning into a sunk-cost argument.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource