@@ -93,11 +93,11 @@ Language Image: {{.ImageVersion}}
9393 }).Parse (`BEGIN_COMMIT_OVERRIDE
9494{{ range .Commits }}
9595BEGIN_NESTED_COMMIT
96- {{.Type}}: [{{.LibraryID}}] {{.Subject}}
96+ {{.Type}}: {{.Subject}}
9797{{.Body}}
9898
9999PiperOrigin-RevId: {{index .Footers "PiperOrigin-RevId"}}
100-
100+ Library-IDs: {{index .Footers "Library-IDs"}}
101101Source-link: [googleapis/googleapis@{{shortSHA .CommitHash}}](https://github.com/googleapis/googleapis/commit/{{shortSHA .CommitHash}})
102102END_NESTED_COMMIT
103103{{ end }}
@@ -182,20 +182,20 @@ func formatGenerationPRBody(repo gitrepo.Repository, state *config.LibrarianStat
182182 // because this function will return early if no conventional commit is found
183183 // since last generation.
184184 startSHA := startCommit .Hash .String ()
185-
185+ groupedCommits := groupByIDAndSubject ( allCommits )
186186 // Sort the slice by commit time in reverse order,
187187 // so that the latest commit appears first.
188- sort .Slice (allCommits , func (i , j int ) bool {
189- return allCommits [i ].When .After (allCommits [j ].When )
188+ sort .Slice (groupedCommits , func (i , j int ) bool {
189+ return groupedCommits [i ].When .After (groupedCommits [j ].When )
190190 })
191- endSHA := allCommits [0 ].CommitHash
191+ endSHA := groupedCommits [0 ].CommitHash
192192 librarianVersion := cli .Version ()
193193 data := & generationPRBody {
194194 StartSHA : startSHA ,
195195 EndSHA : endSHA ,
196196 LibrarianVersion : librarianVersion ,
197197 ImageVersion : state .Image ,
198- Commits : allCommits ,
198+ Commits : groupedCommits ,
199199 FailedLibraries : failedLibraries ,
200200 }
201201 var out bytes.Buffer
@@ -237,6 +237,44 @@ func findLatestGenerationCommit(repo gitrepo.Repository, state *config.Librarian
237237 return res , nil
238238}
239239
240+ // groupByIDAndSubject aggregates conventional commits for ones have the same Piper ID and subject in the footer.
241+ func groupByIDAndSubject (commits []* conventionalcommits.ConventionalCommit ) []* conventionalcommits.ConventionalCommit {
242+ var res []* conventionalcommits.ConventionalCommit
243+ idToCommits := make (map [string ][]* conventionalcommits.ConventionalCommit )
244+ for _ , commit := range commits {
245+ // a commit is not considering for grouping if it doesn't have a footer or
246+ // the footer doesn't have a Piper ID.
247+ if commit .Footers == nil {
248+ commit .Footers = make (map [string ]string )
249+ commit .Footers ["Library-IDs" ] = commit .LibraryID
250+ res = append (res , commit )
251+ continue
252+ }
253+
254+ id , ok := commit .Footers ["PiperOrigin-RevId" ]
255+ if ! ok {
256+ commit .Footers ["Library-IDs" ] = commit .LibraryID
257+ res = append (res , commit )
258+ continue
259+ }
260+
261+ key := fmt .Sprintf ("%s-%s" , id , commit .Subject )
262+ idToCommits [key ] = append (idToCommits [key ], commit )
263+ }
264+
265+ for _ , groupCommits := range idToCommits {
266+ var ids []string
267+ for _ , commit := range groupCommits {
268+ ids = append (ids , commit .LibraryID )
269+ }
270+ firstCommit := groupCommits [0 ]
271+ firstCommit .Footers ["Library-IDs" ] = strings .Join (ids , "," )
272+ res = append (res , firstCommit )
273+ }
274+
275+ return res
276+ }
277+
240278// formatReleaseNotes generates the body for a release pull request.
241279func formatReleaseNotes (state * config.LibrarianState , ghRepo * github.Repository ) (string , error ) {
242280 librarianVersion := cli .Version ()
0 commit comments