[changelog] header = """ # Changelog\n """ body = """ {% if version %}\ ## [{{ version }}] — {{ timestamp | date(format="%Y-%m-%d") }} {% else %}\ ## [Unreleased] {% endif %}\ {% for group, commits in commits | group_by(attribute="group") %} ### {{ group | striptags | trim }} {% for commit in commits %} - {{ commit.message | split(pat="\n") | first | trim }}\ {% endfor %} {% endfor %}\n """ trim = true [git] conventional_commits = true filter_unconventional = true split_commits = false protect_breaking_commits = false filter_commits = false # Only final tags count as releases — rc rehearsal tags must not become # section boundaries, or the final tag's notes would cover only # commits-since-last-rc (v0.1.0 rendered 0 commits with ignore_tags, which # drops rc-tagged commits instead of folding them forward). With rc tags # outside the pattern, finals render the full span and rc tags render # [Unreleased] with everything pending. Verified empirically on both. tag_pattern = 'v[0-9]+\.[0-9]+\.[0-9]+$' topo_order = false sort_commits = "oldest" commit_parsers = [ { message = "^feat", group = "Added" }, { message = "^fix", group = "Fixed" }, { message = "^perf", group = "Changed" }, { message = "^refactor", group = "Changed" }, { message = "^security", group = "Security" }, { message = "^polish", group = "Changed" }, { body = "BREAKING", group = "Breaking" }, { footer = "BREAKING.CHANGE", group = "Breaking" }, { message = "^docs", skip = true }, { message = "^style", skip = true }, { message = "^chore", skip = true }, { message = "^ci", skip = true }, { message = "^test", skip = true }, { message = "^build", skip = true }, ]