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.
- The action is less about generating changelogs than making WordPress plugin updates legible inside pull request review.
- Its stability warning is the sharpest feature because it catches updates that look normal in a lockfile but are ahead of WordPress.org’s stable tag.
- The implementation is unusually resilient for a small utility because it falls back through multiple ways of reading `composer.lock` before giving up.
- Roots built it as a zero-build action so the source stays easy to inspect, easy to modify, and easy to trust.
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.
| Workflow | What you learn | What you still do not know |
|---|---|---|
| Plain composer.lock diff | Which package version changed | Whether the plugin release is stable or risky |
| PR comment with changelog | What changed in the plugin release | Whether the installed version matches the official stable tag |
| Manual review of WordPress.org | Release notes and tags | You 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.
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
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.
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.
| Signal | What it means | Why it changes behavior |
|---|---|---|
| Changelog only | You can read the release notes | You still may assume the version is safe |
| Changelog plus stable-tag warning | The update may not be officially stable yet | The reviewer has a reason to pause before merging |
| No signal | The PR looks like any other dependency bump | The 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.
| Tool | What it watches | What it adds | Main limitation |
|---|---|---|---|
| roots/wp-packages-changelog-action | WP Packages dependency changes in existing PRs | Changelogs and unstable-version warnings | Only helps when a PR already touches the lockfile |
| Dependabot | Outdated dependencies across many ecosystems | Automated update PRs | Broader, but less specific to WordPress plugin review |
| Generic changelog generator | Your own repo history | Release notes for your project | Not 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.





