Skip to content

Package changelogs: Improve consistency and prevent future drift #81341

Open

Description

@ciampo

Follow-up to the #81331 discussion.

The goal is to make package changelogs useful to consumers and prevent new drift. This issue now separates work shipped on trunk from remaining implementation and policy decisions. Checked items describe completed work only; proposals remain unchecked.

Reassessed on 2026-10-01 against trunk 0771c7a7cf35. The current source check covers 124 package changelogs and schemas/CHANGELOG.md. Generated root changelog.txt remains out of scope. Historical npm-wide figures below have not been rerun and must not be read as current counts.

Work shipped since the original audit

  • #83043 documented the entry format and ordered categories, added npm run lint:changelogs and validator tests, split entry-presence checks from structure validation, and repaired selected current entries.
  • #83577 expanded the optional presence matrix to 35 packages, including published tooling and configuration packages.
  • #83618 refined presence-check exclusions for documentation, stories, tests, and development configuration. #82069 had already made changelog-only changes skip the presence check.
  • #82089 made npm publication verification and recovery resumable, including registry identity, dist-tags, remote branches/tags, and finalization/backports.
  • #81658 backfilled ESLint Plugin changelog entries, including two candidates from this audit.

1. Release sections and metadata

Publication recovery has improved, but it does not establish a complete changelog ledger or repair historical omissions.

  • Verify target npm versions, registry gitHead, and dist-tags during publication/recovery. Release: Make npm publication verification resumable #82089.
  • Push and verify release branches and package tags, preserving prepared state so interrupted publication can resume. Release: Make npm publication verification resumable #82089.
  • Make finalization and changelog/version-commit backports recoverable for latest and bugfix releases. Release: Make npm publication verification resumable #82089.
  • Decide whether changelogs list every published version or only releases with consumer-facing changes.
  • Extend release verification to compare expected package versions with changelog release headings, in addition to registry and Git metadata.
  • Define changelog handling for WordPress-targeted and branch-only releases. updatePackages() still explicitly skips changelog processing for WordPress-targeted releases.
  • Re-audit supported-branch gaps and repair those with reliable source data; obtain release-owner review for package paths absent from their target branches.
  • Define how empty releases are represented, for example _No consumer-facing changes._ if a complete ledger is intended.
  • Validate release versions, dates, duplicates, and ordering under the agreed release policy.

Source: package release implementation.

Original release audit, retained as historical evidence

The original audit used commit 8181ec4897c3, 125 package changelogs, and live npm metadata for 120 public packages. At that time:

  • Trunk and npm latest metadata were consistent.
  • Across 1,255 npm wp-X.Y dist-tag checks, 1,224 package versions had a matching branch manifest but no matching release heading.
  • Thirteen package/tag pairs pointed to branches without the package path.
  • Across npm history, 8,963 of 19,710 stable versions had no matching heading on trunk. This included old, branch-only, security, and pre-convention releases; it is not a request to add them all by hand.
  • There were 9,060 empty published-version sections, one duplicate release, six subsection headings using ##, seven missing dates, one nonstandard date, and three missing maintenance comments.
  • Block Library: Restore 8.19.19 release metadata #81331 repaired one release-metadata example.

These registry-wide and historical structure counts have not been refreshed. They establish the original scope, not today's release health.

2. Missing entries and source links

The reassessment searched each candidate's entire named changelog, including published releases. Of the original 52 package-entry candidates, three have implementing PR links and 49 still lack them. A missing link alone does not establish that a separate entry is needed.

Remaining candidates and source-link repairs

The original audit compared history after the 2026-07-29 package release with Unreleased. It reported 65 commits and 110 public-package touches without matching PR links after excluding private packages and mechanical migrations. Those are historical figures. The remaining candidate list is:

A file touch is not proof that every affected package needs a separate entry. Package owners should confirm the final list and prefer useful consumer descriptions.

The following implementing PR links are still absent from package changelogs: #81250, #79934, #81002, #81193, #81307, #81206, #80725, and #81130. The original audit identified the first five as missing source links and the last three as implementing PRs for issue-linked entries. Review the descriptions before deciding whether to add or consolidate entries.

The malformed outer parentheses for #80929 in Block Editor and #79792 in WP Build also remain. schemas/CHANGELOG.md is unchanged from the original snapshot and still has no versioned release ledger.

3. Documentation and CI coverage

Structure validation and entry presence are separate checks. A changed package changelog receives structure validation regardless of the presence allowlist. Presence checks remain optional and cover 35 hardcoded packages.

Sources: maintaining changelogs and CI workflow.

4. Validation and auto-fixes

Verified scope and limitations of the current validator

The validator passed all 124 package changelogs in the reassessed snapshot. That result only verifies its implemented rules. It does not establish complete entries, historical consistency, or release-metadata parity.

