mirror of
https://github.com/apricote/releaser-pleaser.git
synced 2026-01-13 21:21:03 +00:00
fix(versioning): properly handle prerelease version bumps
This commit is contained in:
parent
718364fe5c
commit
3b6aca0f9b
4 changed files with 443 additions and 55 deletions
|
|
@ -64,12 +64,12 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
changesets, tag, err := getChangesetsFromForge(ctx, f)
|
changesets, latestTag, stableTag, err := getChangesetsFromForge(ctx, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get changesets: %w", err)
|
return fmt.Errorf("failed to get changesets: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = reconcileReleasePR(ctx, f, changesets, tag)
|
err = reconcileReleasePR(ctx, f, changesets, latestTag, stableTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to reconcile release pr: %w", err)
|
return fmt.Errorf("failed to reconcile release pr: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -77,36 +77,39 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getChangesetsFromForge(ctx context.Context, forge rp.Forge) ([]rp.Changeset, *rp.Tag, error) {
|
func getChangesetsFromForge(ctx context.Context, forge rp.Forge) (changesets []rp.Changeset, latestTag *rp.Tag, stableTag *rp.Tag, err error) {
|
||||||
tag, err := forge.LatestTag(ctx)
|
latestTag, stableTag, err = forge.LatestTags(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if tag != nil {
|
if latestTag != nil {
|
||||||
logger.InfoContext(ctx, "found previous tag", "tag.hash", tag.Hash, "tag.name", tag.Name)
|
logger.InfoContext(ctx, "found latest tag", "tag.hash", latestTag.Hash, "tag.name", latestTag.Name)
|
||||||
} else {
|
} else {
|
||||||
logger.InfoContext(ctx, "no previous tag found")
|
logger.InfoContext(ctx, "no latest tag found")
|
||||||
|
}
|
||||||
|
if latestTag.Hash != stableTag.Hash {
|
||||||
|
logger.InfoContext(ctx, "found stable tag", "tag.hash", stableTag.Hash, "tag.name", stableTag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
releasableCommits, err := forge.CommitsSince(ctx, tag)
|
releasableCommits, err := forge.CommitsSince(ctx, stableTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.InfoContext(ctx, "Found releasable commits", "length", len(releasableCommits))
|
logger.InfoContext(ctx, "Found releasable commits", "length", len(releasableCommits))
|
||||||
|
|
||||||
changesets, err := forge.Changesets(ctx, releasableCommits)
|
changesets, err = forge.Changesets(ctx, releasableCommits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.InfoContext(ctx, "Found changesets", "length", len(changesets))
|
logger.InfoContext(ctx, "Found changesets", "length", len(changesets))
|
||||||
|
|
||||||
return changesets, tag, nil
|
return changesets, latestTag, stableTag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func reconcileReleasePR(ctx context.Context, forge rp.Forge, changesets []rp.Changeset, tag *rp.Tag) error {
|
func reconcileReleasePR(ctx context.Context, forge rp.Forge, changesets []rp.Changeset, latestTag *rp.Tag, stableTag *rp.Tag) error {
|
||||||
rpBranch := fmt.Sprintf(RELEASER_PLEASER_BRANCH, flagBranch)
|
rpBranch := fmt.Sprintf(RELEASER_PLEASER_BRANCH, flagBranch)
|
||||||
rpBranchRef := plumbing.NewBranchReferenceName(rpBranch)
|
rpBranchRef := plumbing.NewBranchReferenceName(rpBranch)
|
||||||
// Check Forge for open PR
|
// Check Forge for open PR
|
||||||
|
|
@ -131,7 +134,8 @@ func reconcileReleasePR(ctx context.Context, forge rp.Forge, changesets []rp.Cha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextVersion, err := rp.NextVersion(tag, changesets, releaseOverrides.NextVersionType)
|
versionBump := rp.VersionBumpFromChangesets(changesets)
|
||||||
|
nextVersion, err := rp.NextVersion(latestTag, stableTag, versionBump, releaseOverrides.NextVersionType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
forge.go
64
forge.go
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/blang/semver/v4"
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||||
"github.com/google/go-github/v63/github"
|
"github.com/google/go-github/v63/github"
|
||||||
|
|
@ -32,8 +33,9 @@ type Forge interface {
|
||||||
|
|
||||||
GitAuth() transport.AuthMethod
|
GitAuth() transport.AuthMethod
|
||||||
|
|
||||||
// LatestTag returns the last tag created on the main branch. If no tag is found, it returns nil.
|
// LatestTags returns the last stable tag created on the main branch. If there is a more recent pre-release tag,
|
||||||
LatestTag(context.Context) (*Tag, error)
|
// that is also returned. If no tag is found, it returns nil.
|
||||||
|
LatestTags(context.Context) (stable *Tag, prerelease *Tag, err error)
|
||||||
|
|
||||||
// CommitsSince returns all commits to main branch after the Tag. The tag can be `nil`, in which case this
|
// CommitsSince returns all commits to main branch after the Tag. The tag can be `nil`, in which case this
|
||||||
// function should return all commits.
|
// function should return all commits.
|
||||||
|
|
@ -82,24 +84,56 @@ func (g *GitHub) GitAuth() transport.AuthMethod {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GitHub) LatestTag(ctx context.Context) (*Tag, error) {
|
func (g *GitHub) LatestTags(ctx context.Context) (latest *Tag, stable *Tag, err error) {
|
||||||
g.log.Debug("listing all tags in github repository")
|
g.log.DebugContext(ctx, "listing all tags in github repository")
|
||||||
// We only get the first page because the latest tag is returned as the first item
|
|
||||||
tags, _, err := g.client.Repositories.ListTags(ctx, g.options.Owner, g.options.Repo, nil)
|
page := 1
|
||||||
|
|
||||||
|
for {
|
||||||
|
tags, resp, err := g.client.Repositories.ListTags(
|
||||||
|
ctx, g.options.Owner, g.options.Repo,
|
||||||
|
&github.ListOptions{Page: page, PerPage: GitHubPerPageMax},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tags) > 0 {
|
for _, ghTag := range tags {
|
||||||
// TODO: Is tags sorted?
|
tag := &Tag{
|
||||||
tag := tags[0]
|
Hash: ghTag.GetCommit().GetSHA(),
|
||||||
return &Tag{
|
Name: ghTag.GetName(),
|
||||||
Hash: tag.GetCommit().GetSHA(),
|
|
||||||
Name: tag.GetName(),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
version, err := semver.Parse(tag.Name)
|
||||||
|
if err != nil {
|
||||||
|
g.log.WarnContext(
|
||||||
|
ctx, "unable to parse tag as semver, skipping",
|
||||||
|
"tag.name", tag.Name,
|
||||||
|
"tag.hash", tag.Hash,
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if latest == nil {
|
||||||
|
latest = tag
|
||||||
|
}
|
||||||
|
if len(version.Pre) == 0 {
|
||||||
|
// Stable version tag
|
||||||
|
// We return once we have found the latest stable tag, not needed to look at every single tag.
|
||||||
|
return latest, tag, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if page == resp.LastPage || resp.LastPage == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
page = resp.NextPage
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GitHub) CommitsSince(ctx context.Context, tag *Tag) ([]Commit, error) {
|
func (g *GitHub) CommitsSince(ctx context.Context, tag *Tag) ([]Commit, error) {
|
||||||
|
|
|
||||||
|
|
@ -8,56 +8,68 @@ import (
|
||||||
"github.com/leodido/go-conventionalcommits"
|
"github.com/leodido/go-conventionalcommits"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NextVersion(currentTag *Tag, changesets []Changeset, nextVersionType NextVersionType) (string, error) {
|
func NextVersion(latestTag *Tag, stableTag *Tag, versionBump conventionalcommits.VersionBump, nextVersionType NextVersionType) (string, error) {
|
||||||
// TODO: Validate for versioning after pre-releases
|
// TODO: Validate for versioning after pre-releases
|
||||||
currentVersion := "v0.0.0"
|
latestVersion := "v0.0.0"
|
||||||
if currentTag != nil {
|
if latestTag != nil {
|
||||||
currentVersion = currentTag.Name
|
latestVersion = latestTag.Name
|
||||||
|
}
|
||||||
|
stableVersion := "v0.0.0"
|
||||||
|
if stableTag != nil {
|
||||||
|
stableVersion = stableTag.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// The lib can not handle v prefixes
|
// The lib can not handle v prefixes
|
||||||
currentVersion = strings.TrimPrefix(currentVersion, "v")
|
latestVersion = strings.TrimPrefix(latestVersion, "v")
|
||||||
|
stableVersion = strings.TrimPrefix(stableVersion, "v")
|
||||||
|
|
||||||
version, err := semver.Parse(currentVersion)
|
latest, err := semver.Parse(latestVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
versionBump := maxVersionBump(changesets)
|
stable, err := semver.Parse(stableVersion)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
next := stable // Copy all fields
|
||||||
|
|
||||||
switch versionBump {
|
switch versionBump {
|
||||||
case conventionalcommits.UnknownVersion:
|
case conventionalcommits.UnknownVersion:
|
||||||
// No new version, TODO: Throw error?
|
return "", fmt.Errorf("invalid latest bump (unknown)")
|
||||||
case conventionalcommits.PatchVersion:
|
case conventionalcommits.PatchVersion:
|
||||||
err = version.IncrementPatch()
|
err = next.IncrementPatch()
|
||||||
case conventionalcommits.MinorVersion:
|
case conventionalcommits.MinorVersion:
|
||||||
err = version.IncrementMinor()
|
err = next.IncrementMinor()
|
||||||
case conventionalcommits.MajorVersion:
|
case conventionalcommits.MajorVersion:
|
||||||
err = version.IncrementMajor()
|
err = next.IncrementMajor()
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch nextVersionType {
|
switch nextVersionType {
|
||||||
|
case NextVersionTypeUndefined, NextVersionTypeNormal:
|
||||||
|
next.Pre = make([]semver.PRVersion, 0)
|
||||||
case NextVersionTypeAlpha, NextVersionTypeBeta, NextVersionTypeRC:
|
case NextVersionTypeAlpha, NextVersionTypeBeta, NextVersionTypeRC:
|
||||||
id := uint64(0)
|
id := uint64(0)
|
||||||
|
|
||||||
if version.Pre[0].String() == nextVersionType.String() {
|
if len(latest.Pre) >= 2 && latest.Pre[0].String() == nextVersionType.String() {
|
||||||
if version.Pre[1].String() == "" || !version.Pre[1].IsNumeric() {
|
if latest.Pre[1].String() == "" || !latest.Pre[1].IsNumeric() {
|
||||||
return "", fmt.Errorf("invalid format of previous tag")
|
return "", fmt.Errorf("invalid format of previous tag")
|
||||||
}
|
}
|
||||||
id = version.Pre[1].VersionNum + 1
|
id = latest.Pre[1].VersionNum + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
setPRVersion(&version, nextVersionType.String(), id)
|
setPRVersion(&next, nextVersionType.String(), id)
|
||||||
case NextVersionTypeUndefined, NextVersionTypeNormal:
|
|
||||||
version.Pre = make([]semver.PRVersion, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "v" + version.String(), nil
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return "v" + next.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func maxVersionBump(changesets []Changeset) conventionalcommits.VersionBump {
|
func VersionBumpFromChangesets(changesets []Changeset) conventionalcommits.VersionBump {
|
||||||
bump := conventionalcommits.UnknownVersion
|
bump := conventionalcommits.UnknownVersion
|
||||||
|
|
||||||
for _, changeset := range changesets {
|
for _, changeset := range changesets {
|
||||||
|
|
|
||||||
338
versioning_test.go
Normal file
338
versioning_test.go
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
package rp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/leodido/go-conventionalcommits"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNextVersion(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
latestTag *Tag
|
||||||
|
stableTag *Tag
|
||||||
|
versionBump conventionalcommits.VersionBump
|
||||||
|
nextVersionType NextVersionType
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
wantErr assert.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple bump (major)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MajorVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "v2.0.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "simple bump (minor)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MinorVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "v1.2.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "simple bump (patch)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "v1.1.2",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal to prerelease (major)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MajorVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v2.0.0-rc.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal to prerelease (minor)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MinorVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v1.2.0-rc.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal to prerelease (patch)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v1.1.2-rc.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease bump (major)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v2.0.0-rc.0"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MajorVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v2.0.0-rc.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease bump (minor)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.2.0-rc.0"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MinorVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v1.2.0-rc.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease bump (patch)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.2-rc.0"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v1.1.2-rc.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease different bump (major)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.2.0-rc.0"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MajorVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v2.0.0-rc.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease different bump (minor)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.2-rc.0"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.MinorVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v1.2.0-rc.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease to prerelease",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1-alpha.2"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.0"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "v1.1.1-rc.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease to normal (explicit)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1-alpha.2"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.0"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeNormal,
|
||||||
|
},
|
||||||
|
want: "v1.1.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prerelease to normal (implicit)",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1-alpha.2"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.0"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "v1.1.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil tag (major)",
|
||||||
|
args: args{
|
||||||
|
latestTag: nil,
|
||||||
|
stableTag: nil,
|
||||||
|
versionBump: conventionalcommits.MajorVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "v1.0.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil tag (minor)",
|
||||||
|
args: args{
|
||||||
|
latestTag: nil,
|
||||||
|
stableTag: nil,
|
||||||
|
versionBump: conventionalcommits.MinorVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "v0.1.0",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil tag (patch)",
|
||||||
|
args: args{
|
||||||
|
latestTag: nil,
|
||||||
|
stableTag: nil,
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "v0.0.1",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on invalid tag semver",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "foodazzle"},
|
||||||
|
stableTag: &Tag{Name: "foodazzle"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "",
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on invalid tag prerelease",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1-rc.foo"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1-rc.foo"},
|
||||||
|
versionBump: conventionalcommits.PatchVersion,
|
||||||
|
nextVersionType: NextVersionTypeRC,
|
||||||
|
},
|
||||||
|
want: "",
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on invalid bump",
|
||||||
|
args: args{
|
||||||
|
latestTag: &Tag{Name: "v1.1.1"},
|
||||||
|
stableTag: &Tag{Name: "v1.1.1"},
|
||||||
|
versionBump: conventionalcommits.UnknownVersion,
|
||||||
|
nextVersionType: NextVersionTypeUndefined,
|
||||||
|
},
|
||||||
|
want: "",
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := NextVersion(tt.args.latestTag, tt.args.stableTag, tt.args.versionBump, tt.args.nextVersionType)
|
||||||
|
if !tt.wantErr(t, err, fmt.Sprintf("NextVersion(%v, %v, %v, %v)", tt.args.latestTag, tt.args.stableTag, tt.args.versionBump, tt.args.nextVersionType)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equalf(t, tt.want, got, "NextVersion(%v, %v, %v, %v)", tt.args.latestTag, tt.args.stableTag, tt.args.versionBump, tt.args.nextVersionType)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersionBumpFromChangesets(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
changesets []Changeset
|
||||||
|
want conventionalcommits.VersionBump
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no entries (unknown)",
|
||||||
|
changesets: []Changeset{},
|
||||||
|
want: conventionalcommits.UnknownVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-release type (unknown)",
|
||||||
|
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{Type: "docs"}}}},
|
||||||
|
want: conventionalcommits.UnknownVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single breaking (major)",
|
||||||
|
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{BreakingChange: true}}}},
|
||||||
|
want: conventionalcommits.MajorVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single feat (minor)",
|
||||||
|
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{Type: "feat"}}}},
|
||||||
|
want: conventionalcommits.MinorVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single fix (patch)",
|
||||||
|
changesets: []Changeset{{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}}}},
|
||||||
|
want: conventionalcommits.PatchVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple changesets (major)",
|
||||||
|
changesets: []Changeset{
|
||||||
|
{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}}},
|
||||||
|
{ChangelogEntries: []AnalyzedCommit{{BreakingChange: true}}},
|
||||||
|
},
|
||||||
|
want: conventionalcommits.MajorVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple changesets (minor)",
|
||||||
|
changesets: []Changeset{
|
||||||
|
{ChangelogEntries: []AnalyzedCommit{{Type: "fix"}}},
|
||||||
|
{ChangelogEntries: []AnalyzedCommit{{Type: "feat"}}},
|
||||||
|
},
|
||||||
|
want: conventionalcommits.MinorVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple changesets (patch)",
|
||||||
|
changesets: []Changeset{
|
||||||
|
{ChangelogEntries: []AnalyzedCommit{{Type: "docs"}}},
|
||||||
|
{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 {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
assert.Equalf(t, tt.want, VersionBumpFromChangesets(tt.changesets), "VersionBumpFromChangesets(%v)", tt.changesets)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue