Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions internal/cmd/sprint/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func SetFlags(cmd *cobra.Command) {
func sprintList(cmd *cobra.Command, args []string) {
server := viper.GetString("server")
project := viper.GetString("project.key")
boardID := viper.GetInt("board.id")
boardID := getBoardID(cmd)

debug, err := cmd.Flags().GetBool("debug")
cmdutil.ExitIfError(err)
Expand Down Expand Up @@ -203,6 +203,8 @@ func sprintExplorerView(sprintQuery *query.Sprint, flags query.FlagParser, board
return
}

boardName := getBoardName(client, boardID)

if sprintQuery.Params().Current || sprintQuery.Params().Prev || sprintQuery.Params().Next {
sprint := sprints[0]
if sprintQuery.Params().Next {
Expand All @@ -226,7 +228,7 @@ func sprintExplorerView(sprintQuery *query.Sprint, flags query.FlagParser, board

v := view.SprintList{
Project: project,
Board: viper.GetString("board.name"),
Board: boardName,
Server: server,
Data: sprints,
Issues: func(boardID, sprintID int) []*jira.Issue {
Expand Down Expand Up @@ -277,6 +279,7 @@ func getIssueQuery(project string, flags query.FlagParser, showAll bool) (string
}

func setFlags(cmd *cobra.Command) {
cmd.Flags().String("board", "", "Board ID to use (overrides board.id from config)")
cmd.Flags().String("state", "", "Filter sprint by its state (comma separated).\n"+
"Valid values are future, active and closed.\n"+
`Defaults to "active,closed"`)
Expand All @@ -291,6 +294,32 @@ func setFlags(cmd *cobra.Command) {
cmd.Flags().Bool("next", false, "List issues in next planned sprint")
}

func getBoardID(cmd *cobra.Command) int {
boardFlag, err := cmd.Flags().GetString("board")
cmdutil.ExitIfError(err)

if boardFlag != "" {
boardID, err := strconv.Atoi(boardFlag)
cmdutil.ExitIfError(err)
return boardID
}

return viper.GetInt("board.id")
}

func getBoardName(client *jira.Client, boardID int) string {
if boardID == 0 {
return viper.GetString("board.name")
}

board, err := client.BoardByID(boardID)
if err != nil {
return viper.GetString("board.name")
}

return board.Name
}

func hideFlags(cmd *cobra.Command) {
cmdutil.ExitIfError(cmd.Flags().MarkHidden("history"))
cmdutil.ExitIfError(cmd.Flags().MarkHidden("watching"))
Expand Down
24 changes: 24 additions & 0 deletions pkg/jira/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,30 @@ func (c *Client) BoardSearch(project, name string) (*BoardResult, error) {
return c.board(path)
}

// BoardByID fetches a single board by its ID.
func (c *Client) BoardByID(boardID int) (*Board, error) {
path := fmt.Sprintf("/board/%d", boardID)

res, err := c.GetV1(context.Background(), path, nil)
if err != nil {
return nil, err
}
if res == nil {
return nil, ErrEmptyResponse
}
defer func() { _ = res.Body.Close() }()

if res.StatusCode != http.StatusOK {
return nil, formatUnexpectedResponse(res)
}

var out Board

err = json.NewDecoder(res.Body).Decode(&out)

return &out, err
}

func (c *Client) board(path string) (*BoardResult, error) {
res, err := c.GetV1(context.Background(), path, nil)
if err != nil {
Expand Down
84 changes: 63 additions & 21 deletions pkg/jira/board_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,47 @@ import (

func TestBoards(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/rest/agile/1.0/board", r.URL.Path)
switch r.URL.Path {
case "/rest/agile/1.0/board":
qs := r.URL.Query()

qs := r.URL.Query()
switch qs.Get("projectKeyOrId") {
case "BAD":
w.WriteHeader(400)
case "TEST":
assert.Equal(t, url.Values{
"projectKeyOrId": []string{"TEST"},
"type": []string{"scrum"},
}, qs)

switch qs.Get("projectKeyOrId") {
case "BAD":
w.WriteHeader(400)
case "TEST":
assert.Equal(t, url.Values{
"projectKeyOrId": []string{"TEST"},
"type": []string{"scrum"},
}, qs)
resp, err := os.ReadFile("./testdata/boards.json")
assert.NoError(t, err)

resp, err := os.ReadFile("./testdata/boards.json")
assert.NoError(t, err)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
_, _ = w.Write(resp)
case "SEARCH":
assert.Equal(t, url.Values{
"projectKeyOrId": []string{"SEARCH"},
"name": []string{"board"},
}, qs)

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
_, _ = w.Write(resp)
case "SEARCH":
assert.Equal(t, url.Values{
"projectKeyOrId": []string{"SEARCH"},
"name": []string{"board"},
}, qs)
resp, err := os.ReadFile("./testdata/boards.json")
assert.NoError(t, err)

resp, err := os.ReadFile("./testdata/boards.json")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
_, _ = w.Write(resp)
}
case "/rest/agile/1.0/board/1":
resp, err := os.ReadFile("./testdata/board.json")
assert.NoError(t, err)

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
_, _ = w.Write(resp)
case "/rest/agile/1.0/board/999":
w.WriteHeader(404)
}
}))
defer server.Close()
Expand Down Expand Up @@ -81,3 +91,35 @@ func TestBoards(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expected, actual)
}

func TestBoardByID(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/rest/agile/1.0/board/1":
resp, err := os.ReadFile("./testdata/board.json")
assert.NoError(t, err)

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
_, _ = w.Write(resp)
case "/rest/agile/1.0/board/999":
w.WriteHeader(404)
}
}))
defer server.Close()

client := NewClient(Config{Server: server.URL}, WithTimeout(3*time.Second))

actual, err := client.BoardByID(1)
assert.NoError(t, err)

expected := &Board{
ID: 1,
Name: "Board 1",
Type: "scrum",
}
assert.Equal(t, expected, actual)

_, err = client.BoardByID(999)
assert.Error(t, &ErrUnexpectedResponse{}, err)
}
5 changes: 5 additions & 0 deletions pkg/jira/testdata/board.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": 1,
"name": "Board 1",
"type": "scrum"
}