Skip to content

Commit

Permalink
Merge pull request #12 from tigerteufel85/boggy-11/jql-time-support
Browse files Browse the repository at this point in the history
Boggy 11/jql time support
  • Loading branch information
tigerteufel85 committed Jan 5, 2022
2 parents d1eb691 + f43327d commit 61f141a
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 55 deletions.
4 changes: 1 addition & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
language: go

go:
- "1.11"
- "1.12"
- "1.13"
- "1.17"

env:
- GO111MODULE=on
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
FROM golang:1.11-alpine as builder
FROM golang:1.17-alpine as builder
ENV GO111MODULE=on
WORKDIR /boggy/
COPY . ./

RUN apk add git
RUN go mod tidy
RUN CGO_ENABLED=0 go build -o /app boggy.go

FROM alpine:latest as alpine
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ all: clean dep bin/boggy

bin/boggy: dep
mkdir -p bin/
go mod tidy
GO111MODULE=on go build -ldflags="-s -w" -o bin/boggy *.go

clean:
Expand Down
7 changes: 4 additions & 3 deletions bot/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bot

import (
"bufio"
"fmt"
"github.com/nlopes/slack"
"github.com/tigerteufel85/boggy/client"
"github.com/tigerteufel85/boggy/config"
Expand Down Expand Up @@ -78,7 +79,7 @@ func getAllowedUsers() []User {

// load the public and private channels and list of all users from current space
func (b *Bot) loadChannelsUsersAndProjects(config *config.Config) error {
// load channels
fmt.Println("...Loading Channels")
var err error
var cursor string
var channels []slack.Channel
Expand All @@ -100,7 +101,7 @@ func (b *Bot) loadChannelsUsersAndProjects(config *config.Config) error {
}
}

// load users
fmt.Println("...Loading Users")
users, err := b.slackClient.GetUsers()
if err != nil {
return err
Expand All @@ -111,7 +112,7 @@ func (b *Bot) loadChannelsUsersAndProjects(config *config.Config) error {
client.Users[user.ID] = user.Name
}

// load projects
fmt.Println("...Loading Projects")
client.Projects = make(map[string]string)
for _, project := range config.Jira.Projects {
client.Projects[project] = project
Expand Down
1 change: 1 addition & 0 deletions command/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func GetDefaultCommands(slackClient client.SlackClient, jira *jira.Client, confi
Commands: []bot.Command{
NewHelp(slackClient, &commands),
NewJiraIssues(slackClient, jira, config.Jira, config.Replies, config.Regex),
NewJiraIssuesSingle(slackClient, jira, config.Jira, config.Replies, config.Regex),
NewJiraIssue(slackClient, jira, config.Jira, config.Replies),
NewJiraOverview(slackClient, jira, config.Jira, config.Replies, config.Regex),
NewAdminAddUser(slackClient),
Expand Down
114 changes: 114 additions & 0 deletions command/jira_issues_single.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package command

import (
"context"
"github.com/nlopes/slack"
"github.com/tigerteufel85/boggy/bot"
"github.com/tigerteufel85/boggy/client"
"github.com/tigerteufel85/boggy/config"
"github.com/tigerteufel85/boggy/utils"
"gopkg.in/andygrunwald/go-jira.v1"
"strings"
)

type jiraIssuesSingle struct {
slackClient client.SlackClient
jira *jira.Client
jiraCfg config.JiraConfig
jiraReplies config.ReplyConfig
regex config.RegexConfig
}

func NewJiraIssuesSingle(slackClient client.SlackClient, jira *jira.Client, jiraCfg config.JiraConfig, jiraReplies config.ReplyConfig, regex config.RegexConfig) *jiraIssuesSingle {
return &jiraIssuesSingle{
slackClient,
jira,
jiraCfg,
jiraReplies,
regex,
}
}

func (c *jiraIssuesSingle) GetName() string {
return "jira single"
}

func (c *jiraIssuesSingle) IsValid(b *bot.Bot, command string) bool {
if !strings.HasPrefix(command, c.GetName()) {
return false
}

_, err := utils.NewJQL(c.regex, command).BuildJqlQuery(c.jiraCfg)
if err != nil {
return false
}

return true
}

func (c *jiraIssuesSingle) Execute(ctx context.Context, b *bot.Bot, eventText string, event *slack.MessageEvent, user bot.User) bool {
if !strings.HasPrefix(eventText, c.GetName()) {
return false
}

// Create JQL Query
jql := utils.NewJQL(c.regex, eventText)
query, err := jql.BuildJqlQuery(c.jiraCfg)
if err != nil {
c.slackClient.Respond(event, err.Error())
return true
}

// Search issues on JIRA
issues, searchResponse, err := c.jira.Issue.Search(query, &jira.SearchOptions{MaxResults: 50, Expand: "names"})
if err != nil {
auth, _ := c.slackClient.AuthTest()
if user.Name != auth.User {
c.slackClient.Respond(event, err.Error())
}
return true
}

if searchResponse.Total == 0 {
return true
}

// Get all fields
allFields, _, err := c.jira.Field.GetList()
if err != nil {
auth, _ := c.slackClient.AuthTest()
if user.Name != auth.User {
c.slackClient.Respond(event, err.Error())
}
return true
}

for _, issue := range issues {
customFields, _, err := c.jira.Issue.GetCustomFields(issue.ID)
if err != nil {
auth, _ := c.slackClient.AuthTest()
if user.Name != auth.User {
c.slackClient.Respond(event, err.Error())
}
return true
}

responseText := utils.NewLayout(c.regex, eventText).BuildSimpleTextResponse(c.jiraCfg, issue, customFields, allFields, jql)

c.slackClient.Respond(event, responseText)
}

return true
}

func (c *jiraIssuesSingle) GetHelp() []bot.Help {
return []bot.Help{
{
"jira issues single",
"creates a slack response for each crm sale which will start, the placeholders will be replaced respectively",
[]string{
"jira single <project:crm><issuetype:Campaign><offset-field:Start Time><offset-time:18h><jql>“Campaign Category” = Sale</jql><sort:starttime><title>A sale will start in %component% %date% at %time% : %summary%</title><time:90h>",
},
},
}
}
1 change: 1 addition & 0 deletions command/schedule_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func (c *scheduleAdd) IsValid(b *bot.Bot, command string) bool {
func (c *scheduleAdd) getAllowedCommands() []bot.Command {
return []bot.Command{
NewJiraIssues(c.slackClient, c.jira, c.jiraCfg, c.jiraReplies, c.regex),
NewJiraIssuesSingle(c.slackClient, c.jira, c.jiraCfg, c.jiraReplies, c.regex),
NewJiraOverview(c.slackClient, c.jira, c.jiraCfg, c.jiraReplies, c.regex),
}
}
Expand Down
14 changes: 12 additions & 2 deletions config/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ jira:
- DEF
- GHI

location: "Europe/Berlin"

components:
"Backend": ":be:"
"Frontend": ":fe:"

statuses:
open: "Unresolved"
unresolved: "Unresolved"
Expand Down Expand Up @@ -51,6 +57,8 @@ jira:
"Raccoon": ":raccoon:"
"Double Trouble": ":busts_in_silhouette:"

timeformat: "2006-01-02 03:04"

bugoverview:
listall:
- ABC
Expand Down Expand Up @@ -154,9 +162,11 @@ regex:
jirasorting: "(?i:<sort:)([a-zA-Z]*)(>)"
jirastatus: "(?i:<status:)([a-zA-Z]*)(>)"
jiratime: "(?i:<time:)([0-9]*[mhdw])(>)"
jiraoffsettime: "(?i:<offset-time:)([0-9]+[mhdw])(>)"
jiraoffsetfield: "(?i:<offset-field:)([a-zA-Z ]*)(>)"
replycolor: "(?i:<color:)([a-zA-Z0-9]*)(>)"
replylayout: "(?i:<layout:)([a-zA-Z0-9]*)(>)"
replylist: "(?i:<list:)([a-zA-Z0-9]*)(>)"
replytitle: "(?i:<title>)([a-zA-Z0-9 .,;:=\"()><\\-+!?&|_]*)(</title>)"
croncommand: "(?i:<command>)([a-zA-Z0-9 .,;~:=\"()><\\-+!&|\\/_]*)(</command>)"
replytitle: "(?i:<title>)([a-zA-Z0-9 .,;:=\"()><\\-%+!?&|_]*)(</title>)"
croncommand: "(?i:<command>)([a-zA-Z0-9 .,;~:=\"()><\\-%+!&|\\/_]*)(</command>)"
crontime: "(?i:<cron:)([0-9 *-?\\/]*)(>)"
35 changes: 20 additions & 15 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ type JiraConfig struct {
Username string
Password string
Projects []string `yaml:",flow"`
Location string
Components map[string]string `yaml:",flow"`
Statuses map[string]string `yaml:",flow"`
Priorities map[string]Priority `yaml:",flow"`
FeatureTeams TeamConfig
TimeFormat string
BugOverview struct {
ListAll []string `yaml:",flow"`
All string
Expand Down Expand Up @@ -68,19 +71,21 @@ type TeamConfig struct {

// RegexConfig contains the various regex expressions to parse Slack messages for commands
type RegexConfig struct {
JiraAssignee string
JiraCustom string
JiraIssueType string
JiraOption string
JiraPriority string
JiraProject string
JiraSorting string
JiraStatus string
JiraTime string
ReplyColor string
ReplyLayout string
ReplyList string
ReplyTitle string
CronCommand string
CronTime string
JiraAssignee string
JiraCustom string
JiraIssueType string
JiraOption string
JiraPriority string
JiraProject string
JiraSorting string
JiraStatus string
JiraTime string
JiraOffsetTime string
JiraOffsetField string
ReplyColor string
ReplyLayout string
ReplyList string
ReplyTitle string
CronCommand string
CronTime string
}
22 changes: 10 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
module github.com/tigerteufel85/boggy

go 1.17

require (
github.com/imdario/mergo v0.3.7
github.com/nlopes/slack v0.5.0
gopkg.in/andygrunwald/go-jira.v1 v1.6.0
gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5
gopkg.in/yaml.v2 v2.2.2
)

require (
github.com/ae6rt/retry v2.0.0+incompatible // indirect
github.com/blend/go-sdk v1.1.1 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/gorilla/websocket v1.4.0 // indirect
github.com/imdario/mergo v0.3.7
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect
github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 // indirect
github.com/nlopes/slack v0.5.0
github.com/pkg/errors v0.8.1 // indirect
github.com/stretchr/testify v1.3.0 // indirect
github.com/trivago/tgo v1.0.5 // indirect
github.com/wcharczuk/go-chart v2.0.1+incompatible
github.com/xoom/stash v1.3.1
golang.org/x/image v0.0.0-20190118043309-183bebdce1b2 // indirect
gopkg.in/andygrunwald/go-jira.v1 v1.6.0
gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5
gopkg.in/yaml.v2 v2.2.2
)
13 changes: 12 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Boggy
[![Build Status](https://travis-ci.com/tigerteufel85/boggy.svg)](https://travis-ci.com/tigerteufel85/boggy)
[![Build Status](https://app.travis-ci.com/tigerteufel85/boggy.svg)](https://app.travis-ci.com/github/tigerteufel85/boggy)
[![GoDoc](https://godoc.org/github.com/tigerteufel85/boggy?status.svg)](https://godoc.org/github.com/innogames/boggy)
[![Go Report Card](https://goreportcard.com/badge/github.com/tigerteufel85/boggy)](https://goreportcard.com/report/github.com/tigerteufel85/boggy)
[![Release](https://img.shields.io/github/release/tigerteufel85/boggy.svg)](https://github.com/tigerteufel85/boggy/releases)
Expand Down Expand Up @@ -104,6 +104,17 @@ Query information from Jira for or a whole list of tickets.
- filters by a JQL query, please do not add any ordering to it
- please use with care as it makes the commands flexible but also more error prone

## JIRA Single
Query information from Jira and posts each issue one by one.

### Parameters
Generally the same parameters as for "JIRA Issues" can be used but there are a few additional ones.

#### `<offset-field:Start Time>` + `<offset-time:1h>` + `<time:10m>`
- queries tickets where the time from the Start Time field starts in 1h and lasts for 10m
- if current time is 2022-01-01 10:00 and with an offset of 1h and time of 10m
- it creates a query like `"Start Time" >= "2022-01-01 11:00" AND "Start Time" <= "2022-01-01 11:10"`

## Bugs Overview
Creates an overview of the current bug status of a project.

Expand Down

0 comments on commit 61f141a

Please sign in to comment.