Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use towncrier for changelog generation #6974

Merged
merged 8 commits into from
Jul 17, 2022
Merged

Conversation

DudeNr33
Copy link
Collaborator

@DudeNr33 DudeNr33 commented Jun 18, 2022

  • Write a good description on what the PR does.
  • Add an entry to the change log describing the change in
    doc/whatsnew/2/2.15/index.rst (or doc/whatsnew/2/2.14/full.rst
    if the change needs backporting in 2.14). If necessary you can write
    details or offer examples on how the new change is supposed to work.
  • If you used multiple emails or multiple names when contributing, add your mails
    and preferred name in script/.contributors_aliases.json

Type of Changes

Type
📜 Docs

Description

Draft for using towncrier to generate the release notes.
Feedback is welcome.

Things that need to be discussed:

Things I still need to implement:

  • Automatically update towncrier.toml with a tbump script - I would like to wait for feedback first before doing that.

Things that have to be done before merging:

  • extract all current changelog entries into news fragments

@coveralls
Copy link

coveralls commented Jun 18, 2022

Pull Request Test Coverage Report for Build 2686032977

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 95.246%

Totals Coverage Status
Change from base Build 2681565721: 0.0%
Covered Lines: 16808
Relevant Lines: 17647

💛 - Coveralls

@@ -11,3 +11,4 @@ pytest-xdist~=2.5
# Type packages for mypy
types-pkg_resources==0.1.3
tox>=3
towncrier~=21.9
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would include the dependency here so that contributors can actually use the towncrier create command.

@Pierre-Sassoulas
Copy link
Member

The check on the pr number is possible in GitHub actions because GitHub actions have access to it. That's why I wanted to change that. If towncrier is doing the check for the change description another way I'd prefer keeping the consistency with the previous changelog. I don't mind either solution as we'll be able to navigate from issues to PR anyway as they are linked. (Some reference are for PR when no issues were created already so we'll have to handle the disambiguation pr/issues to link to te right thing in the documentation whatever we choose)

@github-actions

This comment has been minimized.

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

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

This look very promising !

@DudeNr33
Copy link
Collaborator Author

The check on the pr number is possible in GitHub actions because GitHub actions have access to it. That's why I wanted to change that. If towncrier is doing the check for the change description another way I'd prefer keeping the consistency with the previous changelog. I don't mind either solution as we'll be able to navigate from issues to PR anyway as they are linked. (Some reference are for PR when no issues were created already so we'll have to handle the disambiguation pr/issues to link to te right thing in the documentation whatever we choose)

As far as I understand the integrated towncrier check command only checks if there is any new news fragment.
It does not include any logic to see if the stem of the news fragment is actually an issue number.
However, we can of course enhance the changelog pipeline with a custom script that searches the PR body for refs/closes/etc., and checks if the added news fragment starts with the number given there.

I currently use the stem of the news fragment file to construct a link to the issue in the changelog:
https://pylint--6974.org.readthedocs.build/en/6974/whatsnew/2/2.15/index.html#false-negatives-fixed
However, this approach is currently missing the information if this is "closes", "refs", or whatever else it may be.
We could change that by including your original check_changelog script from #6688 in the changelog CI and enforce that a news fragment has to include a reference to an issue.

@DudeNr33
Copy link
Collaborator Author

I think we can split the check for the news fragments in two parts:

  1. The changelog.yml workflow ensures that every PR without the "skip news" label contains a news fragment. It does not check the content.
  2. The check_newsfragments.py script is used in the pre-commit configuration. It aims to check the contents of the news fragment.

This way contributors can see as early as possible if the created news fragment has the correct format. And if they forget to add one, the CI will notice and inform them.

Comment on lines 7 to 9
- [ ] Create a news fragment with `towncrier create <IssueNumber>.<type>` which will be
included in the changelog. If necessary you can write details of offer examples on how
the new change is supposed to work.
Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas Jun 18, 2022

Choose a reason for hiding this comment

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

Suggested change
- [ ] Create a news fragment with `towncrier create <IssueNumber>.<type>` which will be
included in the changelog. If necessary you can write details of offer examples on how
the new change is supposed to work.
- [ ] Create a news fragment with `towncrier create <IssueNumber>.<type>` the type can be "new_check",
"removed_check", "extension", "false_positive", "false_negative", "bugfix", "other", or "internal".
(For example ``towncrier create 1234.false_positive``). If necessary you can write details or offer
examples on how the new change is supposed to work.

Copy link
Member

Choose a reason for hiding this comment

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

It seems the list can be generated from towncrier.toml, hardcoding is enough imo, I'll update the suggestion

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated 👍

@@ -0,0 +1,38 @@
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Copy link
Member

Choose a reason for hiding this comment

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

Probably something that should be done in "python3 script/bump_changelog.py {new_version}" There's quite a bit of cleanup to do there with the adoption of towncrier ! We still have the script on the maintenance branch for 2.14 so almost everything can be removed (I think we only need to create the new file for minor automatically ?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree. I was a bit hesitant because of the "DO NOT MODIFY DIRECTLY" comment. 😄 That's probably not relevant any more / not relevant until we might decide to use towncrier in android as well?

Reading the release.md documentation, we have to handle two different invocations of tbump:

  1. Invocation for a release version (without a -devX):
    1.1 Update the version in towncrier.toml
    1.2 build the final documentation
  2. Invocation for a dev version:
    2.1 Update the version in towncrier.toml
    2.2 Update the filename in towncrier.toml
    2.3 Create a new doc/whatsnew/MAJOR/MAJOR.MINOR/index.rst and link that in the parent index.rst files' toctrees

Maybe we should do the tbump related things in a separate PR, to keep this one reviewable.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, right. Astroid is behind now and has a lot less activity than pylint. Last time I did astroid's script first, with the intention to use the same in both but pylint has different need. I don't mind keeping the old release and script routine in astroid as there is no whatsnew in astroid so no duplication for contributor.

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas Jul 12, 2022

Choose a reason for hiding this comment

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

Did you have time to look at "python3 script/bump_changelog.py`` @DudeNr33 ? (Sorry I'm answering a conversation that is at the top of the page it's unclear with the review).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not yet unfortunately. I'll try to get to it in the next days.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@Pierre-Sassoulas Pierre-Sassoulas added the Blocker 🙅 Blocks the next release label Jul 7, 2022
@Pierre-Sassoulas Pierre-Sassoulas added this to the 2.15.0 milestone Jul 7, 2022
@github-actions

This comment has been minimized.

@DudeNr33
Copy link
Collaborator Author

DudeNr33 commented Jul 9, 2022

Sorry guys for letting this open for so long.
I think beside the necessary rework of the tbump scripts this should no be ready for review.
I had some trouble getting the towncrier check command to work in the CI, but it does now!

Check out the current docs build here.
I am thinking about removing the hyperlink to the ticket/PR, as it is duplicated (once from the content of the news fragment itself without hyperlink, and once the hyperlink added by towncrier itself).

I added newsfragments for all changes currently included in the 2.15 changelog until now, and can do a last update before we merge.

@DudeNr33 DudeNr33 marked this pull request as ready for review July 9, 2022 10:20
Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

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

Thanks a lot for all the work here @DudeNr33!

I left some initial comments while I'm trying to wrap my head around what towncrier is doing for us 😄

@github-actions

This comment has been minimized.

@DudeNr33
Copy link
Collaborator Author

DudeNr33 commented Jul 9, 2022

Thanks for the feedback, Daniel!

As it is now already 3 weeks since we initially discussed towncrier, a short recap what it can do for us:

  • Instead of writing changelog entries in one common index.rst, individual files (news fragments) are used --> No more merge conflicts because of the changelog
  • towncrier check can be used in CI to check if a news fragment was added --> Contributors will be notified automatically if they forget to write a changelog entry
  • The concept of news fragments makes implementing a pre-commit hook to check the format of the changelog entry straightforward

I will incorporate the rest of your feedback tomorrow. 😊

@Pierre-Sassoulas
Copy link
Member

No more merge conflicts because of the changelog

70dda48d5b21b9c82783b2408ae4a5b7

Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

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

Thanks for the clear answers @DudeNr33

Some (final) comments, but this looks really promising!

@DanielNoord DanielNoord added the Skip news 🔇 This change does not require a changelog entry label Jul 10, 2022
@github-actions

This comment has been minimized.

Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

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

One final nit.

I'd like to see the interaction with required checks but rest LGTM! 😄

if verbose:
print(f"Checked '{file}': LGTM 🤖👍")
return True
print(f"{file}: does not respect the standard format 🤖👎")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we add something about what the format is here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, this would be helpful. Instead of just printing the cryptic regex I included a short text with placeholders.

@DanielNoord DanielNoord added Skip news 🔇 This change does not require a changelog entry and removed Skip news 🔇 This change does not require a changelog entry labels Jul 10, 2022
@DudeNr33
Copy link
Collaborator Author

One last question from my side:
Should the PULL_REQUEST_TEMPLATE.md still contain some words if we want to treat issues for 2.14.x the same way we did before? Is there any patch release for 2.14 planned?

Beside that I think all open issues are addressed now. I'd just make sure that I double check if I have transformed all changelog entries into news fragments just before we merge.

@DanielNoord
Copy link
Collaborator

Probably something to do with broken caches. Sadly Github doesn't allow removing caches through a nice interface and you can only do so by sending several POST requests.
I believe they are working on making it do-able from the site.

Bumped the cache to a number that we have never used and that seems to work. All tests are running now.

@Pierre-Sassoulas
Copy link
Member

Bumped the cache to a number that we have never used and that seems to work. All tests are running now.

It did not work two days ago, unless we already used 21031606416161651656510161616879 before 😄

@DanielNoord
Copy link
Collaborator

Bumped the cache to a number that we have never used and that seems to work. All tests are running now.

It did not work two days ago, unless we already used 21031606416161651656510161616879 before 😄

That might have been too long? CI passed 😄

@Pierre-Sassoulas
Copy link
Member

I regret rebasing on the 6 tests commits I did now 😄 Tried, 6, 7 , 8, 10, and a big number... I guess we'll never know it's too hard to check in https://github.com/PyCQA/pylint/actions?query=branch%3Atowncrier. Thanks for fixing this @DanielNoord !

@DudeNr33
Copy link
Collaborator Author

Thanks Pierre and Daniel!
Is there anything left to do for this MR or can we merge this?
Would this better be rebase and merge or squash and merge?

@DanielNoord
Copy link
Collaborator

Would this better be rebase and merge or squash and merge?

I'd prefer a git reset --soft and then some smaller commits that are a bit more explicit (for example separating the cache change from the new news entries, etc.) and then rebase the new clean commit history.

@github-actions
Copy link
Contributor

🤖 Effect of this PR on checked open source code: 🤖

Effect on django:
The following messages are no longer emitted:

  1. import-error:
    Unable to import 'jinja2'
    https://github.com/django/django/blob/main/django/template/backends/jinja2.py#L3

Effect on flask:
The following messages are no longer emitted:

  1. import-error:
    Unable to import 'markupsafe'
    https://github.com/pallets/flask/blob/main/src/flask/__init__.py#L1
  2. import-error:
    Unable to import 'markupsafe'
    https://github.com/pallets/flask/blob/main/src/flask/__init__.py#L2
  3. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/scaffold.py#L10
  4. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L3
  5. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L4
  6. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L5
  7. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L6
  8. too-few-public-methods:
    Too few public methods (0/2)
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L36
  9. missing-function-docstring:
    Missing function or method docstring
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L57
  10. missing-function-docstring:
    Missing function or method docstring
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L112
  11. import-error:
    Unable to import 'jinja2.utils'
    https://github.com/pallets/flask/blob/main/src/flask/json/__init__.py#L6
  12. import-error:
    Unable to import 'markupsafe'
    https://github.com/pallets/flask/blob/main/src/flask/json/tag.py#L49

Effect on pandas:
The following messages are no longer emitted:

  1. import-error:
    Unable to import 'markupsafe'
    https://github.com/pandas-dev/pandas/blob/main/pandas/io/formats/style_render.py#L47

This comment was generated for commit a4e4141

@DudeNr33
Copy link
Collaborator Author

Would this better be rebase and merge or squash and merge?

I'd prefer a git reset --soft and then some smaller commits that are a bit more explicit (for example separating the cache change from the new news entries, etc.) and then rebase the new clean commit history.

Thanks for the hint, @DanielNoord!
To make sure I don't mess this up, this is what I would do now:

  1. Make a backup branch from the current state of the towncrier branch (git checkout -b towncrier-backup) in case I do mess up, then switch back to this branch (towncrier)
  2. Soft reset to the commit I originally based my towncrier branch on: git reset --soft 9069eb48d
  3. Create new commits grouping together related files, like one for all news fragments, one for the pipelines, one for the updated docs
  4. force push those new commits to rewrite the history on the remote
  5. use GitHub web interface to select "Rebase and merge" to apply those newly created commits onto main

I tried that with a toy repo and it looks like that should do the trick, but step 4 makes me want to re-assure myself if this is really correct. 😄

@Pierre-Sassoulas
Copy link
Member

I would add a rebase on origin/main before 4 (that should be painless). To be safe in 4) you can --force-push-with-lease (it won't push if you did not have the last version of the server), but considering you're the only one working on your branch now it should be safe either way 👍

@DanielNoord
Copy link
Collaborator

Would this better be rebase and merge or squash and merge?

I'd prefer a git reset --soft and then some smaller commits that are a bit more explicit (for example separating the cache change from the new news entries, etc.) and then rebase the new clean commit history.

Thanks for the hint, @DanielNoord! To make sure I don't mess this up, this is what I would do now:

  1. Make a backup branch from the current state of the towncrier branch (git checkout -b towncrier-backup) in case I do mess up, then switch back to this branch (towncrier)
  2. Soft reset to the commit I originally based my towncrier branch on: git reset --soft 9069eb48d
  3. Create new commits grouping together related files, like one for all news fragments, one for the pipelines, one for the updated docs
  4. force push those new commits to rewrite the history on the remote
  5. use GitHub web interface to select "Rebase and merge" to apply those newly created commits onto main

I tried that with a toy repo and it looks like that should do the trick, but step 4 makes me want to re-assure myself if this is really correct. 😄

Yes, this is what I was thinking of!

@DudeNr33
Copy link
Collaborator Author

Thanks a ton you two! I always learn something new here. 👍
Looks like it worked out as expected by looking at the number of commits and the diffs.
I'll do the rebase and merge once all the checks have passed.

@DanielNoord
Copy link
Collaborator

@DudeNr33 Note that the first commit in this history can be avoided by a git pull --rebase instead of a merge but rebasing these commits is fine with me :)

Always happy to help, I tend to learn quite a lot from your PRs as well.

@github-actions
Copy link
Contributor

🤖 Effect of this PR on checked open source code: 🤖

Effect on django:
The following messages are no longer emitted:

  1. import-error:
    Unable to import 'jinja2'
    https://github.com/django/django/blob/main/django/template/backends/jinja2.py#L3

Effect on flask:
The following messages are no longer emitted:

  1. import-error:
    Unable to import 'markupsafe'
    https://github.com/pallets/flask/blob/main/src/flask/__init__.py#L1
  2. import-error:
    Unable to import 'markupsafe'
    https://github.com/pallets/flask/blob/main/src/flask/__init__.py#L2
  3. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/scaffold.py#L10
  4. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L3
  5. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L4
  6. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L5
  7. import-error:
    Unable to import 'jinja2'
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L6
  8. too-few-public-methods:
    Too few public methods (0/2)
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L36
  9. missing-function-docstring:
    Missing function or method docstring
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L57
  10. missing-function-docstring:
    Missing function or method docstring
    https://github.com/pallets/flask/blob/main/src/flask/templating.py#L112
  11. import-error:
    Unable to import 'jinja2.utils'
    https://github.com/pallets/flask/blob/main/src/flask/json/__init__.py#L6
  12. import-error:
    Unable to import 'markupsafe'
    https://github.com/pallets/flask/blob/main/src/flask/json/tag.py#L49

Effect on pandas:
The following messages are no longer emitted:

  1. import-error:
    Unable to import 'markupsafe'
    https://github.com/pandas-dev/pandas/blob/main/pandas/io/formats/style_render.py#L47

This comment was generated for commit 9b89303

@DudeNr33 DudeNr33 merged commit 0ce5277 into pylint-dev:main Jul 17, 2022
@Pierre-Sassoulas
Copy link
Member

I tend to learn quite a lot from your PRs as well.

Yeap, confirming that, I don't comment on it but I often learn of new, more elegant way to do thing when reviewing.

Great job @DudeNr33 this is a huge new feature, I feel like I handled changelog conflict 10% of the time for the last 5 years, I'm glad it's over 😄 I'm going to try an alpha/beta release with it and see how it goes 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Blocker 🙅 Blocks the next release Skip news 🔇 This change does not require a changelog entry
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants