cc @dblock — would love your opinion on the direction here before anyone writes code.
Problem
Every PR has to add a line to CHANGELOG.md under Next Release (enforced by Dangerfile's changelog.check!). With the current volume of PRs, that single shared section is a constant source of merge conflicts and forced rebases — a PR that was green yesterday needs a rebase today purely because another PR touched the same CHANGELOG region. The conflicts are never semantically interesting; they're pure coordination cost.
Proposal
Adopt a changelog-fragment model (the towncrier idea), but implemented as a dependency-free Ruby rake task — no Python, no API tokens, no new toolchain in a Ruby gem.
Per PR — instead of editing CHANGELOG.md, add one file:
changelog/2723.feature.md
Deprecate passing a positional options Hash to `Grape::DSL::Desc#desc` - [@ericproulx]
The filename carries the PR number and the type (feature → #### Features, fix → #### Fixes, extensible to deprecation/perf/breaking). The body keeps our curated, attributed prose. Since every PR adds a distinct file, two PRs never conflict.
CI / Danger — replace changelog.check! with a rule that fails the PR unless it adds a changelog/*.md fragment, plus a rake changelog:check that validates filenames.
Release — bundle exec rake changelog:build collects the fragments, groups/sorts them, rewrites the ### x.y.z (Next) block into a dated release section in the existing Grape format (* [#NNNN](…/pull/NNNN): … - [@author].), inserts a fresh empty (Next) header, and deletes the consumed fragments — all in the single release commit. CHANGELOG.md then only ever changes at release time.
Net effect: curated/attributed entries are preserved, day-to-day PRs stop conflicting, and the release diff stays clean.
Alternatives considered
- towncrier (Python) — mature and proven, but adds a Python + towncrier dependency to a Ruby project's CI/release flow.
- github_changelog_generator — no fragment files, but derives entries from PR titles/labels (loses our hand-written attributed style) and needs a GitHub API token in CI.
Open questions for @dblock
- Direction: comfortable with the dependency-free Ruby rake task, or do you'd prefer real towncrier / something else?
- Fragment types/sections — keep it to
feature/fix to match today, or seed deprecation/perf/breaking now?
- Migration of the current unreleased
3.3.0 (Next) entries: back-fill ~30 fragments so the system is consistent immediately, or leave them as text and only fragment forward?
- Any concern about changing the long-standing CONTRIBUTING workflow (lines 83–85 / 123–125)?
Happy to put up a PR once there's agreement on the approach. Concrete recent example of the friction: #2723.
cc @dblock — would love your opinion on the direction here before anyone writes code.
Problem
Every PR has to add a line to
CHANGELOG.mdunder Next Release (enforced byDangerfile'schangelog.check!). With the current volume of PRs, that single shared section is a constant source of merge conflicts and forced rebases — a PR that was green yesterday needs a rebase today purely because another PR touched the same CHANGELOG region. The conflicts are never semantically interesting; they're pure coordination cost.Proposal
Adopt a changelog-fragment model (the towncrier idea), but implemented as a dependency-free Ruby rake task — no Python, no API tokens, no new toolchain in a Ruby gem.
Per PR — instead of editing
CHANGELOG.md, add one file:The filename carries the PR number and the type (
feature→#### Features,fix→#### Fixes, extensible todeprecation/perf/breaking). The body keeps our curated, attributed prose. Since every PR adds a distinct file, two PRs never conflict.CI / Danger — replace
changelog.check!with a rule that fails the PR unless it adds achangelog/*.mdfragment, plus arake changelog:checkthat validates filenames.Release —
bundle exec rake changelog:buildcollects the fragments, groups/sorts them, rewrites the### x.y.z (Next)block into a dated release section in the existing Grape format (* [#NNNN](…/pull/NNNN): … - [@author].), inserts a fresh empty(Next)header, and deletes the consumed fragments — all in the single release commit.CHANGELOG.mdthen only ever changes at release time.Net effect: curated/attributed entries are preserved, day-to-day PRs stop conflicting, and the release diff stays clean.
Alternatives considered
Open questions for @dblock
feature/fixto match today, or seeddeprecation/perf/breakingnow?3.3.0 (Next)entries: back-fill ~30 fragments so the system is consistent immediately, or leave them as text and only fragment forward?Happy to put up a PR once there's agreement on the approach. Concrete recent example of the friction: #2723.