Skip to content

Commit

Permalink
Merge pull request #19 from innogames/variables
Browse files Browse the repository at this point in the history
custom variables which can be used in macros etc
  • Loading branch information
brainexe authored Jan 9, 2020
2 parents f84f181 + 7930979 commit 4aeb1ff
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 1 deletion.
2 changes: 2 additions & 0 deletions command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/innogames/slack-bot/command/mqtt"
"github.com/innogames/slack-bot/command/pullrequest"
"github.com/innogames/slack-bot/command/queue"
"github.com/innogames/slack-bot/command/variables"
"github.com/innogames/slack-bot/command/weather"
"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -49,6 +50,7 @@ func GetCommands(slackClient client.SlackClient, cfg config.Config, logger *logr
queue.NewListCommand(slackClient),

custom.GetCommand(slackClient),
variables.GetCommand(slackClient),
)

// jenkins
Expand Down
2 changes: 1 addition & 1 deletion command/macro.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (c *macroCommand) Execute(event slack.MessageEvent) bool {

// extract the parameters from regexp
params := util.RegexpResultToParams(macro.re, match)
params["sender"] = event.User
params["userId"] = event.User

for _, commandText := range macro.config.Commands {
command, err := util.CompileTemplate(commandText)
Expand Down
22 changes: 22 additions & 0 deletions command/variables/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package variables

import (
"fmt"

"github.com/innogames/slack-bot/bot/matcher"
"github.com/nlopes/slack"
)

func (c *command) Add(match matcher.Result, event slack.MessageEvent) {
name := match.GetString("name")
value := match.GetString("value")

list := loadList(event.User)
list[name] = value
storeList(event, list)

c.slackClient.Reply(
event,
fmt.Sprintf("Added variable: `%s` = `%s`.", name, value),
)
}
34 changes: 34 additions & 0 deletions command/variables/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package variables

import (
"github.com/innogames/slack-bot/bot"
"github.com/innogames/slack-bot/bot/matcher"
"github.com/innogames/slack-bot/client"
)

// GetCommand returns a set of all commands to manage user specific variables
func GetCommand(slackClient client.SlackClient) bot.Command {
return &command{slackClient}
}

type command struct {
slackClient client.SlackClient
}

func (c *command) GetMatcher() matcher.Matcher {
return matcher.NewGroupMatcher(
matcher.NewRegexpMatcher("(add|set) variable '?(?P<name>.*?)'? '?(?P<value>.*?)'?", c.Add),
matcher.NewRegexpMatcher("(delete|remove) variable '?(?P<name>.*?)'?", c.Delete),
matcher.NewTextMatcher("list variables", c.List),
)
}

func (c *command) GetHelp() []bot.Help {
return []bot.Help{
{
"custom variables",
"",
[]string{},
},
}
}
17 changes: 17 additions & 0 deletions command/variables/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package variables

import (
"fmt"
"github.com/innogames/slack-bot/bot/matcher"
"github.com/nlopes/slack"
)

func (c *command) Delete(match matcher.Result, event slack.MessageEvent) {
name := match.GetString("name")

list := loadList(event.User)
delete(list, name)
storeList(event, list)

c.slackClient.Reply(event, fmt.Sprintf("Okay, I deleted variable: `%s`", name))
}
112 changes: 112 additions & 0 deletions command/variables/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package variables

import (
"testing"

"github.com/innogames/slack-bot/bot"
"github.com/innogames/slack-bot/mocks"
"github.com/nlopes/slack"
"github.com/stretchr/testify/assert"
)

func TestCustomCommands(t *testing.T) {
slackClient := &mocks.SlackClient{}
commands := bot.Commands{}
variablesCommand := GetCommand(slackClient).(*command)
commands.AddCommand(variablesCommand)

t.Run("Invalid command", func(t *testing.T) {
event := slack.MessageEvent{}
event.User = "user1"
event.Text = "notify me not"

actual := commands.Run(event)
assert.Equal(t, false, actual)
})

t.Run("List empty variables", func(t *testing.T) {
event := slack.MessageEvent{}
event.Text = "list variables"
event.User = "user1"
slackClient.On("Reply", event, "No variables define yet. Use `add variable 'defaultServer' 'beta'`").Return("")
actual := commands.Run(event)
assert.Equal(t, true, actual)
})

t.Run("Add a variable with invalid syntax", func(t *testing.T) {
event := slack.MessageEvent{}
event.User = "user1"
event.Text = "add variable name"
actual := commands.Run(event)
assert.Equal(t, false, actual)
})

t.Run("Add valid variable", func(t *testing.T) {
event := slack.MessageEvent{}
event.User = "user1"
event.Text = "add variable 'myKey' 'myValue'"

slackClient.On("Reply", event, "Added variable: `myKey` = `myValue`.").Return("")
actual := commands.Run(event)

assert.Equal(t, true, actual)
})

t.Run("List commands should list new variable", func(t *testing.T) {
event := slack.MessageEvent{}
event.User = "user1"
event.Text = "list variables"

slackClient.On("Reply", event, "You defined 1 variables:\n - myKey: `myValue`")
actual := commands.Run(event)

assert.Equal(t, true, actual)
})

t.Run("Template with unknown user", func(t *testing.T) {

function := variablesCommand.GetTemplateFunction()["customVariable"]

actual := function.(func(string, string) string)("U123", "myKey")
assert.Equal(t, "_unknown variable: myKey_", actual)
})

t.Run("Template with unknown user", func(t *testing.T) {

function := variablesCommand.GetTemplateFunction()["customVariable"]

actual := function.(func(string, string) string)("user1", "myKey2")
assert.Equal(t, "_unknown variable: myKey2_", actual)
})

t.Run("Template with known variable", func(t *testing.T) {

function := variablesCommand.GetTemplateFunction()["customVariable"]

actual := function.(func(string, string) string)("user1", "myKey")
assert.Equal(t, "myValue", actual)
})

t.Run("Delete variable with invalid syntax", func(t *testing.T) {
event := slack.MessageEvent{}
event.Text = "delete variable"
event.User = "user1"

actual := commands.Run(event)

assert.Equal(t, false, actual)
})

t.Run("Delete variable", func(t *testing.T) {
event := slack.MessageEvent{}
event.Text = "delete variable myKey"
event.User = "user1"

slackClient.On("Reply", event, "Okay, I deleted variable: `myKey`")

actual := commands.Run(event)

assert.Equal(t, true, actual)
})

}
23 changes: 23 additions & 0 deletions command/variables/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package variables

import (
"fmt"

"github.com/innogames/slack-bot/bot/matcher"
"github.com/nlopes/slack"
)

func (c *command) List(match matcher.Result, event slack.MessageEvent) {
list := loadList(event.User)
if len(list) == 0 {
c.slackClient.Reply(event, "No variables define yet. Use `add variable 'defaultServer' 'beta'`")
return
}

responseText := fmt.Sprintf("You defined %d variables:", len(list))
for name, value := range list {
responseText += fmt.Sprintf("\n - %s: `%s`", name, value)
}

c.slackClient.Reply(event, responseText)
}
22 changes: 22 additions & 0 deletions command/variables/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package variables

import (
"github.com/innogames/slack-bot/bot/storage"
"github.com/nlopes/slack"
)

const storeKey = "user_variables"

type list map[string]string

func loadList(userId string) list {
list := make(list, 0)

storage.Read(storeKey, userId, &list)

return list
}

func storeList(event slack.MessageEvent, list list) {
storage.Write(storeKey, event.User, list)
}
20 changes: 20 additions & 0 deletions command/variables/template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package variables

import (
"fmt"
"text/template"
)

func (c *command) GetTemplateFunction() template.FuncMap {
return template.FuncMap{
"customVariable": func(userId string, name string) string {
list := loadList(userId)

if value, ok := list[name]; ok {
return value
}

return fmt.Sprintf("_unknown variable: %s_", name)
},
}
}
19 changes: 19 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ It's also possible to get a notification when there is a state change in a certa
**Example**
- `watch ticket PROJ-12234`


## Custom variables
Configure user specific variables to customize bot behaviour. E.g. each developer has his own server environment.

**Example:** Having this global config:
```
macros:
- name: deploy
trigger: "deploy (?P<branch>.*)"
commands:
- deploy {{.branch}} to {{ customVariable "defaultServer" }}
```

User can define his default environment once by using `set variable serverEnvironment aws-02`.

Then the `deploy feature-123` will deploy the branch to the defined `aws-02` environment.
Each user can define his own variables.


## Quiz command
If you need a small break and want to play a little quiz game you can do so by calling this command.
No more than 50 questions are allowed.
Expand Down

0 comments on commit 4aeb1ff

Please sign in to comment.