diff --git a/docs/configuration.md b/docs/configuration.md index 76193803..c424d4b2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -266,7 +266,7 @@ Set to `false` to disable. | `mode` | `"root"` \| `"packages"` \| `"both"` | — | Where to write changelog files. root: repo root only. packages: per-package (monorepos). both: repo root and per-package. When omitted entirely (no changelog config), defaults to root. | | `file` | string | — | Changelog file name override (default: CHANGELOG.md) | | `refs` | `"strip"` \| `"escape"` \| `"link"` | `"link"` | How `#NNN` issue/PR refs in the changelog are rendered. Applies to the whole entry — both the appended label and any bare `#N` carried over from the commit subject into the description (a description ref that also appears in the appended label is de-duplicated away). 'link' (default): the PR and the issues it closed are labelled as `(PR #503 · closes #500)`, where the PR links to its canonical /pull/ URL with `PR #503` as the visible text — this keeps the GitHub hovercard but stops the bare-token rich inline card that duplicated the entry; closed issues link to /issues/. An entry with no identifiable PR (a non-squash commit, or a non-GitHub repo) falls back to a plain ref list. 'escape': plain text \\#NNN (no link, no hovercard, no PR/closes labelling). 'strip': refs are removed entirely. Scoped-package / @user mentions in entry text are always neutralised regardless of this setting. | -| `demoteScopes` | `string[]` | `["deps"]` | Conventional-commit scopes whose changelog entries are demoted into a trailing "Dependencies & version bumps" subsection instead of interleaving with Added / Fixed / Changed. Applies to the standing-PR changelogs — each releasable row and the "Show all changes" footer. Nothing is hidden or dropped: low-signal dependency bumps just stop crowding the user-facing changes at the top, and a reader who wants the exact per-package deps expands the subsection. The de-duplicated change count is unchanged. Default: ["deps"]. Set to [] to render every scope inline. | +| `demoteScopes` | `string[]` | `["deps","deps-dev"]` | Conventional-commit scopes whose changelog entries are demoted into a trailing "Dependencies & version bumps" subsection instead of interleaving with Added / Fixed / Changed. Applies to the standing-PR changelogs — each releasable row and the "Show all changes" footer. Nothing is hidden or dropped: low-signal dependency bumps just stop crowding the user-facing changes at the top, and a reader who wants the exact per-package deps expands the subsection. The de-duplicated change count is unchanged. Default: ["deps", "deps-dev"] (the scopes Dependabot uses for production and development bumps). Set to [] to render every scope inline. | **`notes.changelog.templates`** — Template configuration for changelog. diff --git a/packages/config/src/index.ts b/packages/config/src/index.ts index 6918b64b..2aa9f02b 100644 --- a/packages/config/src/index.ts +++ b/packages/config/src/index.ts @@ -20,6 +20,7 @@ export { type ChangelogConfig, type CIConfig, type CILabelsConfig, + DEFAULT_DEMOTE_SCOPES, type GitConfig, type GitHubReleaseConfig, type LLMCategory, diff --git a/packages/config/src/schema.ts b/packages/config/src/schema.ts index 74ec5df8..2a8418e1 100644 --- a/packages/config/src/schema.ts +++ b/packages/config/src/schema.ts @@ -12,6 +12,9 @@ import { z } from 'zod'; // schema:gen` (then `pnpm docs:config`). // --------------------------------------------------------------------------- +/** Dependabot's default commit scopes: `deps` for production bumps, `deps-dev` for development bumps. */ +export const DEFAULT_DEMOTE_SCOPES: readonly string[] = ['deps', 'deps-dev']; + export const GitConfigSchema = z.object({ remote: z.string().default('origin').describe('Git remote name'), branch: z.string().default('main').describe('Default branch name'), @@ -353,9 +356,9 @@ export const ChangelogConfigSchema = z ), demoteScopes: z .array(z.string()) - .default(['deps']) + .default([...DEFAULT_DEMOTE_SCOPES]) .describe( - 'Conventional-commit scopes whose changelog entries are demoted into a trailing "Dependencies & version bumps" subsection instead of interleaving with Added / Fixed / Changed. Applies to the standing-PR changelogs — each releasable row and the "Show all changes" footer. Nothing is hidden or dropped: low-signal dependency bumps just stop crowding the user-facing changes at the top, and a reader who wants the exact per-package deps expands the subsection. The de-duplicated change count is unchanged. Default: ["deps"]. Set to [] to render every scope inline.', + 'Conventional-commit scopes whose changelog entries are demoted into a trailing "Dependencies & version bumps" subsection instead of interleaving with Added / Fixed / Changed. Applies to the standing-PR changelogs — each releasable row and the "Show all changes" footer. Nothing is hidden or dropped: low-signal dependency bumps just stop crowding the user-facing changes at the top, and a reader who wants the exact per-package deps expands the subsection. The de-duplicated change count is unchanged. Default: ["deps", "deps-dev"] (the scopes Dependabot uses for production and development bumps). Set to [] to render every scope inline.', ), }) .describe('Changelog file configuration'); diff --git a/packages/release/src/standing-pr/changelog-region.ts b/packages/release/src/standing-pr/changelog-region.ts index c6bae0ea..30d52062 100644 --- a/packages/release/src/standing-pr/changelog-region.ts +++ b/packages/release/src/standing-pr/changelog-region.ts @@ -1,3 +1,4 @@ +import { DEFAULT_DEMOTE_SCOPES } from '@releasekit/config'; import { type ChangelogRefsMode, escapeChangelogMentions, @@ -220,17 +221,13 @@ function repoUrlOf(changelogs: VersionOutput['changelogs']): string | null { * the indent that nests the block under its row. It returns the collapsed `
` block, or `''` * when those packages have no real changelog entries. * - * The channel-section grouping regroups *where* rows are placed; it reuses this renderer unchanged - * to keep *how* changelogs attach to a row identical. `refs` (`changelog.refs`, default `'link'`) - * controls how bare `#NNN` - * refs render. `demoteScopes` (`changelog.demoteScopes`, default `['deps']`) routes matching- - * scope entries into a trailing "Dependencies & version bumps" subsection instead of interleaving - * them; the `(N entries)` count still counts every entry, demoted included. + * Channel-section grouping reuses this renderer, so changelogs attach to rows the same way everywhere. + * `refs` and `demoteScopes` come from `changelog.*`; demoted entries still count toward `(N entries)`. */ export function makeRowChangelogRenderer( changelogs: VersionOutput['changelogs'], refs: ChangelogRefsMode = 'link', - demoteScopes: readonly string[] = ['deps'], + demoteScopes: readonly string[] = DEFAULT_DEMOTE_SCOPES, ): RowChangelogRenderer { const byPkg = new Map(changelogs.map((cl) => [cl.packageName, cl])); const refOpts: RefRenderOptions = { refs, repoUrl: repoUrlOf(changelogs) }; @@ -292,5 +289,5 @@ export function renderCombinedFooter( ? `Show project-wide changes (${n} ${n === 1 ? 'change' : 'changes'})` : `Show all changes (${n} ${n === 1 ? 'change' : 'changes'}, de-duplicated)`; const refOpts: RefRenderOptions = { refs: opts.refs ?? 'link', repoUrl: repoUrlOf(versionOutput.changelogs) }; - return wrapDetails(summary, renderGrouped(deduped, refOpts, opts.demoteScopes ?? ['deps']), ''); + return wrapDetails(summary, renderGrouped(deduped, refOpts, opts.demoteScopes ?? DEFAULT_DEMOTE_SCOPES), ''); } diff --git a/packages/release/src/standing-pr/standing-pr.ts b/packages/release/src/standing-pr/standing-pr.ts index ef851697..4d124429 100644 --- a/packages/release/src/standing-pr/standing-pr.ts +++ b/packages/release/src/standing-pr/standing-pr.ts @@ -1,5 +1,5 @@ import * as fs from 'node:fs'; -import { type CIConfig, loadConfig as loadReleaseKitConfig } from '@releasekit/config'; +import { type CIConfig, DEFAULT_DEMOTE_SCOPES, loadConfig as loadReleaseKitConfig } from '@releasekit/config'; import type { VersionOutput, VersionPackageUpdate } from '@releasekit/core'; import { deriveReleaseChannel, @@ -938,7 +938,7 @@ export async function runStandingPRUpdate(options: StandingPROptions): Promise { expect(footer).toContain('_(a, b)_'); }); + // The row renderer and the footer each fall back to the default separately, so cover both. + it('should demote Dependabot deps-dev entries by default in rows and the combined footer', () => { + const changelogs = [ + cl('@scope/app', [ + { type: 'feat', description: 'App feature' }, + { type: 'changed', description: 'bump the development-dependencies group', scope: 'deps-dev' }, + ]), + ]; + const block = makeRowChangelogRenderer(changelogs)(['@scope/app'], false, ''); + expect(block).not.toContain('#### Changed'); + expect(block).toContain('#### Dependencies & version bumps'); + expect(block).toContain('- bump the development-dependencies group (`deps-dev`)'); + + const footer = renderCombinedFooter(output({ changelogs })); + expect(footer).not.toContain('#### Changed'); + expect(footer).toContain('#### Dependencies & version bumps'); + expect(footer).toContain('- bump the development-dependencies group'); + }); + it('should render every scope inline when demoteScopes is empty', () => { const render = makeRowChangelogRenderer( [cl('@scope/app', [{ type: 'changed', description: 'bump deps', scope: 'deps' }])], diff --git a/packages/release/test/unit/standing-pr.spec.ts b/packages/release/test/unit/standing-pr.spec.ts index 7b827bbf..0e33fdb6 100644 --- a/packages/release/test/unit/standing-pr.spec.ts +++ b/packages/release/test/unit/standing-pr.spec.ts @@ -90,6 +90,7 @@ vi.mock('node:fs', () => ({ })); vi.mock('@releasekit/config', () => ({ + DEFAULT_DEMOTE_SCOPES: ['deps', 'deps-dev'], loadCIConfig: vi.fn(), loadConfig: vi.fn().mockReturnValue({ ci: { standingPr: { branch: 'release/next', deleteBranchOnMerge: true } }, diff --git a/releasekit.schema.json b/releasekit.schema.json index c03844b9..e640f99e 100644 --- a/releasekit.schema.json +++ b/releasekit.schema.json @@ -640,12 +640,13 @@ "demoteScopes": { "type": "array", "default": [ - "deps" + "deps", + "deps-dev" ], "items": { "type": "string" }, - "description": "Conventional-commit scopes whose changelog entries are demoted into a trailing \"Dependencies & version bumps\" subsection instead of interleaving with Added / Fixed / Changed. Applies to the standing-PR changelogs — each releasable row and the \"Show all changes\" footer. Nothing is hidden or dropped: low-signal dependency bumps just stop crowding the user-facing changes at the top, and a reader who wants the exact per-package deps expands the subsection. The de-duplicated change count is unchanged. Default: [\"deps\"]. Set to [] to render every scope inline." + "description": "Conventional-commit scopes whose changelog entries are demoted into a trailing \"Dependencies & version bumps\" subsection instead of interleaving with Added / Fixed / Changed. Applies to the standing-PR changelogs — each releasable row and the \"Show all changes\" footer. Nothing is hidden or dropped: low-signal dependency bumps just stop crowding the user-facing changes at the top, and a reader who wants the exact per-package deps expands the subsection. The de-duplicated change count is unchanged. Default: [\"deps\", \"deps-dev\"] (the scopes Dependabot uses for production and development bumps). Set to [] to render every scope inline." } }, "description": "Changelog file configuration"