Skip to content

release: a breaking commit of an unconfigured type hoists a raw lowercase heading above Features #437

Description

@IgorShevchik

Environment

main @ 28677edf, release-please-config.json. Generalises a case found while reviewing #435.

Description

changelog-sections replaces the preset's type list wholesale, so a type absent from ours has no entry. For a non-breaking commit that means it is dropped, which is #434's territory. For a breaking one it means something worse: the commit survives, but unlabelled.

Two lines in conventional-changelog-conventionalcommits@6.1.0's writer-opts.js produce it:

commit.notes.forEach(note => { note.title = 'BREAKING CHANGES'; discard = false })
if (discard && (entry === undefined || entry.hidden)) return
if (entry) commit.type = entry.section

A breaking note sets discard = false, so the commit is not dropped. But the section rewrite is guarded by if (entry) — with no entry, commit.type stays the raw type string and becomes the group title. Group order comes from commitGroupOrder.indexOf(title), which returns -1 for an unknown title, sorting it above index 0:

### ⚠ BREAKING CHANGES
* style! breaks things

### style                     ← raw lowercase type, above everything
* a breaking style commit …

### Features
…

Scope: twelve types, not one

This was noticed via style, but style is not the problem. Types used in this history with no entry in changelog-sections:

type commits
playground 31
doc 23
style 22
playgrounds 12
cli 6
demo 2
core, ai 1 each

plus typo'd subjects (ix, hore, feal, eat).

Not currently live

All 30 breaking commits in this history are of configured types — fix 15, feat 12, refactor 2, chore 1 — so nothing published has ever rendered this way. It is the same bar #434 was fixed at: no occurrence yet, and the first one would be wrong.

Options

  1. Add hidden entries for the types that can plausibly recur. { "type": "style", "section": "Chore", "hidden": true } keeps normal commits out of the changelog (as the preset intends) while giving breaking ones a real section instead of a raw heading. Cheap, but whack-a-mole across twelve types, most of which look like scopes misused as types and are long disused.
  2. Accept it and guard the input instead. No PR-title lint exists here — no commitlint, no semantic-pull-request action — and since the repo squash-merges, the PR title becomes the subject unvalidated. A title check would stop unconfigured types at the door and also close the typo cases, which no config list can catch.
  3. Do nothing, deliberately, and record why.

Option 2 looks like the one that actually retires the class rather than the instance, and it would have prevented feal(init) Init All and ix too.

Additional context

Found by an independent review pass over #435, which corrected the mistaken claim that omitting a default-hidden type is equivalent to listing it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions