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

Add local Changelog generation based on PR titles and labels #4219

Open
wants to merge 22 commits into
base: main
Choose a base branch
from

Conversation

vigneshsankariyer1234567890
Copy link

Description

Currently, we use Github's Changelog generator: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes

However, this is not the best option since it increases reliance on Github actions themselves. Furthermore, there is a need for local changelog generation in order to simplify the release process.

In the initial issue, attempts were made to look for a tool that could generate the Changelogs directly. Some tools include git-chglog, which actually generate the logs based on the commits themselves. However, these tools are not useful because FerretDB does not follow Changelog commit message standards at the moment, which leads to non-standard commit messages. This also means that it is difficult to use a tool that groups commit messages to hence get the list of PRs.

Instead, I opted for a custom approach that utilised the existing changelog template found in FerretDB (under .github/release.yml). Instead of using commits directly, the idea is to get the merged PRs from the Github API endpoint after the latest tag (which indicates a release). With the definition provided in the release.yml, we can emulate the Changelog generation action locally by subsequently grouping the PRs by the labels defined in the template, and lastly rendering as markdown to stdout.

Here is a demo of how it works:

Screen.Recording.2024-04-03.at.1.15.46.PM.mov

To test it, generate binaries for tools as per instructions in the CONTRIBUTING.md, and launch task changelog directly from root folder, with an input MILESTONE_TITLE according to the milestone that you wish to generate the Changelog for.

Closes #2682 .

Readiness checklist

  • I added/updated unit tests (and they pass).
  • I added/updated integration/compatibility tests (and they pass).
  • I added/updated comments and checked rendering.
  • I made spot refactorings.
  • I updated user documentation.
  • I ran task all, and it passed.
  • I ensured that PR title is good enough for the changelog.
  • (for maintainers only) I set Reviewers (@FerretDB/core), Milestone (Next), Labels, Project and project's Sprint fields.
  • I marked all done items in this checklist.

@CLAassistant
Copy link

CLAassistant commented Mar 31, 2024

CLA assistant check
All committers have signed the CLA.

tools/go.work Outdated Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

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

Please move that into tools/go.mod

Choose a reason for hiding this comment

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

moved into tools/go.mod

Copy link
Member

Choose a reason for hiding this comment

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

First of all:

FerretDB/CONTRIBUTING.md

Lines 359 to 363 in c299c53

4. In the pull request review conversations,
please either leave a new comment or resolve (close) the conversation,
which ensures other people can read all comments.
But do not do that simultaneously.
Conversations should typically be resolved by the conversation starter, not the PR author.

Second, tools/go.mod wasn't updated.
Third, CI fails: https://github.com/FerretDB/FerretDB/actions/runs/8506940135/job/23298489403?pr=4219. Please run formatting, linting, etc locally as described in CONTRIBUTING.md

Choose a reason for hiding this comment

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

Apologies regarding comment resolution.

I have updated tools/go.mod to include the dependency for yaml.v3 (and amended formatting issues)

tools/generatechangelog/generatechangelog.go Outdated Show resolved Hide resolved
tools/generatechangelog/generatechangelog_test.go Outdated Show resolved Hide resolved
tools/generatechangelog/generatechangelog_test.go Outdated Show resolved Hide resolved
Copy link

codecov bot commented Apr 1, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 67.21%. Comparing base (f95b5d2) to head (9a393ff).
Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4219      +/-   ##
==========================================
- Coverage   75.35%   67.21%   -8.14%     
==========================================
  Files         323      316       -7     
  Lines       22407    22051     -356     
==========================================
- Hits        16884    14821    -2063     
- Misses       4303     6070    +1767     
+ Partials     1220     1160      -60     

see 127 files with indirect coverage changes

Flag Coverage Δ
filter-false ?
filter-true 67.21% <ø> (-1.50%) ⬇️
hana-1 ?
integration 67.21% <ø> (-1.58%) ⬇️
mongodb-1 5.11% <ø> (-0.01%) ⬇️
mysql-1 ?
mysql-2 ?
mysql-3 ?
postgresql-1 46.38% <ø> (-0.09%) ⬇️
postgresql-2 49.52% <ø> (-0.10%) ⬇️
postgresql-3 49.72% <ø> (-8.45%) ⬇️
sqlite-1 45.52% <ø> (-0.16%) ⬇️
sqlite-2 48.61% <ø> (-0.18%) ⬇️
sqlite-3 48.87% <ø> (-0.11%) ⬇️
unit ?

Flags with carried forward coverage won't be shown. Click here to find out more.

@AlekSi
Copy link
Member

AlekSi commented Apr 1, 2024

@vigneshsankariyer1234567890 I will do a re-review shortly; please see our contribution documentation in the meantime

Copy link
Member

@AlekSi AlekSi left a comment

Choose a reason for hiding this comment

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

tools/go.mod Outdated
@@ -20,6 +20,8 @@ require (
mvdan.cc/gofumpt v0.6.0
)

require gopkg.in/yaml.v3 v3.0.1
Copy link
Member

Choose a reason for hiding this comment

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

Please move it to the group above

Choose a reason for hiding this comment

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

Added to group as requested, and run task lint to verify formatting.

tools/tools.go Outdated
@@ -25,11 +25,14 @@ import (
_ "golang.org/x/tools/cmd/stringer"
_ "golang.org/x/vuln/cmd/govulncheck"
_ "mvdan.cc/gofumpt"

_ "github.com/FerretDB/FerretDB/tools/generatechangelog"
Copy link
Member

Choose a reason for hiding this comment

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

It should not be there – note that checkdocs, checkswitch, checkcomments are all not imported

Choose a reason for hiding this comment

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

Removed verified binary generation still works.

@vigneshsankariyer1234567890
Copy link
Author

@AlekSi regarding tests for the introduced tool, I noticed that tools/Taskfile.yml has a script for testing checkcomments, checkdocs, checkswitch etc. Should I also be adding the test for generatechangelog within that?

@AlekSi
Copy link
Member

AlekSi commented Apr 2, 2024

Yes, absolutely. Please follow existing things and style as close as possible

@vigneshsankariyer1234567890
Copy link
Author

@AlekSi requested your review, and ensured lint and formatting passes. At the moment, running task all fails due to internal test failures, but I'm checking if it is an issue with my device.

- {{ .Title }} by @{{ .User.Login }} in {{ .URL }}
{{- end }}
{{- "\n" }}
{{- end }}
Copy link
Member

Choose a reason for hiding this comment

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

Let's add a missing line break there

Choose a reason for hiding this comment

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

added line break

Comment on lines +17 to +20
const (
OrgOwner = "FerretDB"
Repo = "FerretDB"
)
Copy link
Member

Choose a reason for hiding this comment

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

I think we could remove those constants

Choose a reason for hiding this comment

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

removed constants, and used directly in github call

Copy link
Member

Choose a reason for hiding this comment

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

But they are still there?..

return &commit.Author.Date.Time, nil
}

func FetchPRs(ctx context.Context, client *github.Client, owner, repo, sinceDate string) ([]PRItem, error) {
Copy link
Member

Choose a reason for hiding this comment

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

We could remove owner and repo

Choose a reason for hiding this comment

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

removed params for owner and repo

query := fmt.Sprintf("repo:%s/%s is:pr is:merged merged:>=%s", owner, repo, sinceDate)
opts := &github.SearchOptions{Sort: "created", Order: "desc", ListOptions: github.ListOptions{PerPage: 100}}

issues, _, err := client.Search.Issues(ctx, query, opts)
Copy link
Member

Choose a reason for hiding this comment

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

That would not work correctly if two versions were being developed and released in parallel. For example, v1.21.1 and v1.22.0.

Let's simplify all that: make the tool accept the Milestone title, get it, get a list of all PRs in it

Choose a reason for hiding this comment

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

Understood. Just to be clear, this would be the flow:

  1. Get the milestone based on title
  2. Search for PRs which are closed and merged based on the milestone number
  3. Format according to release template

Copy link
Member

Choose a reason for hiding this comment

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

Re 2 – not “search”. Search is a different and more complicated API. We just need to get a list of PRs within the milestone: https://github.com/FerretDB/FerretDB/milestone/63?closed=1

Choose a reason for hiding this comment

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

Understood. I used the "Issues" API instead, which has a ListByRepo method which allows to pass the milestone number and filter by closed. Subsequently, I identified Issues as Pull Requests by using the Issue::IsPullRequest method. However, I'm not sure about the distinction between Closed and Merged Pull requests, so I will take a further look at the API to clarify this.

res := []PRItem{}

for _, issue := range issues.Issues {
res = append(res, func(i *github.Issue) PRItem {
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure why we use anonymous inline function with struct and JSON tags, but I think we should not

Choose a reason for hiding this comment

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

Removed the JSON tags, they were there originally for verification

Copy link
Member

Choose a reason for hiding this comment

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

I still don't understand why we use anonymous inline structs. I think we should not.

tools/generatechangelog/generatechangelog.go Show resolved Hide resolved
func TestGroupPRsByCategories(t *testing.T) {
prItems := []PRItem{
{
URL: "http://example.com/pr1",
Copy link
Member

Choose a reason for hiding this comment

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

I don't think there is a need to test each individual piece individually. We could use a real (old) milestone and real (old) PRs

Choose a reason for hiding this comment

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

I've added an integration test that does each individual part and checks based on the output, which has real PRs.

@vigneshsankariyer1234567890
Copy link
Author

@AlekSi requested for your re-review. As requested, I have changed it such that task changelog takes in a variable "MILESTONE_TITLE", and can be used like this: task changelog MILESTONE_TITLE="your_milestone_here". I have also amended it to use the Issues API directly, and added an integration test that checks if the output matches the expected PRs for an old version (v0.9.1).

@AlekSi AlekSi added the community Issues and PRs assigned to community members label Apr 15, 2024
Copy link
Contributor

mergify bot commented Apr 16, 2024

@vigneshsankariyer1234567890 this pull request has merge conflicts.

@mergify mergify bot added the conflict PRs that have merge conflicts label Apr 16, 2024
@mergify mergify bot removed the conflict PRs that have merge conflicts label Apr 17, 2024
Copy link
Member

@AlekSi AlekSi left a comment

Choose a reason for hiding this comment

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

There are multiple CI failures that mask linter failures. Please run them locally.

Comment on lines +17 to +20
const (
OrgOwner = "FerretDB"
Repo = "FerretDB"
)
Copy link
Member

Choose a reason for hiding this comment

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

But they are still there?..

}

func NewGitHubClient() *github.Client {
return github.NewClient(nil).WithAuthToken(os.Getenv("GITHUB_TOKEN"))
Copy link
Member

Choose a reason for hiding this comment

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

We should use https://github.com/FerretDB/gh there

res := []PRItem{}

for _, issue := range issues.Issues {
res = append(res, func(i *github.Issue) PRItem {
Copy link
Member

Choose a reason for hiding this comment

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

I still don't understand why we use anonymous inline structs. I think we should not.

Copy link
Contributor

mergify bot commented May 7, 2024

@vigneshsankariyer1234567890 this pull request has merge conflicts.

@mergify mergify bot added the conflict PRs that have merge conflicts label May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Issues and PRs assigned to community members conflict PRs that have merge conflicts
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.

Find a better tool for CHANGELOG.md generation
3 participants