Skip to content

Commit

Permalink
Merge pull request #1127 from mumoshu/describe-locks-parsing
Browse files Browse the repository at this point in the history
`@bot describe locks` parsing
  • Loading branch information
pirlodog1125 authored Aug 29, 2024
2 parents 422081a + 1401e54 commit 7113441
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
go-version: '1.19'
cache: true
- name: Run tests
run: go test ./...
run: GOCAT_TEST_KUBECONFIG=$HOME/.kube/config go test ./...
golangci:
name: lint
runs-on: ubuntu-latest
Expand Down
8 changes: 8 additions & 0 deletions slackcmd/describe_locks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package slackcmd

type DescribeLocks struct {
}

func (l *DescribeLocks) Name() string {
return "describe-locks"
}
47 changes: 43 additions & 4 deletions slackcmd/parse.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
package slackcmd

import (
"errors"
"fmt"
"regexp"
"strings"
)

type PatternError struct {
Pattern string
}

func (e PatternError) Error() string {
return fmt.Errorf("valid pattern is `%s`", e.Pattern).Error()
}

func patternError(pattern string) PatternError {
return PatternError{Pattern: pattern}
}

var lockUnlockPattern = regexp.MustCompile(`(unlock|lock) ([0-9a-zA-Z-]+) (staging|production|sandbox|stg|pro|prd)\s*(.*)`)

func Parse(text string) (Command, error) {
cmd, err1 := parseLockUnlock(text)
if err1 == nil {
return cmd, nil
} else if !errors.As(err1, &PatternError{}) {
return nil, fmt.Errorf("invalid command %q: %w", text, err1)
}

cmd, err2 := parseDescribeLocks(text)
if err2 == nil {
return cmd, nil
} else if !errors.As(err2, &PatternError{}) {
return nil, fmt.Errorf("invalid command %q: %w", text, err2)
}

return nil, fmt.Errorf("invalid command %q: %v, %v", text, err1, err2)
}

func parseLockUnlock(text string) (Command, error) {
match := findLockUnlock(text)
if match == nil {
return nil, fmt.Errorf("invalid command %q: valid pattern is 'lock|unlock <project> <env> [for <reason>]", text)
return nil, patternError("lock|unlock <project> <env> [for <reason>]")
}

var (
Expand All @@ -24,7 +55,7 @@ func Parse(text string) (Command, error) {
switch command {
case "unlock":
if reason != "" {
return nil, fmt.Errorf("invalid command %q: unlock command does not accept reason", text)
return nil, errors.New("unlock command does not accept reason")
}

return &Unlock{
Expand All @@ -33,11 +64,11 @@ func Parse(text string) (Command, error) {
}, nil
case "lock":
if reason == "" {
return nil, fmt.Errorf("invalid command %q: lock command requires reason", text)
return nil, errors.New("lock command requires reason")
}

if !strings.HasPrefix(reason, "for ") {
return nil, fmt.Errorf("invalid command %q: reason must start with 'for'", text)
return nil, errors.New("reason must start with 'for'")
}

reason = strings.TrimPrefix(reason, "for ")
Expand All @@ -52,6 +83,14 @@ func Parse(text string) (Command, error) {
}
}

func parseDescribeLocks(text string) (Command, error) {
if text != "describe locks" {
return nil, patternError("describe locks")
}

return &DescribeLocks{}, nil
}

func findLockUnlock(text string) [][]string {
return lockUnlockPattern.FindAllStringSubmatch(text, -1)
}
50 changes: 30 additions & 20 deletions slackcmd/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ var (

func TestParse(t *testing.T) {
type test struct {
name string
text string
want Command
err error
name string
text string
want Command
errMsg string
}

var tests = []test{}
Expand All @@ -37,9 +37,9 @@ func TestParse(t *testing.T) {
for i, p := range invalidProjects {
for j, e := range invalidENvs {
tests = append(tests, test{
name: fmt.Sprintf("lock with invalid project %d and env %d", i, j),
text: fmt.Sprintf("lock %s %s for deployment of revision a", p, e),
err: fmt.Errorf("invalid command %q: valid pattern is 'lock|unlock <project> <env> [for <reason>]", fmt.Sprintf("lock %s %s for deployment of revision a", p, e)),
name: fmt.Sprintf("lock with invalid project %d and env %d", i, j),
text: fmt.Sprintf("lock %s %s for deployment of revision a", p, e),
errMsg: fmt.Sprintf("invalid command %q: valid pattern is `lock|unlock <project> <env> [for <reason>]`, valid pattern is `describe locks`", fmt.Sprintf("lock %s %s for deployment of revision a", p, e)),
})
}
}
Expand All @@ -57,36 +57,46 @@ func TestParse(t *testing.T) {
for i, p := range invalidProjects {
for j, e := range invalidENvs {
tests = append(tests, test{
name: fmt.Sprintf("unlock with invalid project %d and env %d", i, j),
text: fmt.Sprintf("unlock %s %s", p, e),
err: fmt.Errorf("invalid command %q: valid pattern is 'lock|unlock <project> <env> [for <reason>]", fmt.Sprintf("unlock %s %s", p, e)),
name: fmt.Sprintf("unlock with invalid project %d and env %d", i, j),
text: fmt.Sprintf("unlock %s %s", p, e),
errMsg: fmt.Sprintf("invalid command %q: valid pattern is `lock|unlock <project> <env> [for <reason>]`, valid pattern is `describe locks`", fmt.Sprintf("unlock %s %s", p, e)),
})
}
}

tests = append(tests, test{
name: "unlock has redundant reason",
text: "unlock myproject1 production for deployment of revision a",
err: fmt.Errorf("invalid command %q: unlock command does not accept reason", "unlock myproject1 production for deployment of revision a"),
name: "unlock has redundant reason",
text: "unlock myproject1 production for deployment of revision a",
errMsg: fmt.Sprintf("invalid command %q: unlock command does not accept reason", "unlock myproject1 production for deployment of revision a"),
})

tests = append(tests, test{
name: "lock missing reason",
text: "lock myproject1 production",
err: fmt.Errorf("invalid command %q: lock command requires reason", "lock myproject1 production"),
name: "lock missing reason",
text: "lock myproject1 production",
errMsg: fmt.Sprintf("invalid command %q: lock command requires reason", "lock myproject1 production"),
})

tests = append(tests, test{
name: "unknown command",
text: "unknown myproject1 production for deployment of revision a",
err: fmt.Errorf("invalid command %q: valid pattern is 'lock|unlock <project> <env> [for <reason>]", "unknown myproject1 production for deployment of revision a"),
name: "unknown command",
text: "unknown myproject1 production for deployment of revision a",
errMsg: fmt.Sprintf("invalid command %q: valid pattern is `lock|unlock <project> <env> [for <reason>]`, valid pattern is `describe locks`", "unknown myproject1 production for deployment of revision a"),
})

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.text)
assert.Equal(t, tt.want, got, "result")
assert.Equal(t, tt.err, err, "error")
var errMsg string
if err != nil {
errMsg = err.Error()
}
assert.Equal(t, tt.errMsg, errMsg, "error")
})
}

t.Run("describe locks", func(t *testing.T) {
got, err := Parse("describe locks")
assert.NoError(t, err)
assert.IsType(t, &DescribeLocks{}, got)
})
}

0 comments on commit 7113441

Please sign in to comment.