roots/wp-packages-changelog-action: The GitHub Action That Makes WordPress Plugin Updates Reviewable

It pulls changelogs from WordPress.org, annotates pull requests, and flags versions that outrun a plugin’s stable tag, all without a build step.

6 to 8 min read • View on GitHub • More from roots

A reviewer sits between a pull request diff and a stack of WordPress plugin packages, with a narrow bridge connecting them. The bridge carries a changelog sheet and a warning flag, showing how the action turns dependency changes into something a human can judge quickly.
The action bridges Composer-native review and WordPress plugin reality, then adds a warning when the version on the lockfile is ahead of the stable tag.
Key Takeaways

WordPress developers who use Composer still live with a mismatch: the lockfile says what changed, but not whether the change is safe to ship. `roots/wp-packages-changelog-action` narrows that gap by pulling the plugin changelog into the PR itself and adding a warning when the version under review runs ahead of the stable tag on WordPress.org.

The problem: WordPress plugin updates are still hard to trust

In a modern dependency workflow, an update should be easy to inspect. In the WordPress plugin world, the metadata is split across Composer, WordPress.org, and whatever mirrors sit in between. That makes a routine bump feel less like a package upgrade and more like a small investigation.

WorkflowWhat you learnWhat you still do not know
Plain composer.lock diffWhich package version changedWhether the plugin release is stable or risky
PR comment with changelogWhat changed in the plugin releaseWhether the installed version matches the official stable tag
Manual review of WordPress.orgRelease notes and tagsYou have to leave the PR to gather it all

That is the gap this action is built to close. It takes a dependency update that would otherwise be opaque and turns it into something a reviewer can scan in seconds.

What this action actually does inside a pull request

The workflow is simple on the surface. The action compares the base and head lockfiles, filters for `wp-plugin/*` packages, queries WordPress.org for plugin metadata, then posts a single comment back to the PR. The comment is meant to update itself, not multiply.

One action, three routes, one comment. The output stays the same even when the input path changes.

That matters because the action is not just an information dump. It is built to survive the messy cases that happen in real GitHub automation, where file size, permissions, and API shape are not always ideal.

The part that makes it clever: layered fallbacks

A close-up of a composer.lock file with three branching paths leaving it. One path goes to a normal API fetch, one drops into a larger blob container, and one bends into a diff parser with a narrow permission key. All three paths end at the same comment bubble, showing that the action can produce one reliable PR note through multiple routes.
The core implementation is a fallback chain. If one route to the lockfile fails, another can still feed the same review comment.

The interesting bit is not just that it has fallbacks. It is that the fallbacks preserve the same product outcome. No matter which route succeeds, the reviewer gets one coherent note instead of a broken workflow.

getContent -> blob fallback -> diff parse

filter: wp-plugin/*
lookup: WordPress.org metadata
compare: installed version vs stable tag
output: one PR comment

Automatically comment WordPress plugin changelogs on pull requests when WP Packages dependencies change in your composer.lock or composer.json files.

Roots, Organization · roots/wp-packages-changelog-action

Why the stable-tag warning matters more than the changelog

The changelog is useful. The warning is the real feature. If the action sees that the installed version is ahead of the plugin’s stable tag, it calls that out immediately, right where the team is already reviewing the change.

SignalWhat it meansWhy it changes behavior
Changelog onlyYou can read the release notesYou still may assume the version is safe
Changelog plus stable-tag warningThe update may not be officially stable yetThe reviewer has a reason to pause before merging
No signalThe PR looks like any other dependency bumpThe hidden risk stays invisible

That is a narrow feature with a big effect. It turns a passive comment bot into a lightweight safety check for a workflow that normally assumes package versioning is honest.

Why Roots built this as a zero-build action

The repo keeps almost all of its logic in `action.yml` and uses `actions/github-script` to execute it. That choice cuts out a build pipeline, keeps the source readable, and makes the action easier to audit than a packaged bundle with compiled output.

runs:
  using: "node20"
  steps:
    - uses: actions/github-script@v7
      with:
        script: |
          // fetch lockfiles, query WordPress.org, post comment

For a small utility, that is a good trade. The code stays close to the behavior, contributors can reason about it quickly, and the action does not ask for more machinery than the problem needs.

Where it fits in the WordPress Composer ecosystem

This repo sits inside the Roots ecosystem, alongside WP Packages and the broader Bedrock-style effort to make WordPress development feel more like modern dependency management. It does not pretend the ecosystem is fully modern. It just makes one fragile step easier to review.

ToolWhat it watchesWhat it addsMain limitation
roots/wp-packages-changelog-actionWP Packages dependency changes in existing PRsChangelogs and unstable-version warningsOnly helps when a PR already touches the lockfile
DependabotOutdated dependencies across many ecosystemsAutomated update PRsBroader, but less specific to WordPress plugin review
Generic changelog generatorYour own repo historyRelease notes for your projectNot designed for third-party plugin metadata

That is the niche. It is not trying to replace dependency automation. It is trying to make a very specific kind of WordPress dependency change less mysterious.

What to use instead, and why this is different

If you want a bot that opens update PRs, Dependabot is still the default answer. If you want a changelog for your own project, a generic generator fits better. This action is narrower than both, and that narrowness is the point.

It lives exactly where the decision is made: in the pull request that is about to merge a plugin change. That is a better place for context than a separate dashboard or a distant release note page.

The takeaway

`roots/wp-packages-changelog-action` is small, but its opinion is clear. WordPress plugin updates should not just be fetched. They should be explained, checked, and made reviewable before they land.