python-semantic-release / python-semantic-release

Automating Releases via SemVer and Commit Message Conventions
https://python-semantic-release.readthedocs.io/en/stable/
MIT License
827 stars 249 forks source link

How to generate a CHANGELOG like version 7 and below? #982

Open GiamBoscaro opened 4 months ago

GiamBoscaro commented 4 months ago

I have upgraded my libraries and upgrade semantic-release to the latest version 9.8.5. I was coming from version 7 before. Everything is working correctly after some tweaks, but the CHANGELOG generation is much worse than before in my opinion. Any suggestion on how to improve this?

Example:

Old CHANGELOG

Paragraphs based on commit (feat, fix, docs etc) Module in Bold (core, auth, users) One long list of changes for every version

# Changelog

<!--next-version-placeholder-->

## v1.16.0 (2024-07-04)

### Feature

* **users:** something something [CSR-1234] ([`4bcca39`](https://github.com/....))
* **auth:** something something [CSR-1235] ([`98c011e`](https://github.com/....))

## v1.15.0 (2024-06-14)

### Feature

* **core:** something something [CSR-1235] ([`98c011e`](https://github.com/....))

### Documentation

* **core:** something something [CSR-1235] ([`98c011e`](https://github.com/....))

New CHANGELOG:

Paragraphs based on commit (feat, fix, docs etc) Module are not in bold (core, auth, users) Mixed up pre releases with full releases, very confused

# CHANGELOG

## v1.1.0 (2024-07-18)

## v1.1.0-rc.1 (2024-07-18)

### Feature

* fix(users): fixed users API [CSR-11111] ([`73a1823`](https://bitbucket.org/git/scm/...))

## v1.0.0 (2024-07-18)

## v1.0.0-rc.2 (2024-07-18)

### Feature

* feat(users): added users API [CSR-2222] ([`fa91e5a`](https://bitbucket.org/git/scm/...))

## v1.0.0-rc.1 (2024-07-18)

## v0.0.0-rc.1 (2024-07-18)
wyardley commented 4 months ago

I had a similar situation (and in fact, I added some of the behavior in 7.x). Maybe check out #952 and #953 - I posted a custom template I'm using there that does at least some of what I think you're looking for; sounds like we may have to wait for a major for some bigger changes. (I also updated my template snippet to include some spacing tweaks made since I first added it).

But the meat of what I'm doing is like this... would be nice if there were a slightly less messy way to handle the scopes.

* {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.descriptions[0] }} ([`{{ commit.short_hash }}`]({{ commit.hexsha | commit_hash_url }}))

Someone more adept at Jinja than me could probably also write little macros / functions that can be shared between the changelog / release notes, and reused within templates, to make it a little more readable.

GiamBoscaro commented 4 months ago

I had a similar situation (and in fact, I added some of the behavior in 7.x). Maybe check out #952 and #953 - I posted a custom template I'm using there that does at least some of what I think you're looking for; sounds like we may have to wait for a major for some bigger changes. (I also updated my template snippet to include some spacing tweaks made since I first added it).

But the meat of what I'm doing is like this... would be nice if there were a slightly less messy way to handle the scopes.

* {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.descriptions[0] }} ([`{{ commit.short_hash }}`]({{ commit.hexsha | commit_hash_url }}))

Someone more adept at Jinja than me could probably also write little macros / functions that can be shared between the changelog / release notes, and reused within templates, to make it a little more readable.

Thank you! I couldn't see you templates but I have downloaded this CHANGELOG.angular.md.j2 and with that the CHANGELOG looks better already (the md preview is good but the actual md file is badly formatted with huge spaces between lines, don't know why).

Anyway, one other behaviour that I would like to understand is this:

The npm library of semantic-release generates the CHANGELOG based on the branch I am in. So if I am in main, it is going to generate a CHANGELOG based only on full releases. This creates a very clean file with only full releases. If I am on stage or qa, it generates a CHANGELOG based only on stage releases (rc). This creates a very clean file showing changes only for rc (I call it BETA_CHANGELOG).

In case of the python semantic-release library, this generates a single CHANGELOG and puts all the prereleases and full releases together (you can see that in the second example on the OP). Basically, when I do a full release I will NOT have a list of changes for the full version (let's say 1.2.0), but I will have a long list of prereleases (1.2.0-rc1, rc2 etc) and for each the changes of that particular prereleases. Then at the top I will just have the title ## v1.2.0 (2024-07-18), wrapping all the prereleases together. I would like to have a CHANGELOG like my first example when I am in main. I do not want to see any prerelease, just list all the changes since the last full release!

codejedi365 commented 4 months ago

@GiamBoscaro, yes, I agree, I have fix in the works to improve the issue with prereleases all being inside of the full changelog. Thank you for your description of you desired outcome.

GiamBoscaro commented 4 months ago

@GiamBoscaro, yes, I agree, I have fix in the works to improve the issue with prereleases all being inside of the full changelog. Thank you for your description of you desired outcome.

Thank you!

There is also some other things that are different from npm semantic- release. I do not know if it is the right place to talk about this, but I have seen that any prerelease from any branch is considered the same prerelease during versioning. What I mean is: I have a prerelease tagged like 1.2.0-dev.3 from dev branch, I merge dev into stage. Semantic release will run and will not release a 1.2.0-rc.1, but will skip it because since the latest prerelease no relevant commits were pushed (indeed there was only a PR merged). This is different from npm semantic release since there all the branches are considered different and semantic release with actually push a prerelease in this case.

codejedi365 commented 4 months ago

Yes, this is a bug discussed in #789.

codejedi365 commented 3 months ago

but I have downloaded this CHANGELOG.angular.md.j2 and with that the CHANGELOG looks better already (the md preview is good but the actual md file is badly formatted with huge spaces between lines, don't know why).

That file from my PR was a draft. Obviously I hadn't finished the spacing created by my attempt to make it more readable with syntax formatting. I recently found out that you can use a hyphen at the end of a closure (-}}) to have jinja consume the newline character thanks to @wyardley.

GiamBoscaro commented 3 months ago

but I have downloaded this CHANGELOG.angular.md.j2 and with that the CHANGELOG looks better already (the md preview is good but the actual md file is badly formatted with huge spaces between lines, don't know why).

That file from my PR was a draft. Obviously I hadn't finished the spacing created by my attempt to make it more readable with syntax formatting. I recently found out that you can use a hyphen at the end of a closure (-}}) to have jinja consume the newline character thanks to @wyardley.

Sure I know it is a draft. No complaint. The md rendering is good enough for me at the moment.

t11c commented 2 months ago

Hi, had the same problem got the spaces removed, heres my current CHANGELOG.md.j2 It also includes the commit body, each line is a bullet point.

# CHANGELOG

{% if context.history.unreleased | length > 0 %}
## Unreleased
{% for type_, commits in context.history.unreleased | dictsort if type_ != "unknown" -%}
### {{ type_ | capitalize }}
{%- for commit in commits if type_ != "unknown" %}
{% if commit.scope -%}
- **{{ commit.scope }}**: {{ commit.descriptions[0] }} ([`{{ commit.short_hash }}`]({{ commit.hexsha | commit_hash_url }}))
{% else -%}
- {{ commit.descriptions[0] | capitalize }} ([`{{ commit.short_hash }}`]({{ commit.hexsha | commit_hash_url }}))
{% endif %}
{%- if commit.descriptions | length > 1 %}
  {%- for description in commit.descriptions[1:] %}
    - {{ description }}
  {%- endfor %}
{%- endif %}
{%- if commit.breaking_descriptions | length > 0 %}
    **BREAKING CHANGES:** {{ commit.breaking_descriptions | join(" ") }}
{%- endif %}
{%- endfor %}
{% endfor %}
{% endif %}

{% for version, release in context.history.released.items() -%}
## {{ version.as_semver_tag() }} ({{ release.tagged_date.strftime("%Y-%m-%d") }})
{%- for type_, commits in release["elements"] | dictsort if type_ != "unknown" %}
### {{ type_ | capitalize }}
{%- for commit in commits if type_ != "unknown" %}
{% if commit.scope -%}
- **{{ commit.scope }}**: {{ commit.descriptions[0] }} ([`{{ commit.short_hash }}`]({{ commit.hexsha | commit_hash_url }}))
{% else -%}
- {{ commit.descriptions[0] | capitalize }} ([`{{ commit.short_hash }}`]({{ commit.hexsha | commit_hash_url }}))
{% endif %}
{%- if commit.descriptions | length > 1 %}
  {%- for description in commit.descriptions[1:] %}
    - {{ description }}
  {%- endfor %}
{%- endif %}
{%- if commit.breaking_descriptions | length > 0 %}
    **BREAKING CHANGES:** {{ commit.breaking_descriptions | join(" ") }}
{%- endif %}
{%- endfor %}
{% endfor %}
{%- if "breaking" in release["elements"] %}
### BREAKING CHANGES
{%- for type_, commits in release["elements"] | dictsort if type_ == "breaking" %}
{%- for commit in commits %}
{% if commit.breaking_descriptions | length > 0 -%}
{% if commit.scope -%}
- **{{ commit.scope }}**: {{ commit.breaking_descriptions | join("\n\n") | capitalize }}
{% else -%}
- {{ commit.breaking_descriptions | join("\n\n") | capitalize }}
{% endif %}
{% endif %}
{%- endfor %}
{%- endfor %}
{% endif %}
{% endfor %}