Focused probes confirmed that it accepts:

  • Different numeric PR labels and URL targets, such as [#123](https://github.com/WordPress/gutenberg/pull/456).
  • An entry lacking outer parentheses and terminal punctuation.
  • A changelog without Unreleased when no PR requirement is supplied.
  • Duplicate published release headings.

It rejects an unknown Features subsection and a recognized entry with only an issue link. Its PR-link regex checks syntax, not whether the PR exists or implements the described change.

The default command discovers only packages/*/CHANGELOG.md; CI also selects only package changelogs. schemas/CHANGELOG.md is excluded from both. For a selected file, validation covers its entire Unreleased section, not just added or modified lines. Published sections are otherwise outside structural validation, apart from current-PR placement checking.

Safe auto-fix candidates include agreed heading aliases, section ordering, duplicate subsection consolidation, spacing, matching PR labels, and canonical suffixes. Release-date repairs require known source data. Spelling fixes must avoid code spans and quoted misspellings. Semantic classification, consumer usefulness, affected-package coverage, consolidation, and security wording remain review responsibilities.

Source: validator.

5. Section names and categories

The shipped order is Stable Release, Breaking Changes, New Features, Enhancements, Deprecations, Bug Fixes, Internal, Documentation. This replaces the earlier proposed order in this issue. New APIs, Code Quality, Experimental, TypeScript, and Performance are not allowed Unreleased headings.

The release parser still accepts some older heading prefixes, including New API, but the validator's narrower documented list prevents those names in validated Unreleased sections. Classification must follow consumer impact, not keyword-based auto-fixes.

Historical category audit

The original snapshot had 2,471 subsection headings using 24 names, including 197 headings outside the originally proposed canonical set in 52 files. Sixty were simple naming variants; 137 used additional categories. There were 29 repeated subsection groups in 11 files.

These counts have not been refreshed against the shipped taxonomy. In particular, categories such as Documentation must now be judged against the documented current list, not treated as violations merely because the original audit listed them separately.

Suggested semantic review remains: classify performance changes as enhancements or regression fixes; classify published-type changes by their consumer effect; omit or use Internal for appropriate non-consumer work; describe experimental status in the entry instead of using an Experimental heading.

6. Entry format and spelling

The current snapshot contains 101 mismatched numeric PR labels and URL targets across package changelogs; 90 are the repeated #31270 label pointing to PR #61930. These are refreshed counts, compared with 103 and 92 in the original audit. The malformed suffixes for #80929 and #79792 remain.

Original formatting evidence and entry example
### Bug Fixes

-   `Component`: Fix the consumer-visible problem and state the resulting behavior ([#12345](https://github.com/WordPress/gutenberg/pull/12345)).

Describe public behavior, API, compatibility, or required consumer action. The imperative wording above is the original proposal; the shipped documentation specifies links and punctuation but does not prescribe that verb tense.

The original audit also reported 890 noncanonical PR suffixes, 16 broken parenthesized links, 18 bullet-spacing differences, 86 double-blank-line runs, and ten sibling-entry pairs with an extra blank line. These counts have not been refreshed.

Original spelling candidates included coniguration, intial, DatViews, sizs, cliking, chared, stings, othr, autocomple, ComoboboxControl, the the, and 0.8 .0. Recheck each occurrence before editing; quoted misspellings and code identifiers must be preserved.

7. Longer-term authoring workflow

Direct changelog edits remain the shipped workflow. Structured per-PR fragments are still a proposal and need not block incremental validator improvements.

  • Decide whether to pursue fragments as a separate follow-up.
  • If adopted, define package, category, consumer summary, and optional consolidation metadata.
  • Let CI supply the PR number automatically.
  • Support an explicit no-consumer-change decision without necessarily publishing it as an entry.
  • Compile canonical changelog sections on the correct release branch, including agreed backport handling.

Remaining decisions and sequencing

The entry template, current category list, and optional entry guidance have shipped. They no longer need to be treated as prerequisites for all implementation.

  1. Agree on coverage and exceptions before widening presence checks or requiring explicit no-consumer-change decisions.
  2. Agree on complete-ledger and empty-release policy before expanding release verification or repairing branch-only history.
  3. Extend the existing validator for confirmed syntax gaps, keeping mechanical fixes separate from semantic review.
  4. Review the remaining entry candidates and historical debt with package owners; refresh old audit counts before planning bulk cleanup.
  5. Treat fragments as a separate authoring-workflow decision.

Activity

  1. aduth commented on Oct 1, 2026

    @aduth
    Member

    There's a lot here, but I imagine that a lot of this will have improved by #83043.

  2. ciampo commented on Oct 1, 2026

    @ciampo
    ContributorAuthor

    Good point, I tweaed the issue description and tried to check all points that I feel have been addressed already

  3. talldan commented on Oct 7, 2026

    @talldan
    Contributor

    I'm supportive of required package changelogs, but the constant merge conflicts from the current workflow are too much friction.

    I think it's something that needs to be solved sooner rather than later. It is just not at all pleasant to work on the project while it's like this. Taking into account how time each contributor spends solving conflicts, it's time that could be better spent elsewhere.

    edit: Just to add, I am personally happy to work on improving it (e.g. switching to changelog fragments), but at the same time don't want to duplicate or cause issues with other work on changelogs.

  4. ciampo commented on Oct 7, 2026

    @ciampo
    ContributorAuthor

    I'm in favor of using fragments, but I wonder if this requires some form of consensus before moving forward. Should we just cc WordPress/gutenberg-core ?

  5. talldan commented on Oct 8, 2026

    @talldan
    Contributor

    There's a past discussion on the subject here in slack - https://wordpress.slack.com/archives/C02QB2JS7/p1718178158242679.

  6. ciampo commented on Oct 8, 2026

    @ciampo
    ContributorAuthor

    I guess we have consenus to at least propoase an approach in a PR. @talldan , are you going to own this initial exploration? In the past I had personally proposed https://github.com/changesets/changesets, but I don't have a strong preference.

  7. talldan commented on Oct 13, 2026

    @talldan
    Contributor

    I'm happy to look into it. The third party tools that came up in my search were:

    We'll need to think about rollout too. Maybe we experiment with one or two packages first? I think whatever we do, and whichever tool we use we shouldn't disregard how well it works in a monorepo.

  8. ciampo commented on Oct 13, 2026

    @ciampo
    ContributorAuthor

    I'd shortlist Changesets and Changie for the pilot. Changesets looks strongest for npm monorepo releases; Changie seems closer to fixing changelog conflicts while keeping our release process.

    I tasked an agent to prepare a quick comparison table
    Tool Fit for Gutenberg Maintenance and adoption
    Changesets Multi-package fragments, independent versions, and dependency updates. Best if versioning is also in scope. ~12.5k stars; September release; used by Astro and Chakra UI.
    Changie Custom categories/templates and multi-package authoring. We'd retain npm dependency management. ~0.9k stars; August release; used by Terraform and dbt-adapters.
    Towncrier Shared config, separate changelogs. Requires Python and per-package runs with explicit versions. ~0.9k stars; September release; used by pip, pytest, and Twisted.

    Checked on 13 October 2026; release months refer to 2026. Since 15 July, Changesets and Towncrier show broader contributor activity; Changie relies mainly on its creator. I'd weigh that risk without ruling it out. Stars alone don't establish reliability or future support, as Towncrier's established adoption illustrates.

    The main catch is preserving our release rules: categories determine version bumps, with release-wide minimums and special handling for 0.x promotion. Changesets would need integration here.

    I'd test both with a change spanning two packages, different version bumps, a backport, and a release with no new entry. I'd also check fragment readability and migration. This is based on docs and source; I'd choose after the pilot.

    Other options worth considering
    Option Fit Maintenance and adoption
    Beachball npm fragments and grouped changes. Compare with Changesets for release automation. ~0.8k stars; September release; used by Fluent UI. Recent development mainly involves one contributor.
    Jetpack Changelogger Custom categories and version-bump metadata. PHP/Composer is less natural for our JS packages. Used in Jetpack's monorepo; September updates. Judge the main repo, not mirror stars.
    Release Please Monorepo release PRs, but Conventional Commits make it less suited to fragments. ~7.6k stars; Google-maintained; August release.
  9. talldan commented on Oct 15, 2026

    @talldan
    Contributor

    I did some diving into this today. I lean towards trying out Changie. It seems to fit better with our existing workflows. It's more of a minimal tool, so:

    • It's easy enough to migrate and keep our history
    • We can map change 'kinds' to semver bumps, so we can keep our existing system and it'll auto calculate version bumps:
    kinds:
      - label: Enhancement
        auto: minor
      - label: Bug Fix
        auto: patch
    
    • It supports monorepos, though it's through an explicit config. That might make gradual adoption easier, but it's some maintenance.
    • Good support for customization - components (as in a way to further categorize changelogs), templates and custom fields

    Some shortcomings:

    • Gutenberg typically bumps packages by minor version by default, and only patch version for hotfix releases. There's no config option for this, but we can force our own version number, so we could get changie to auto calculate a version number and then use a minumum minor version.
    • It uses changelog versions as the source of truth, but we'd really want package.json version to be the source of truth. There's a risk of the two becoming out of sync. Again we can force a version number if we detect a mismatch.
    • The 'Stable release' kind is a little harder to support, but not impossible.

    So far I think we can workaround the shortcomings. I think we could propose/work on some upstream changes too that are mutually beneficial.

    I looked at changesets too. It does have some cool features, but I think it's too much of a shift. It requires only 'major', 'minor', and 'patch' kinds of changes (example - https://github.com/changesets/changesets/blob/main/packages/cli/CHANGELOG.md), and it's more deeply integrated into the release process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions