refactor: move commit analyzing out of forge

This commit is contained in:
Julian Tölle 2024-08-17 16:26:40 +02:00
parent f2a982d7a0
commit 5882a6bf2c
11 changed files with 152 additions and 188 deletions

View file

@ -90,18 +90,16 @@ func UpdateChangelogFile(wt *git.Worktree, newEntry string) error {
return nil return nil
} }
func NewChangelogEntry(changesets []Changeset, version, link, prefix, suffix string) (string, error) { func NewChangelogEntry(commits []AnalyzedCommit, version, link, prefix, suffix string) (string, error) {
features := make([]AnalyzedCommit, 0) features := make([]AnalyzedCommit, 0)
fixes := make([]AnalyzedCommit, 0) fixes := make([]AnalyzedCommit, 0)
for _, changeset := range changesets { for _, commit := range commits {
for _, commit := range changeset.ChangelogEntries { switch commit.Type {
switch commit.Type { case "feat":
case "feat": features = append(features, commit)
features = append(features, commit) case "fix":
case "fix": fixes = append(fixes, commit)
fixes = append(fixes, commit)
}
} }
} }

View file

@ -96,11 +96,11 @@ func TestUpdateChangelogFile(t *testing.T) {
func Test_NewChangelogEntry(t *testing.T) { func Test_NewChangelogEntry(t *testing.T) {
type args struct { type args struct {
changesets []Changeset analyzedCommits []AnalyzedCommit
version string version string
link string link string
prefix string prefix string
suffix string suffix string
} }
tests := []struct { tests := []struct {
name string name string
@ -111,9 +111,9 @@ func Test_NewChangelogEntry(t *testing.T) {
{ {
name: "empty", name: "empty",
args: args{ args: args{
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{}}}, analyzedCommits: []AnalyzedCommit{},
version: "1.0.0", version: "1.0.0",
link: "https://example.com/1.0.0", link: "https://example.com/1.0.0",
}, },
want: "## [1.0.0](https://example.com/1.0.0)", want: "## [1.0.0](https://example.com/1.0.0)",
wantErr: assert.NoError, wantErr: assert.NoError,
@ -121,13 +121,13 @@ func Test_NewChangelogEntry(t *testing.T) {
{ {
name: "single feature", name: "single feature",
args: args{ args: args{
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{ analyzedCommits: []AnalyzedCommit{
{ {
Commit: Commit{}, Commit: Commit{},
Type: "feat", Type: "feat",
Description: "Foobar!", Description: "Foobar!",
}, },
}}}, },
version: "1.0.0", version: "1.0.0",
link: "https://example.com/1.0.0", link: "https://example.com/1.0.0",
}, },
@ -137,13 +137,13 @@ func Test_NewChangelogEntry(t *testing.T) {
{ {
name: "single fix", name: "single fix",
args: args{ args: args{
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{ analyzedCommits: []AnalyzedCommit{
{ {
Commit: Commit{}, Commit: Commit{},
Type: "fix", Type: "fix",
Description: "Foobar!", Description: "Foobar!",
}, },
}}}, },
version: "1.0.0", version: "1.0.0",
link: "https://example.com/1.0.0", link: "https://example.com/1.0.0",
}, },
@ -153,7 +153,7 @@ func Test_NewChangelogEntry(t *testing.T) {
{ {
name: "multiple commits with scopes", name: "multiple commits with scopes",
args: args{ args: args{
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{ analyzedCommits: []AnalyzedCommit{
{ {
Commit: Commit{}, Commit: Commit{},
Type: "feat", Type: "feat",
@ -176,7 +176,7 @@ func Test_NewChangelogEntry(t *testing.T) {
Description: "So sad!", Description: "So sad!",
Scope: ptr("sad"), Scope: ptr("sad"),
}, },
}}}, },
version: "1.0.0", version: "1.0.0",
link: "https://example.com/1.0.0", link: "https://example.com/1.0.0",
}, },
@ -196,13 +196,13 @@ func Test_NewChangelogEntry(t *testing.T) {
{ {
name: "prefix", name: "prefix",
args: args{ args: args{
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{ analyzedCommits: []AnalyzedCommit{
{ {
Commit: Commit{}, Commit: Commit{},
Type: "fix", Type: "fix",
Description: "Foobar!", Description: "Foobar!",
}, },
}}}, },
version: "1.0.0", version: "1.0.0",
link: "https://example.com/1.0.0", link: "https://example.com/1.0.0",
prefix: "### Breaking Changes", prefix: "### Breaking Changes",
@ -219,13 +219,13 @@ func Test_NewChangelogEntry(t *testing.T) {
{ {
name: "suffix", name: "suffix",
args: args{ args: args{
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{ analyzedCommits: []AnalyzedCommit{
{ {
Commit: Commit{}, Commit: Commit{},
Type: "fix", Type: "fix",
Description: "Foobar!", Description: "Foobar!",
}, },
}}}, },
version: "1.0.0", version: "1.0.0",
link: "https://example.com/1.0.0", link: "https://example.com/1.0.0",
suffix: "### Compatibility\n\nThis version is compatible with flux-compensator v2.2 - v2.9.", suffix: "### Compatibility\n\nThis version is compatible with flux-compensator v2.2 - v2.9.",
@ -245,7 +245,7 @@ This version is compatible with flux-compensator v2.2 - v2.9.
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := NewChangelogEntry(tt.args.changesets, tt.args.version, tt.args.link, tt.args.prefix, tt.args.suffix) got, err := NewChangelogEntry(tt.args.analyzedCommits, tt.args.version, tt.args.link, tt.args.prefix, tt.args.suffix)
if !tt.wantErr(t, err) { if !tt.wantErr(t, err) {
return return
} }

View file

@ -59,7 +59,7 @@ func run(cmd *cobra.Command, _ []string) error {
}) })
} }
releaserPleaser := rp.New(forge, logger, flagBranch) releaserPleaser := rp.New(forge, logger, flagBranch, rp.NewConventionalCommitsParser(), rp.SemVerNextVersion)
return releaserPleaser.Run(ctx) return releaserPleaser.Run(ctx)
} }

View file

@ -7,6 +7,19 @@ import (
"github.com/leodido/go-conventionalcommits/parser" "github.com/leodido/go-conventionalcommits/parser"
) )
type Commit struct {
Hash string
Message string
PullRequest *PullRequest
}
type PullRequest struct {
ID int
Title string
Description string
}
type AnalyzedCommit struct { type AnalyzedCommit struct {
Commit Commit
Type string Type string
@ -34,7 +47,7 @@ func NewConventionalCommitsParser() *ConventionalCommitsParser {
} }
} }
func (c *ConventionalCommitsParser) AnalyzeCommits(commits []Commit) ([]AnalyzedCommit, error) { func (c *ConventionalCommitsParser) Analyze(commits []Commit) ([]AnalyzedCommit, error) {
analyzedCommits := make([]AnalyzedCommit, 0, len(commits)) analyzedCommits := make([]AnalyzedCommit, 0, len(commits))
for _, commit := range commits { for _, commit := range commits {

View file

@ -111,7 +111,7 @@ func TestAnalyzeCommits(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
analyzedCommits, err := NewConventionalCommitsParser().AnalyzeCommits(tt.commits) analyzedCommits, err := NewConventionalCommitsParser().Analyze(tt.commits)
if !tt.wantErr(t, err) { if !tt.wantErr(t, err) {
return return
} }

117
forge.go
View file

@ -25,12 +25,6 @@ const (
GitHubLabelColor = "dedede" GitHubLabelColor = "dedede"
) )
type Changeset struct {
URL string
Identifier string
ChangelogEntries []AnalyzedCommit
}
type Forge interface { type Forge interface {
RepoURL() string RepoURL() string
CloneURL() string CloneURL() string
@ -46,9 +40,6 @@ type Forge interface {
// function should return all commits. // function should return all commits.
CommitsSince(context.Context, *Tag) ([]Commit, error) CommitsSince(context.Context, *Tag) ([]Commit, error)
// Changesets looks up the Pull/Merge Requests for each commit, returning its parsed metadata.
Changesets(context.Context, []Commit) ([]Changeset, error)
// EnsureLabelsExist verifies that all desired labels are available on the repository. If labels are missing, they // EnsureLabelsExist verifies that all desired labels are available on the repository. If labels are missing, they
// are created them. // are created them.
EnsureLabelsExist(context.Context, []Label) error EnsureLabelsExist(context.Context, []Label) error
@ -184,10 +175,16 @@ func (g *GitHub) CommitsSince(ctx context.Context, tag *Tag) ([]Commit, error) {
var commits = make([]Commit, 0, len(repositoryCommits)) var commits = make([]Commit, 0, len(repositoryCommits))
for _, ghCommit := range repositoryCommits { for _, ghCommit := range repositoryCommits {
commits = append(commits, Commit{ commit := Commit{
Hash: ghCommit.GetSHA(), Hash: ghCommit.GetSHA(),
Message: ghCommit.GetCommit().GetMessage(), Message: ghCommit.GetCommit().GetMessage(),
}) }
commit.PullRequest, err = g.prForCommit(ctx, commit)
if err != nil {
return nil, fmt.Errorf("failed to check for commit pull request: %w", err)
}
commits = append(commits, commit)
} }
return commits, nil return commits, nil
@ -272,73 +269,49 @@ func (g *GitHub) commitsSinceInit(ctx context.Context) ([]*github.RepositoryComm
return repositoryCommits, nil return repositoryCommits, nil
} }
func (g *GitHub) Changesets(ctx context.Context, commits []Commit) ([]Changeset, error) { func (g *GitHub) prForCommit(ctx context.Context, commit Commit) (*PullRequest, error) {
// We naively look up the associated PR for each commit through the "List pull requests associated with a commit" // We naively look up the associated PR for each commit through the "List pull requests associated with a commit"
// endpoint. This requires len(commits) requests. // endpoint. This requires len(commits) requests.
// Using the "List pull requests" endpoint might be faster, as it allows us to fetch 100 arbitrary PRs per request, // Using the "List pull requests" endpoint might be faster, as it allows us to fetch 100 arbitrary PRs per request,
// but worst case we need to look up all PRs made in the repository ever. // but worst case we need to look up all PRs made in the repository ever.
changesets := make([]Changeset, 0, len(commits)) log := g.log.With("commit.hash", commit.Hash)
page := 1
var associatedPRs []*github.PullRequest
for _, commit := range commits { for {
log := g.log.With("commit.hash", commit.Hash) log.Debug("fetching pull requests associated with commit", "page", page)
page := 1 prs, resp, err := g.client.PullRequests.ListPullRequestsWithCommit(
var associatedPRs []*github.PullRequest ctx, g.options.Owner, g.options.Repo,
commit.Hash, &github.ListOptions{
for { Page: page,
log.Debug("fetching pull requests associated with commit", "page", page) PerPage: GitHubPerPageMax,
prs, resp, err := g.client.PullRequests.ListPullRequestsWithCommit(
ctx, g.options.Owner, g.options.Repo,
commit.Hash, &github.ListOptions{
Page: page,
PerPage: GitHubPerPageMax,
})
if err != nil {
return nil, err
}
associatedPRs = append(associatedPRs, prs...)
if page == resp.LastPage || resp.LastPage == 0 {
break
}
page = resp.NextPage
}
var pullrequest *github.PullRequest
for _, pr := range associatedPRs {
// We only look for the PR that has this commit set as the "merge commit" => The result of squashing this branch onto main
if pr.GetMergeCommitSHA() == commit.Hash {
pullrequest = pr
break
}
}
if pullrequest == nil {
log.Warn("did not find associated pull request, not considering it for changesets")
// No pull request was found for this commit, nothing to do here
// TODO: We could also return the minimal changeset for this commit, so at least it would come up in the changelog.
continue
}
log = log.With("pullrequest.id", pullrequest.GetID())
// TODO: Parse PR description for overrides
changelogEntries, err := NewConventionalCommitsParser().AnalyzeCommits([]Commit{commit})
if err != nil {
log.Warn("unable to parse changelog entries", "error", err)
continue
}
if len(changelogEntries) > 0 {
changesets = append(changesets, Changeset{
URL: pullrequest.GetHTMLURL(),
Identifier: fmt.Sprintf("#%d", pullrequest.GetNumber()),
ChangelogEntries: changelogEntries,
}) })
if err != nil {
return nil, err
} }
associatedPRs = append(associatedPRs, prs...)
if page == resp.LastPage || resp.LastPage == 0 {
break
}
page = resp.NextPage
} }
return changesets, nil var pullrequest *github.PullRequest
for _, pr := range associatedPRs {
// We only look for the PR that has this commit set as the "merge commit" => The result of squashing this branch onto main
if pr.GetMergeCommitSHA() == commit.Hash {
pullrequest = pr
break
}
}
if pullrequest == nil {
return nil, nil
}
return gitHubPRToPullRequest(pullrequest), nil
} }
func (g *GitHub) EnsureLabelsExist(ctx context.Context, labels []Label) error { func (g *GitHub) EnsureLabelsExist(ctx context.Context, labels []Label) error {
@ -578,6 +551,14 @@ func (g *GitHub) CreateRelease(ctx context.Context, commit Commit, title, change
return nil return nil
} }
func gitHubPRToPullRequest(pr *github.PullRequest) *PullRequest {
return &PullRequest{
ID: pr.GetNumber(),
Title: pr.GetTitle(),
Description: pr.GetBody(),
}
}
func gitHubPRToReleasePullRequest(pr *github.PullRequest) *ReleasePullRequest { func gitHubPRToReleasePullRequest(pr *github.PullRequest) *ReleasePullRequest {
labels := make([]Label, 0, len(pr.Labels)) labels := make([]Label, 0, len(pr.Labels))
for _, label := range pr.Labels { for _, label := range pr.Labels {

5
git.go
View file

@ -17,11 +17,6 @@ const (
GitRemoteName = "origin" GitRemoteName = "origin"
) )
type Commit struct {
Hash string
Message string
}
type Tag struct { type Tag struct {
Hash string Hash string
Name string Name string

View file

@ -31,6 +31,9 @@ func init() {
} }
} }
// ReleasePullRequest
//
// TODO: Reuse [PullRequest]
type ReleasePullRequest struct { type ReleasePullRequest struct {
ID int ID int
Title string Title string
@ -58,7 +61,7 @@ func NewReleasePullRequest(head, branch, version, changelogEntry string) (*Relea
type ReleaseOverrides struct { type ReleaseOverrides struct {
Prefix string Prefix string
Suffix string Suffix string
// TODO: Doing the changelog for normal releases after previews requires to know about this while fetching the changesets // TODO: Doing the changelog for normal releases after previews requires to know about this while fetching the commits
NextVersionType NextVersionType NextVersionType NextVersionType
} }

View file

@ -18,13 +18,17 @@ type ReleaserPleaser struct {
forge Forge forge Forge
logger *slog.Logger logger *slog.Logger
targetBranch string targetBranch string
commitParser CommitParser
nextVersion VersioningStrategy
} }
func New(forge Forge, logger *slog.Logger, targetBranch string) *ReleaserPleaser { func New(forge Forge, logger *slog.Logger, targetBranch string, commitParser CommitParser, versioningStrategy VersioningStrategy) *ReleaserPleaser {
return &ReleaserPleaser{ return &ReleaserPleaser{
forge: forge, forge: forge,
logger: logger, logger: logger,
targetBranch: targetBranch, targetBranch: targetBranch,
commitParser: commitParser,
nextVersion: versioningStrategy,
} }
} }
@ -154,12 +158,13 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error {
logger.InfoContext(ctx, "Found releasable commits", "length", len(releasableCommits)) logger.InfoContext(ctx, "Found releasable commits", "length", len(releasableCommits))
changesets, err := rp.forge.Changesets(ctx, releasableCommits) // TODO: Handle commit overrides
analyzedCommits, err := rp.commitParser.Analyze(releasableCommits)
if err != nil { if err != nil {
return err return err
} }
logger.InfoContext(ctx, "Found changesets", "length", len(changesets)) logger.InfoContext(ctx, "Analyzed commits", "length", len(analyzedCommits))
rpBranch := fmt.Sprintf(PullRequestBranchFormat, rp.targetBranch) rpBranch := fmt.Sprintf(PullRequestBranchFormat, rp.targetBranch)
rpBranchRef := plumbing.NewBranchReferenceName(rpBranch) rpBranchRef := plumbing.NewBranchReferenceName(rpBranch)
@ -177,15 +182,15 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error {
logger.InfoContext(ctx, "found existing release pull request", "pr.id", pr.ID, "pr.title", pr.Title) logger.InfoContext(ctx, "found existing release pull request", "pr.id", pr.ID, "pr.title", pr.Title)
} }
if len(changesets) == 0 { if len(analyzedCommits) == 0 {
if pr != nil { if pr != nil {
logger.InfoContext(ctx, "closing existing pull requests, no changesets available", "pr.id", pr.ID, "pr.title", pr.Title) logger.InfoContext(ctx, "closing existing pull requests, no commits available", "pr.id", pr.ID, "pr.title", pr.Title)
err = rp.forge.ClosePullRequest(ctx, pr) err = rp.forge.ClosePullRequest(ctx, pr)
if err != nil { if err != nil {
return err return err
} }
} else { } else {
logger.InfoContext(ctx, "No changesets available for release") logger.InfoContext(ctx, "No commits available for release")
} }
return nil return nil
@ -199,8 +204,9 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error {
} }
} }
versionBump := VersionBumpFromChangesets(changesets) versionBump := VersionBumpFromCommits(analyzedCommits)
nextVersion, err := SemVerNextVersion(releases, versionBump, releaseOverrides.NextVersionType) // TODO: Set version in release pr
nextVersion, err := rp.nextVersion(releases, versionBump, releaseOverrides.NextVersionType)
if err != nil { if err != nil {
return err return err
} }
@ -235,7 +241,7 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error {
return fmt.Errorf("failed to update files with new version: %w", err) return fmt.Errorf("failed to update files with new version: %w", err)
} }
changelogEntry, err := NewChangelogEntry(changesets, nextVersion, rp.forge.ReleaseURL(nextVersion), releaseOverrides.Prefix, releaseOverrides.Suffix) changelogEntry, err := NewChangelogEntry(analyzedCommits, nextVersion, rp.forge.ReleaseURL(nextVersion), releaseOverrides.Prefix, releaseOverrides.Suffix)
if err != nil { if err != nil {
return fmt.Errorf("failed to build changelog entry: %w", err) return fmt.Errorf("failed to build changelog entry: %w", err)
} }

View file

@ -69,24 +69,22 @@ func SemVerNextVersion(r Releases, versionBump conventionalcommits.VersionBump,
return "v" + next.String(), nil return "v" + next.String(), nil
} }
func VersionBumpFromChangesets(changesets []Changeset) conventionalcommits.VersionBump { func VersionBumpFromCommits(commits []AnalyzedCommit) conventionalcommits.VersionBump {
bump := conventionalcommits.UnknownVersion bump := conventionalcommits.UnknownVersion
for _, changeset := range changesets { for _, commit := range commits {
for _, entry := range changeset.ChangelogEntries { entryBump := conventionalcommits.UnknownVersion
entryBump := conventionalcommits.UnknownVersion switch {
switch { case commit.BreakingChange:
case entry.BreakingChange: entryBump = conventionalcommits.MajorVersion
entryBump = conventionalcommits.MajorVersion case commit.Type == "feat":
case entry.Type == "feat": entryBump = conventionalcommits.MinorVersion
entryBump = conventionalcommits.MinorVersion case commit.Type == "fix":
case entry.Type == "fix": entryBump = conventionalcommits.PatchVersion
entryBump = conventionalcommits.PatchVersion }
}
if entryBump > bump { if entryBump > bump {
bump = entryBump bump = entryBump
}
} }
} }

View file

@ -333,86 +333,56 @@ func TestReleases_NextVersion(t *testing.T) {
} }
} }
func TestVersionBumpFromChangesets(t *testing.T) { func TestVersionBumpFromCommits(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
changesets []Changeset analyzedCommits []AnalyzedCommit
want conventionalcommits.VersionBump want conventionalcommits.VersionBump
}{ }{
{ {
name: "no entries (unknown)", name: "no entries (unknown)",
changesets: []Changeset{}, analyzedCommits: []AnalyzedCommit{},
want: conventionalcommits.UnknownVersion, want: conventionalcommits.UnknownVersion,
}, },
{ {
name: "non-release type (unknown)", name: "non-release type (unknown)",
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{Type: "docs"}}}}, analyzedCommits: []AnalyzedCommit{{Type: "docs"}},
want: conventionalcommits.UnknownVersion, want: conventionalcommits.UnknownVersion,
}, },
{ {
name: "single breaking (major)", name: "single breaking (major)",
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{BreakingChange: true}}}}, analyzedCommits: []AnalyzedCommit{{BreakingChange: true}},
want: conventionalcommits.MajorVersion, want: conventionalcommits.MajorVersion,
}, },
{ {
name: "single feat (minor)", name: "single feat (minor)",
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{Type: "feat"}}}}, analyzedCommits: []AnalyzedCommit{{Type: "feat"}},
want: conventionalcommits.MinorVersion, want: conventionalcommits.MinorVersion,
}, },
{ {
name: "single fix (patch)", name: "single fix (patch)",
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}}}}, analyzedCommits: []AnalyzedCommit{{Type: "fix"}},
want: conventionalcommits.PatchVersion, want: conventionalcommits.PatchVersion,
}, },
{ {
name: "multiple changesets (major)", name: "multiple entries (major)",
changesets: []Changeset{ analyzedCommits: []AnalyzedCommit{{Type: "fix"}, {BreakingChange: true}},
{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}}}, want: conventionalcommits.MajorVersion,
{ChangelogEntries: []AnalyzedCommit{{BreakingChange: true}}},
},
want: conventionalcommits.MajorVersion,
}, },
{ {
name: "multiple changesets (minor)", name: "multiple entries (minor)",
changesets: []Changeset{ analyzedCommits: []AnalyzedCommit{{Type: "fix"}, {Type: "feat"}},
{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}}}, want: conventionalcommits.MinorVersion,
{ChangelogEntries: []AnalyzedCommit{{Type: "feat"}}},
},
want: conventionalcommits.MinorVersion,
}, },
{ {
name: "multiple changesets (patch)", name: "multiple entries (patch)",
changesets: []Changeset{ analyzedCommits: []AnalyzedCommit{{Type: "docs"}, {Type: "fix"}},
{ChangelogEntries: []AnalyzedCommit{{Type: "docs"}}}, want: conventionalcommits.PatchVersion,
{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}}},
},
want: conventionalcommits.PatchVersion,
},
{
name: "multiple entries in one changeset (major)",
changesets: []Changeset{
{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}, {BreakingChange: true}}},
},
want: conventionalcommits.MajorVersion,
},
{
name: "multiple entries in one changeset (minor)",
changesets: []Changeset{
{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}, {Type: "feat"}}},
},
want: conventionalcommits.MinorVersion,
},
{
name: "multiple entries in one changeset (patch)",
changesets: []Changeset{
{ChangelogEntries: []AnalyzedCommit{{Type: "docs"}, {Type: "fix"}}},
},
want: conventionalcommits.PatchVersion,
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, VersionBumpFromChangesets(tt.changesets), "VersionBumpFromChangesets(%v)", tt.changesets) assert.Equalf(t, tt.want, VersionBumpFromCommits(tt.analyzedCommits), "VersionBumpFromCommits(%v)", tt.analyzedCommits)
}) })
} }
} }