Skip to content

fix(cliff): render commit body lists and drop repository artifacts - #31

Open
ThetaSinner wants to merge 6 commits into
mainfrom
fix/cliff-changelog-artifacts
Open

fix(cliff): render commit body lists and drop repository artifacts#31
ThetaSinner wants to merge 6 commits into
mainfrom
fix/cliff-changelog-artifacts

Conversation

@ThetaSinner

@ThetaSinner ThetaSinner commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

  • Lists in a commit body keep their structure instead of being flattened onto one line. The template joined every newline in a paragraph into a space and could not tell a list item from a hard-wrapped continuation.
  • The # Conflicts: block git leaves behind after a conflicted rebase is no longer published as a release note.
  • Rebase artifacts that ended up as commit subjects, such as # This is a combination of 2 commits. and --fixup=<sha>, are dropped rather than grouped under Other Changes.
  • A first-time contributor whose handle could not be resolved is left out of the list entirely, instead of rendering as @ made their first contribution. If that leaves no named contributors at all, the ### First-time Contributors heading is dropped too rather than standing over an empty list.
  • upper_first no longer applies to list items, where it was capitalising identifiers: iroh-relay 1.0: became Iroh-relay 1.0:, own_url_for_preflight() became Own_url_for_preflight().

All five were visible in the kitsune2 0.5.0 notes.

Checked against kitsune2's full history and against hc-http-gw, hc-chc-service and hc-spin-rust-utils. The last is byte-identical to the old output; the other two change only as described above.

The suite was not run in CI at all, so nothing checked this configuration. Most of it needs a Git server and a crate registry, but changelog generation is local, so the rendering test is split into its own target and the workflow now runs it. It was verified to fail against the previous configuration.

The formatting commit is pre-existing drift, kept separate.

Before merging

prepare-release.yml fetches this file from refs/heads/main, so merging takes effect for every repository's next release immediately, with no version pinning.

Generated changelogs had four problems, all visible in released notes:

- Multi-line lists in a commit body were flattened onto a single line,
  because the template joined every newline in a paragraph into a space
  and could not tell a list item from a hard-wrapped continuation. List
  items are now marked during preprocessing and rendered as a nested
  list, with continuation lines joined back onto their item.
- The "# Conflicts:" block that git leaves behind after a conflicted
  rebase was published as a release note.
- Rebase artifacts that ended up as commit subjects, such as
  "# This is a combination of 2 commits." and "--fixup=<sha>", were
  grouped under Other Changes.
- A first-time contributor whose handle could not be resolved rendered
  as "@ made their first contribution".

upper_first is no longer applied to list items. It was capitalising
identifiers, turning "iroh-relay 1.0:" into "Iroh-relay 1.0:" and
"own_url_for_preflight()" into "Own_url_for_preflight()".
Locks in the behaviour fixed in the previous commit: list structure in a
commit body, joining hard-wrapped lines, leaving list items as the author
wrote them, dropping git comment lines, and skipping rebase artifacts.

Verified to fail against the previous configuration, so it is a genuine
regression test rather than a description of current behaviour.

The test does not push, because changelog generation is entirely local.
That means it runs without the Gitea and registry services, unlike the
rest of this file.
Pre-existing formatting drift, unrelated to the changelog configuration
changes on this branch. Committed separately so it does not obscure them.
The suite was not run in CI at all, so nothing checked the changelog
configuration. Most of these tests need a Git server and a crate registry,
which this workflow does not provide, but changelog generation is entirely
local and needs neither.

Move the rendering test into its own file so the workflow can select it by
target rather than by test name, and so a future rendering test is picked up
without also having to remember to edit the workflow.
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ThetaSinner, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 5 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e77d9134-9827-4358-81c5-4e9cc28c90b5

📥 Commits

Reviewing files that changed from the base of the PR and between 79286c3 and 4eb1097.

📒 Files selected for processing (2)
  • crates/integration/tests/changelog_rendering.rs
  • pre-1.0-cliff.toml

Walkthrough

Updated git-cliff preprocessing and templates to normalize and render commit bodies, including nested lists, wrapped paragraphs, contributor sections, and filtered artifacts. Added an integration test covering these rendering cases and a workflow step to run it independently. Reformatted unchanged release utility expressions and warning text.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main changelog rendering fix and artifact filtering changes.
Description check ✅ Passed The description matches the changelog rendering fixes, regression test, and CI updates in the changeset.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cliff-changelog-artifacts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
crates/integration/tests/changelog_rendering.rs (1)

38-40: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a nested-list fixture.

This only tests a continuation line. Add an indented child bullet and assert its deeper output indentation; the current preprocessor flattens nested bullets.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/integration/tests/changelog_rendering.rs` around lines 38 - 40, Extend
the changelog fixture in the relevant rendering test to include an indented
nested child bullet, then update assertions to verify the child preserves deeper
output indentation rather than being flattened. Keep the existing
continuation-line coverage and use the current changelog preprocessing/rendering
test flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pre-1.0-cliff.toml`:
- Line 98: Update the list-item preprocessing rule in pre-1.0-cliff.toml so it
preserves each item's leading indentation in the marker representation, and
ensure the template renders that depth as corresponding indentation. In
crates/integration/tests/changelog_rendering.rs, extend the changelog rendering
fixture with a parent and nested child list item, then assert the rendered child
remains nested.
- Line 109: Update the hash-prefixed matcher in the configuration to match only
the known squash-artifact format rather than every subject beginning with “#”.
Preserve legitimate subjects such as “#123: fix startup” when
filter_unconventional is false, and keep the existing skip behavior for actual
squash artifacts.

