tests: rework passive tests into native go tests

this commit re-works the basic.t tests and administers them using go's
native testing suite.

Signed-off-by: ldelossa <ldelossa@redhat.com>
This commit is contained in:
ldelossa
2020-09-04 21:15:55 -04:00
committed by Louis DeLosSantos
parent 42e5d23f63
commit a8c961fe19
11 changed files with 1271 additions and 21 deletions
+49
View File
@@ -0,0 +1,49 @@
config:
stop: true
endpoint: https://go-jira.atlassian.net
password-source: stdin
user: gojira
login: gojira@corybennett.org
project: BASIC
queries:
todo: >-
resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'To Do'
custom-commands:
- name: env
help: print the JIRA environment variables available to custom commands
script: |-
env | sort | grep JIRA
- name: print-project
help: print the name of the configured project
script: "echo $JIRA_PROJECT"
- name: jira-path
help: print the path the jira command that is running this alias
script: |-
echo {{jira}}
- name: mine
help: display issues assigned to me
script: |-
if [ -n "$JIRA_PROJECT" ]; then
# if `project: ...` configured just list the issues for current project
{{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() and project = $JIRA_PROJECT ORDER BY priority asc, created"
else
# otherwise list issues for all project
{{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() ORDER BY priority asc, created"
fi
- name: argtest
help: testing passing args
script: |-
echo {{args.ARG}}
args:
- name: ARG
help: string to echo for testing
- name: opttest
help: testing passing option flags
script: |-
echo {{options.OPT}}
options:
- name: OPT
help: string to echo for testing
+1
View File
@@ -0,0 +1 @@
template: list
+56
View File
@@ -0,0 +1,56 @@
package test
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
)
// withApiLogin is a hack to provide an api token on every command, this means keyring
// and gpg is not necessary to run the testing suite.
//
// a buffer containing stdout will be returned to the caller if no error is encountered.
// this still expects a config file is in a parent where the test runs for project
// and endpoint details.
func withApiLogin(login string, token string, cmd *exec.Cmd) (bytes.Buffer, error) {
var buf bytes.Buffer
cmd.Args = append(cmd.Args, "--login", login)
diag := fmt.Sprintf("--- running command: %+v ---\n", cmd.Args)
io.WriteString(os.Stdout, diag)
// write to stdout and also to our buffer
out := io.MultiWriter(&buf, os.Stdout)
cmd.Stdout = out
e := io.MultiWriter(&buf, os.Stderr)
cmd.Stderr = e
in, err := cmd.StdinPipe()
if err != nil {
return buf, err
}
err = cmd.Start()
if err != nil {
return buf, err
}
_, err = io.WriteString(in, token)
if err != nil {
return buf, err
}
in.Close()
err = cmd.Wait()
if err != nil {
return buf, err
}
diag = fmt.Sprintf("--- finished command: %+v ---\n\n", cmd.Args)
io.WriteString(os.Stdout, diag)
return buf, nil
}
+98
View File
@@ -0,0 +1,98 @@
package test
import (
"bytes"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
)
func checkDiff(t *testing.T, buf bytes.Buffer, expect string, formats ...interface{}) {
expect = fmt.Sprintf(expect, formats...)
if !cmp.Equal(expect, buf.String()) {
t.Fatal(
cmp.Diff(
buf.String(),
expect,
),
)
}
}
func checkCreateIssue(t *testing.T, buf bytes.Buffer, endpoint string) string {
out := strings.Split(buf.String(), " ")
if len(out) < 3 {
t.Fatalf("unexpected split count on create output: %v", buf.String())
}
issue := out[1]
expect := fmt.Sprintf("OK %s %s/browse/%s\n", issue, endpoint, issue)
if !cmp.Equal(expect, buf.String()) {
t.Fatal(
cmp.Diff(
buf.String(),
expect,
),
)
}
return issue
}
func checkEditIssue(t *testing.T, buf bytes.Buffer, issue, endpoint string) {
out := strings.Split(buf.String(), " ")
if len(out) < 3 {
t.Fatalf("unexpected split count on create output: %v", buf.String())
}
editedIssue := out[1]
expect := fmt.Sprintf("OK %s %s/browse/%s\n", issue, endpoint, issue)
if !cmp.Equal(expect, buf.String()) {
t.Fatal(
cmp.Diff(
buf.String(),
expect,
),
)
}
if !cmp.Equal(editedIssue, issue) {
t.Fatal(
cmp.Diff(
editedIssue,
issue,
),
)
}
}
func checkIssueInOutput(t *testing.T, buf bytes.Buffer, issue string) {
if !strings.Contains(buf.String(), issue) {
t.Fatalf("issue %s not located in stdout: %s", issue, buf.String())
}
}
func checkIssueNotInOutput(t *testing.T, buf bytes.Buffer, issue string) {
if strings.Contains(buf.String(), issue) {
t.Fatalf("issue %s not located in stdout: %s", issue, buf.String())
}
}
func checkBlockIssue(t *testing.T, buf bytes.Buffer, issue, blocker, endpoint string) {
checkDualIssues(t, buf, blocker, issue, endpoint)
}
func checkDupIssue(t *testing.T, buf bytes.Buffer, issue, duplicate, endpoint string) {
checkDualIssues(t, buf, issue, duplicate, endpoint)
}
func checkDualIssues(t *testing.T, buf bytes.Buffer, first, second, endpoint string) {
lines := strings.Split(buf.String(), "\n")
if len(lines) < 2 {
t.Fatalf("unexpected split count on create output: %v", buf.String())
}
testBuf := bytes.NewBuffer([]byte(lines[0] + "\n"))
checkEditIssue(t, *testBuf, first, endpoint)
testBuf = bytes.NewBuffer([]byte(lines[1] + "\n"))
checkEditIssue(t, *testBuf, second, endpoint)
}
+815
View File
@@ -0,0 +1,815 @@
package test
import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"
)
const (
endpoint = "https://go-jira.atlassian.net"
goJiraApiToken = "Rw1cPlKI40TJeEl1Pj88A5ED"
goJiraLogin = "gojira@corybennett.org"
mothraApiToken = "UNXrI9gq5p0LWUtblAxDA7A6"
mothraLogin = "mothra@corybennett.org"
)
var jira string = "../dist/github.com/go-jira/jira-linux-amd64"
func Test_CLI(t *testing.T) {
// setup the jira cli environment
jira, err := filepath.Abs(jira)
if err != nil {
t.Fatal(err)
}
if !filepath.IsAbs(jira) {
t.Fatalf("could not obtain absolute path to jira binary")
}
if _, err := os.Stat(jira); err != nil {
t.Fatalf("could not stat %v: %v", jira, err)
}
os.Setenv("COLUMNS", "149")
os.Setenv("JIRA_LOG_FORMAT", "%{level:-5s} %{message}")
os.Setenv("ENDPOINT", endpoint)
os.Setenv("JIRACLOUD", "1")
t.Run("basic", test_Basic)
t.Run("pagination", test_Pagination)
}
// test_Basic will test the basic functionality required in the cli
func test_Basic(t *testing.T) {
// we'll reassign these often, just create
// them here.
var buf bytes.Buffer
var err error
// Create an issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
createIssue(
jira,
"BASIC",
"summary",
"description",
),
)
if err != nil {
t.Fatalf("cmd failed. stdout: %v err: %v", buf.String(), err)
}
issue := checkCreateIssue(t, buf, endpoint)
// View the issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
priority: Medium
votes: 0
description: |
description
`, issue)
// confirm new issue shows in project list
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(
jira,
"BASIC",
"", // empty string means do not use a named query
"", // empty string means do not use raw query
"", // empty string means do not use a template
"", // empty string means do not limit response
),
)
checkIssueInOutput(t, buf, issue)
// confirm issue appears with named query
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(
jira,
"BASIC",
"todo",
"",
"",
"",
),
)
checkIssueInOutput(t, buf, issue)
// confirm issue appears with table template
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(
jira,
"BASIC",
"",
"",
"table",
"",
),
)
checkIssueInOutput(t, buf, issue)
// edit an issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
editIssue(
jira,
issue,
"edit comment",
"priority=High",
"",
),
)
checkEditIssue(t, buf, issue, endpoint)
// edit multiple issues with query and check comments updated
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
editIssue(
jira,
issue,
"bulk edit comment",
"priority=High",
`resolution = unresolved AND project = 'BASIC' AND status = 'To Do'`,
),
)
checkEditIssue(t, buf, issue, endpoint)
// view the issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
priority: High
votes: 0
description: |
description
comments:
- | # GoJira, a minute ago
edit comment
- | # GoJira, a minute ago
bulk edit comment
`, issue)
// try invalid close of issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
closeIssue(
jira,
issue,
),
)
checkDiff(t, buf, `ERROR Invalid Transition "close" from "To Do", Available: To Do, In Progress, In Review, Done
`)
// put issue in done state
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
doneIssue(
jira,
issue,
),
)
checkEditIssue(t, buf, issue, endpoint)
// make sure our resolved issue is not present in the project
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(
jira,
"BASIC",
"",
"",
"",
"",
),
)
checkIssueNotInOutput(t, buf, issue)
// create two new issues to test duplicating
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
createIssue(
jira,
"BASIC",
"summary",
"description",
),
)
issue = checkCreateIssue(t, buf, endpoint)
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
createIssue(
jira,
"BASIC",
"dup",
"dup",
),
)
dup := checkCreateIssue(t, buf, endpoint)
// mark issue as duplicate
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
dupIssue(
jira,
issue,
dup,
),
)
checkDupIssue(t, buf, issue, dup, endpoint)
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers:
depends: %s[Done]
priority: Medium
votes: 0
description: |
description
`, issue, dup)
// check dup is resolved and not in listed issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(jira,
"BASIC",
"",
"",
"",
""),
)
checkIssueNotInOutput(t, buf, dup)
// create blocker issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
createIssue(
jira,
"BASIC",
"blocks",
"blocks",
),
)
blocker := checkCreateIssue(t, buf, endpoint)
// set blocker
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
blockIssue(
jira,
blocker,
issue,
),
)
checkBlockIssue(t, buf, blocker, issue, endpoint)
// confirm blocker shows up when viewing issue
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers: %s[To Do]
depends: %s[Done]
priority: Medium
votes: 0
description: |
description
`, issue, blocker, dup)
// confirm both issues are unresolved
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(
jira,
"BASIC",
"",
"",
"",
"",
),
)
checkIssueInOutput(t, buf, issue)
checkIssueInOutput(t, buf, blocker)
// //
// begin using mothra user //
// //
// use mothra to vote for main issue
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
voteIssue(
jira,
issue,
false,
),
)
checkEditIssue(t, buf, issue, endpoint)
// view issue to confirm vote
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers: %s[To Do]
depends: %s[Done]
priority: Medium
votes: 1
description: |
description
`, issue, blocker, dup)
// down vote and confirm
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
voteIssue(
jira,
issue,
true, // down vote true
),
)
checkEditIssue(t, buf, issue, endpoint)
// view issue to confirm vote
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers: %s[To Do]
depends: %s[Done]
priority: Medium
votes: 0
description: |
description
`, issue, blocker, dup)
// TODO(louis): skipping watcher test for now until a
// "watchers" command is implemented.
// set blocker to "In Progress"
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
transIssue(
jira,
"In Progress",
blocker,
),
)
checkEditIssue(t, buf, blocker, endpoint)
// set it back to "To Do"
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
todoIssue(
jira,
blocker,
),
)
checkEditIssue(t, buf, blocker, endpoint)
// set it to "In Review"
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
transIssue(
jira,
"review",
blocker,
),
)
checkEditIssue(t, buf, blocker, endpoint)
// set it back to "To Do"
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
todoIssue(
jira,
blocker,
),
)
checkEditIssue(t, buf, blocker, endpoint)
// set it to in progress
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
progIssue(
jira,
blocker,
),
)
checkEditIssue(t, buf, blocker, endpoint)
// set it to in done
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
doneIssue(
jira,
blocker,
),
)
checkEditIssue(t, buf, blocker, endpoint)
// confirm blocker is done
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers: %s[Done]
depends: %s[Done]
priority: Medium
votes: 0
description: |
description
`, issue, blocker, dup)
// verify we can add comment
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
commentIssue(
jira,
issue,
"Yo, Comment",
),
)
checkEditIssue(t, buf, issue, endpoint)
// verify we can see comment
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
issue,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers: %s[Done]
depends: %s[Done]
priority: Medium
votes: 0
description: |
description
comments:
- | # Mothra, a minute ago
Yo, Comment
`, issue, blocker, dup)
// verify we can add labels
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
addLabelsIssue(
jira,
blocker,
"test-label",
"another-label",
),
)
checkEditIssue(t, buf, blocker, endpoint)
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
blocker,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: Done
summary: blocks
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers:
depends: %s[To Do]
priority: Medium
votes: 0
labels: another-label, test-label
description: |
blocks
`, blocker, issue)
// verify we can remove labels
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
removeLabelsIssue(
jira,
blocker,
"another-label",
),
)
checkEditIssue(t, buf, blocker, endpoint)
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
blocker,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: Done
summary: blocks
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers:
depends: %s[To Do]
priority: Medium
votes: 0
labels: test-label
description: |
blocks
`, blocker, issue)
// verify we can replace labels
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
setLabelsIssue(
jira,
blocker,
"more-label",
"better-label",
),
)
checkEditIssue(t, buf, blocker, endpoint)
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
blocker,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: Done
summary: blocks
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers:
depends: %s[To Do]
priority: Medium
votes: 0
labels: better-label, more-label
description: |
blocks
`, blocker, issue)
// verify mothra can take an issue
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
takeIssue(
jira,
blocker,
),
)
checkEditIssue(t, buf, blocker, endpoint)
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
blocker,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: Done
summary: blocks
project: BASIC
issuetype: Bug
assignee: Mothra
reporter: GoJira
blockers:
depends: %s[To Do]
priority: Medium
votes: 0
labels: better-label, more-label
description: |
blocks
`, blocker, issue)
// verify martha can give the issue back
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
giveIssue(
jira,
blocker,
"gojira",
),
)
checkEditIssue(t, buf, blocker, endpoint)
buf, err = withApiLogin(
mothraLogin,
mothraApiToken,
viewIssue(
jira,
blocker,
),
)
checkDiff(t, buf, `issue: %s
created: a minute ago
status: Done
summary: blocks
project: BASIC
issuetype: Bug
assignee: GoJira
reporter: GoJira
blockers:
depends: %s[To Do]
priority: Medium
votes: 0
labels: better-label, more-label
description: |
blocks
`, blocker, issue)
}
func test_Pagination(t *testing.T) {
var buf bytes.Buffer
var err error
// note:
// we test limit+1 to handle extra newline split
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(
jira,
"BASIC",
"",
"project = 'BASIC' AND status = 'Done'", // query
"",
"102",
),
)
if err != nil {
t.Fatalf("failed to list issues. stderr:%v err: %v", buf.String(), err)
}
if len(strings.Split(buf.String(), "\n")) != 103 {
t.Fatalf("got: %v want: %v", len(strings.Split(buf.String(), "\n")), 103)
}
buf, err = withApiLogin(
goJiraLogin,
goJiraApiToken,
listIssues(
jira,
"BASIC",
"",
"project = 'BASIC' AND status = 'Done'", // query
"", // empty string means do not use a template
"1",
),
)
if err != nil {
t.Fatalf("failed to list issues. stderr:%v err: %v", buf.String(), err)
}
if len(strings.Split(buf.String(), "\n")) != 2 {
t.Fatalf("got: %v want: %v", len(strings.Split(buf.String(), "\n")), 2)
}
}
+226
View File
@@ -0,0 +1,226 @@
package test
import (
"os/exec"
)
func session(jira string) *exec.Cmd {
cmd := exec.Command(
jira,
"session",
)
return cmd
}
func createIssue(jira, project, summary, description string) *exec.Cmd {
sum := "summary=" + summary
desc := "description=" + description
cmd := exec.Command(
jira,
"create",
"--project", project,
"-o", sum,
"-o", desc,
"--noedit",
)
return cmd
}
func viewIssue(jira, issue string) *exec.Cmd {
return exec.Command(
jira,
"view",
issue,
)
}
func listIssues(jira, project, query, rawquery, template, limit string) *exec.Cmd {
cmd := exec.Command(
jira,
"ls",
"--project",
project,
)
if query != "" {
cmd.Args = append(cmd.Args, "-n", query)
}
if rawquery != "" {
cmd.Args = append(cmd.Args, "-q", rawquery)
}
if template != "" {
cmd.Args = append(cmd.Args, "--template", template)
}
if limit != "" {
cmd.Args = append(cmd.Args, "--limit", limit)
}
return cmd
}
func editIssue(jira, issue, message, override, query string) *exec.Cmd {
cmd := exec.Command(
jira,
"edit",
issue,
"-m",
message,
"--override",
override,
"--noedit",
)
if query != "" {
cmd.Args = append(cmd.Args, "--query", query)
}
return cmd
}
func closeIssue(jira, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"close",
issue,
)
return cmd
}
func doneIssue(jira, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"done",
issue,
)
return cmd
}
func dupIssue(jira, issue, duplicate string) *exec.Cmd {
cmd := exec.Command(
jira,
"dup",
duplicate,
issue,
)
return cmd
}
func blockIssue(jira, blocker, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"block",
blocker,
issue,
)
return cmd
}
func voteIssue(jira, issue string, down bool) *exec.Cmd {
cmd := exec.Command(
jira,
"vote",
issue,
)
if down {
cmd.Args = append(cmd.Args, "--down")
}
return cmd
}
func watchIssue(jira, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"watch",
issue,
)
return cmd
}
func transIssue(jira, trans, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"trans",
trans,
issue,
"--noedit",
)
return cmd
}
func todoIssue(jira, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"todo",
issue,
)
return cmd
}
func progIssue(jira, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"prog",
issue,
)
return cmd
}
func commentIssue(jira, issue, comment string) *exec.Cmd {
cmd := exec.Command(
jira,
"comment",
issue,
"--noedit",
"-m",
comment,
)
return cmd
}
func addLabelsIssue(jira, issue string, labels ...string) *exec.Cmd {
cmd := exec.Command(
jira,
"labels",
"add",
issue,
)
cmd.Args = append(cmd.Args, labels...)
return cmd
}
func removeLabelsIssue(jira, issue string, labels ...string) *exec.Cmd {
cmd := exec.Command(
jira,
"labels",
"remove",
issue,
)
cmd.Args = append(cmd.Args, labels...)
return cmd
}
func setLabelsIssue(jira, issue string, labels ...string) *exec.Cmd {
cmd := exec.Command(
jira,
"labels",
"set",
issue,
)
cmd.Args = append(cmd.Args, labels...)
return cmd
}
func takeIssue(jira, issue string) *exec.Cmd {
cmd := exec.Command(
jira,
"take",
issue,
)
return cmd
}
func giveIssue(jira, issue, taker string) *exec.Cmd {
cmd := exec.Command(
jira,
"give",
issue,
taker,
)
return cmd
}