Skip to content

Commit

Permalink
feat: allow prerelease label to be specified with pre command (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
purpleclay authored Feb 17, 2024
1 parent 2840193 commit e8e431b
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 61 deletions.
131 changes: 85 additions & 46 deletions internal/nsv/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,57 @@ import (
)

const (
command = "NSV:"
forceMajor = "force~major"
forceMinor = "force~minor"
forcePatch = "force~patch"
forceIgnore = "force~ignore"
prerelease = "pre"
prefix = "NSV:"
sep = "~"
forceCmd = "force"
forceMajor = "major"
forceMinor = "minor"
forcePatch = "patch"
forceIgnore = "ignore"
preCmd = "pre"
preAlpha = "alpha"
preBeta = "beta"
preRc = "rc"
)

type Command struct {
Force Increment
Prerelease bool
Prerelease string
}

func DetectCommand(log []git.LogEntry) (Command, Match) {
command := Command{}
match := Match{}

for i, entry := range log {
msg := strings.TrimSpace(entry.Message)
idx := strings.LastIndex(msg, "\n")
if idx == -1 {
continue
}

footer := msg[idx+1:]
if strings.ToUpper(footer[:len(prefix)]) != prefix {
continue
}

cmdLine := strings.TrimSpace(footer[len(prefix):])
match = Match{Index: i, Start: idx + 1, End: (idx + len(footer)) + 1}

cmds := commands(cmdLine)
for _, cmd := range cmds {
if strings.HasPrefix(cmd, forceCmd) {
command.Force = chompForce(cmd)
} else if strings.HasPrefix(cmd, preCmd) {
command.Prerelease = chompPre(cmd)
}
}

// Detect only the first command
break
}

return command, match
}

func commands(line string) []string {
Expand All @@ -52,7 +92,7 @@ func commands(line string) []string {
var err error

// keep chomping until an error is returned
rem, out, err = cmd()(rem)
rem, out, err = chompCmd()(rem)
if err != nil {
break
}
Expand All @@ -63,7 +103,7 @@ func commands(line string) []string {
return cmds
}

func cmd() chomp.Combinator[string] {
func chompCmd() chomp.Combinator[string] {
return func(s string) (string, string, error) {
rem, out, err := chomp.Not(", ")(s)
if err != nil {
Expand All @@ -75,45 +115,44 @@ func cmd() chomp.Combinator[string] {
}
}

func DetectCommand(log []git.LogEntry) (Command, Match) {
force := NoIncrement
pre := false
match := Match{}

for i, entry := range log {
msg := strings.TrimSpace(entry.Message)
idx := strings.LastIndex(msg, "\n")
if idx == -1 {
continue
}

footer := msg[idx+1:]
if strings.ToUpper(footer[:len(command)]) != command {
continue
}

cmdLine := strings.TrimSpace(footer[len(command):])
match = Match{Index: i, Start: idx + 1, End: (idx + len(footer)) + 1}
func chompForce(cmd string) Increment {
_, out, err := chomp.SepPair(
chomp.Tag(forceCmd),
chomp.Tag(sep),
chomp.First(
chomp.Tag(forceMajor),
chomp.Tag(forceMinor),
chomp.Tag(forcePatch),
chomp.Tag(forceIgnore),
))(cmd)
if err != nil {
return NoIncrement
}

cmds := commands(cmdLine)
for _, cmd := range cmds {
switch cmd {
case forceMajor:
force = MajorIncrement
case forceMinor:
force = MinorIncrement
case forcePatch:
force = PatchIncrement
case forceIgnore:
force = NoIncrement
case prerelease:
pre = true
}
}
switch out[1] {
case forceMajor:
return MajorIncrement
case forceMinor:
return MinorIncrement
case forcePatch:
return PatchIncrement
default:
return NoIncrement
}
}

// Only want the first detected command
break
func chompPre(cmd string) string {
_, out, err := chomp.SepPair(
chomp.Tag(preCmd),
chomp.Tag(sep),
chomp.First(
chomp.Tag(preAlpha),
chomp.Tag(preBeta),
chomp.Tag(preRc),
))(cmd)
if err != nil {
return "beta"
}

return Command{Force: force, Prerelease: pre}, match
return out[1]
}
52 changes: 41 additions & 11 deletions internal/nsv/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ SOFTWARE.
package nsv_test

import (
"fmt"
"testing"

git "github.com/purpleclay/gitz"
Expand Down Expand Up @@ -83,7 +84,7 @@ nsv:force~ignore`,
require.Equal(t, tt.inc, cmd.Force, "failed to match increment")
require.Equal(t, tt.match.Start, match.Start, "failed to match starting index")
require.Equal(t, tt.match.End, match.End, "failed to match end index")
require.False(t, cmd.Prerelease, "prerelease should be false")
require.Empty(t, cmd.Prerelease, "prerelease should be empty")
})
}
}
Expand Down Expand Up @@ -115,16 +116,45 @@ Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.c
func TestDetectCommandPrerelease(t *testing.T) {
t.Parallel()

cmd, match := nsv.DetectCommand([]git.LogEntry{
tests := []struct {
name string
command string
label string
}{
{
Message: `experimental feature has been added to search
nsv:pre`,
name: "DefaultToBeta",
command: "pre",
label: "beta",
},
})
assert.True(t, cmd.Prerelease)
assert.Equal(t, nsv.NoIncrement, cmd.Force)
assert.Equal(t, 46, match.Start)
assert.Equal(t, 53, match.End)
{
name: "Alpha",
command: "pre~alpha",
label: "alpha",
},
{
name: "Beta",
command: "pre~beta",
label: "beta",
},
{
name: "ReleaseCandidate",
command: "pre~rc",
label: "rc",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
cmd, _ := nsv.DetectCommand([]git.LogEntry{
{
Message: fmt.Sprintf(`experimental feature has been added to search
nsv:%s`, tt.command),
},
})
require.Equal(t, tt.label, cmd.Prerelease, "failed to match prerelease label")
})
}
}

func TestDetectMultipleCommands(t *testing.T) {
Expand All @@ -136,7 +166,7 @@ func TestDetectMultipleCommands(t *testing.T) {
nsv:pre,force~major`,
},
})
assert.True(t, cmd.Prerelease)
assert.Equal(t, "beta", cmd.Prerelease)
assert.Equal(t, nsv.MajorIncrement, cmd.Force)
assert.Equal(t, 33, match.Start)
assert.Equal(t, 52, match.End)
Expand Down Expand Up @@ -166,7 +196,7 @@ Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.c
{Message: `combine existing methods to reduce complexity of api
BREAKING-CHANGE: backwards compatibility with v1 is no longer supported
nsv: force~minor`},
nsv:force~minor`},
}
b.ResetTimer()

Expand Down
4 changes: 2 additions & 2 deletions internal/nsv/semver.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,14 @@ func bump(ver, format string, inc Increment, cmd Command) (string, error) {
bumpedVer = semv.IncPatch()
}

if cmd.Prerelease {
if cmd.Prerelease != "" {
if pTag.Prerelease() {
// As this is an existing prerelease, increment it as expected
label, inc, _ := strings.Cut(pTag.Pre, ".")
i, _ := strconv.Atoi(inc)
bumpedVer, _ = bumpedVer.SetPrerelease(fmt.Sprintf("%s.%d", label, i+1))
} else {
bumpedVer, _ = bumpedVer.SetPrerelease("beta.1")
bumpedVer, _ = bumpedVer.SetPrerelease(cmd.Prerelease + ".1")
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/nsv/semver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,14 @@ func TestNextVersionFromPrerelease(t *testing.T) {

func TestNextVersionPrerelease(t *testing.T) {
log := `> (main, origin/main) feat: initial restructure of documents for improved elastic search
nsv:pre
nsv:pre~alpha
> (tag: 0.2.0) feat: use the elastic scroll api to page results`
gittest.InitRepository(t, gittest.WithLog(log))
gitc, _ := git.NewClient()

next, err := nsv.NextVersion(gitc, nsv.Options{})
require.NoError(t, err)
assert.Equal(t, "0.3.0-beta.1", next.Tag)
assert.Equal(t, "0.3.0-alpha.1", next.Tag)
}

func TestNextVersionIncrementsPrerelease(t *testing.T) {
Expand Down

0 comments on commit e8e431b

Please sign in to comment.