---

Nitpick comments:
In `@crates/integration/tests/changelog_rendering.rs`:
- Around line 38-40: Extend the changelog fixture in the relevant rendering test
to include an indented nested child bullet, then update assertions to verify the
child preserves deeper output indentation rather than being flattened. Keep the
existing continuation-line coverage and use the current changelog
preprocessing/rendering test flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 944d2149-90ea-431a-b430-b41710d09d91

📥 Commits

Reviewing files that changed from the base of the PR and between 6d27c17 and 79286c3.

📒 Files selected for processing (6)
  • .github/workflows/test.yaml
  • crates/integration/src/lib.rs
  • crates/integration/tests/changelog_rendering.rs
  • crates/release_util/src/lib.rs
  • crates/release_util/src/prepare_release.rs
  • pre-1.0-cliff.toml

Comment thread pre-1.0-cliff.toml
Comment thread pre-1.0-cliff.toml Outdated
@cocogitto-bot

cocogitto-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

❌ Found 4 compliant commit and 2 non-compliant commits in babad90...4eb1097.

Commit 979194c by @ThetaSinner is not conform to the conventional commit specification :

  • message: fixup! fix(cliff): render commit body lists and drop repository artifacts
  • cause:
    Missing commit type separator `:`
    
    Caused by:
         --> 1:7
          |
        1 | fixup! fix(cliff): render commit body lists and drop repository artifacts
          |       ^---
          |
          = expected type_separator
    

Commit 4eb1097 by @ThetaSinner is not conform to the conventional commit specification :

  • message: fixup! ci: run the changelog rendering tests
  • cause:
    Missing commit type separator `:`
    
    Caused by:
         --> 1:7
          |
        1 | fixup! ci: run the changelog rendering tests
          |       ^---
          |
          = expected type_separator
    

@ThetaSinner
ThetaSinner requested a review from a team July 28, 2026 14:48

@cdunster cdunster left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments but looks good

Comment on lines +3 to +5
//! Unlike the other tests in this crate, nothing here pushes to a remote or publishes a crate,
//! because changelog generation is entirely local. That means this file, and only this file, can
//! run without the Gitea and registry services, so CI runs it on every pull request.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Some of this seems like it might become stale; maybe something like:

Suggested change
//! Unlike the other tests in this crate, nothing here pushes to a remote or publishes a crate,
//! because changelog generation is entirely local. That means this file, and only this file, can
//! run without the Gitea and registry services, so CI runs it on every pull request.
//! The tests in this module must not rely on external services so that they can be run locally and
//! in CI.

Comment on lines +18 to +20
///
/// Unlike the other tests in this file, this one never pushes, because changelog generation is
/// purely local. That keeps it runnable without the Gitea and registry services.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that "file" here is a typo, but I also think that this paragraph can just be removed as it's covered by the module description.

Suggested change
///
/// Unlike the other tests in this file, this one never pushes, because changelog generation is
/// purely local. That keeps it runnable without the Gitea and registry services.

/// Unlike the other tests in this file, this one never pushes, because changelog generation is
/// purely local. That keeps it runnable without the Gitea and registry services.
#[test]
fn commit_body_rendering() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend splitting each of these into separate tests so we can more easily see if a single feature breaks. I do also get wanting to test a larger file though, so it's not a strong request.

" - Some lead-in prose that is hard wrapped over two lines:
- an item that is itself hard wrapped onto a second line
- rcgen 0.14: CertifiedKey::key_pair renamed to signing_key
- A trailing paragraph after the list."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This trailing paragraph renders as if it is a separate item/commit. This could be a problem, as I've seen some commits that write this as a continuation, e.g.

The commit:

feat: Some feature that changes the API to add a field `foo`

This is because `bar()` needs it.
## Features

- Some feature that changes the API to add a field `foo`
- This is because `bar()` needs it.

Now the body that was adding more detail seems like a new item and doesn't make sense.

// The Other Changes group itself is not checked for absence. It legitimately holds the
// issue-reference subject above, which is an unconventional commit rather than an artifact.
// The assertions above already establish that no artifact reaches the changelog at all.
}

@cdunster cdunster Aug 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd quite like to see a test for rendering breaking changes with a reason, so a commit message like:

feat!: added the `foo` field to the `Bar` struct

The `foo` field is required by the following callers:

- `use_foo_1()`
- `use_foo_2()`

BREAKING CHANGE: This is a change to the public API, and all callers now need to handle `foo`.

This would hopefully render as something like:

- [**BREAKING**] Added the `foo` field to the `Bar` struct
    - The `foo` field is required by the following callers:
        - `use_foo_1()`
        - `use_foo_2()`
    - **Breaking Change**: This is a change to the public API, and all callers now need to handle `foo`.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants