From be9c7b3ece26ee5b003c4a6ed72cedf817ec3201 Mon Sep 17 00:00:00 2001 From: Gerrit Date: Mon, 9 Aug 2021 08:48:21 +0200 Subject: [PATCH] Also extract section for breaking changes. (#45) --- .../github/actions/release_drafter.go | 85 ++++++++++++------- .../github/actions/release_drafter_test.go | 32 +++++++ 2 files changed, 86 insertions(+), 31 deletions(-) diff --git a/pkg/webhooks/github/actions/release_drafter.go b/pkg/webhooks/github/actions/release_drafter.go index 7457804..5328786 100644 --- a/pkg/webhooks/github/actions/release_drafter.go +++ b/pkg/webhooks/github/actions/release_drafter.go @@ -21,8 +21,23 @@ import ( var ( githubIssueRef = regexp.MustCompile(`\(#(?P[0-9]+)\)`) + blocks = []codeBlock{ + { + identifier: "ACTIONS_REQUIRED", + sectionHeadline: "Required Actions", + }, + { + identifier: "BREAKING_CHANGE", + sectionHeadline: "Breaking Changes", + }, + } ) +type codeBlock struct { + identifier string + sectionHeadline string +} + type releaseDrafter struct { logger *zap.SugaredLogger client *clients.Github @@ -111,7 +126,7 @@ func (r *releaseDrafter) draft(ctx context.Context, p *releaseDrafterParams) err tmp := fmt.Sprintf("([release notes](%s))", p.ReleaseURL) releaseSuffix = &tmp } - err = r.prependActionsRequired(m, *p.ComponentReleaseInfo, releaseSuffix) + err = r.prependCodeBlocks(m, *p.ComponentReleaseInfo, releaseSuffix) if err != nil { r.logger.Debugw("skip adding release draft", "reason", err, "repo", p.RepositoryName) return nil @@ -183,7 +198,7 @@ func (r *releaseDrafter) updateReleaseBody(org string, priorBody string, compone tmp := fmt.Sprintf("([release notes](%s))", releaseURL) releaseSuffix = &tmp } - _ = r.prependActionsRequired(m, *componentBody, releaseSuffix) + _ = r.prependCodeBlocks(m, *componentBody, releaseSuffix) } heading := fmt.Sprintf("%s v%s", component, componentVersion.String()) @@ -229,7 +244,7 @@ func (r *releaseDrafter) appendMergedPR(ctx context.Context, title string, numbe m := markdown.Parse(infos.body) issueSuffix := fmt.Sprintf("(%s/%s#%d)", r.client.Organization(), p.RepositoryName, number) - err = r.prependActionsRequired(m, *p.ComponentReleaseInfo, &issueSuffix) + err = r.prependCodeBlocks(m, *p.ComponentReleaseInfo, &issueSuffix) if err != nil { r.logger.Debugw("skip adding merged pull request to release draft", "reason", err, "repo", p.RepositoryName) return nil @@ -282,48 +297,56 @@ func (r *releaseDrafter) appendPullRequest(org string, priorBody string, repo st if prBody != nil { issueSuffix := fmt.Sprintf("(%s/%s#%d)", org, repo, number) - _ = r.prependActionsRequired(m, *prBody, &issueSuffix) + _ = r.prependCodeBlocks(m, *prBody, &issueSuffix) } return m.String() } -func (r *releaseDrafter) prependActionsRequired(m *markdown.Markdown, body string, issueSuffix *string) error { - actionBlock, err := markdown.ExtractAnnotatedBlock("ACTIONS_REQUIRED", body) - if err != nil { - return err - } +func (r *releaseDrafter) prependCodeBlocks(m *markdown.Markdown, body string, issueSuffix *string) error { + changed := false - if issueSuffix != nil { - actionBlock += " " + *issueSuffix - } + for _, b := range blocks { + actionBlock, err := markdown.ExtractAnnotatedBlock(b.identifier, body) + if err != nil { + continue + } - actionBody := markdown.ToListItem(actionBlock) - if len(body) == 0 { - return err - } + if issueSuffix != nil { + actionBlock += " " + *issueSuffix + } - headline := "Required Actions" + actionBody := markdown.ToListItem(actionBlock) + if len(body) == 0 { + continue + } - releaseSection := ensureReleaseSection(m, r.draftHeadline) + releaseSection := ensureReleaseSection(m, r.draftHeadline) - section := releaseSection.FindSectionByHeading(2, headline) - if section != nil { - if strings.Contains(strings.Join(section.ContentLines, ""), strings.Join(actionBody, "")) { - // idempotence check: hint was already added - return nil + section := releaseSection.FindSectionByHeading(2, b.sectionHeadline) + if section != nil { + if strings.Contains(strings.Join(section.ContentLines, ""), strings.Join(actionBody, "")) { + // idempotence check: hint was already added + continue + } + section.AppendContent(actionBody) + changed = true + continue } - section.AppendContent(actionBody) - return nil + + releaseSection.PrependChild(&markdown.MarkdownSection{ + Level: 2, + Heading: b.sectionHeadline, + ContentLines: actionBody, + }) + changed = true } - releaseSection.PrependChild(&markdown.MarkdownSection{ - Level: 2, - Heading: headline, - ContentLines: actionBody, - }) + if changed { + return nil + } - return nil + return fmt.Errorf("no changes") } func ensureReleaseSection(m *markdown.Markdown, headline string) *markdown.MarkdownSection { diff --git a/pkg/webhooks/github/actions/release_drafter_test.go b/pkg/webhooks/github/actions/release_drafter_test.go index 67e3393..5ae9863 100644 --- a/pkg/webhooks/github/actions/release_drafter_test.go +++ b/pkg/webhooks/github/actions/release_drafter_test.go @@ -167,6 +167,23 @@ Some description * API has changed ([release notes](https://some-url)) ## Component Releases ### metal-robot v0.2.5 +* Fix (metal-stack/metal-robot#123) @Gerrit91`, + }, + { + name: "extracting breaking changes and required actions, empty release bidy", + headline: "General", + org: "metal-stack", + component: "metal-robot", + componentVersion: semver.MustParse("0.2.5"), + componentBody: v3.String("## General Changes\r\n\r\n* Fix (#123) @Gerrit91\r\n```ACTIONS_REQUIRED\r\nAPI has changed\r\n```\r\n```BREAKING_CHANGE\r\nAPI has changed\r\n```"), + releaseURL: "https://some-url", + want: `# General +## Breaking Changes +* API has changed ([release notes](https://some-url)) +## Required Actions +* API has changed ([release notes](https://some-url)) +## Component Releases +### metal-robot v0.2.5 * Fix (metal-stack/metal-robot#123) @Gerrit91`, }, } @@ -279,6 +296,21 @@ Some description ## Required Actions * API has changed (metal-stack/metal-robot#11) # Merged Pull Requests +* Some new feature (metal-stack/metal-robot#11) @metal-robot`, + }, + { + name: "creating fresh release draft with breaking change", + org: "metal-stack", + repo: "metal-robot", + title: "Some new feature", + number: 11, + author: "metal-robot", + priorBody: "", + prBody: v3.String("This is a new feature\r\n```BREAKING_CHANGE\r\nAPI has changed\r\n```"), + want: `# General +## Breaking Changes +* API has changed (metal-stack/metal-robot#11) +# Merged Pull Requests * Some new feature (metal-stack/metal-robot#11) @metal-robot`, }, }