1
0
mirror of https://github.com/interviewstreet/go-jira.git synced 2025-08-06 22:13:02 +02:00

feat(context): Add support for context package

This commit is contained in:
Suhaib Mujahid
2020-05-03 09:38:32 -04:00
committed by GitHub
parent 8b64c7f005
commit e1f4265e2b
22 changed files with 766 additions and 254 deletions

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -47,7 +48,7 @@ type Session struct {
Cookies []*http.Cookie Cookies []*http.Cookie
} }
// AcquireSessionCookie creates a new session for a user in JIRA. // AcquireSessionCookieWithContext creates a new session for a user in JIRA.
// Once a session has been successfully created it can be used to access any of JIRA's remote APIs and also the web UI by passing the appropriate HTTP Cookie header. // Once a session has been successfully created it can be used to access any of JIRA's remote APIs and also the web UI by passing the appropriate HTTP Cookie header.
// The header will by automatically applied to every API request. // The header will by automatically applied to every API request.
// Note that it is generally preferrable to use HTTP BASIC authentication with the REST API. // Note that it is generally preferrable to use HTTP BASIC authentication with the REST API.
@ -56,7 +57,7 @@ type Session struct {
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
// //
// Deprecated: Use CookieAuthTransport instead // Deprecated: Use CookieAuthTransport instead
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) { func (s *AuthenticationService) AcquireSessionCookieWithContext(ctx context.Context, username, password string) (bool, error) {
apiEndpoint := "rest/auth/1/session" apiEndpoint := "rest/auth/1/session"
body := struct { body := struct {
Username string `json:"username"` Username string `json:"username"`
@ -66,7 +67,7 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
password, password,
} }
req, err := s.client.NewRequest("POST", apiEndpoint, body) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, body)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -91,6 +92,13 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
return true, nil return true, nil
} }
// AcquireSessionCookie wraps AcquireSessionCookieWithContext using the background context.
//
// Deprecated: Use CookieAuthTransport instead
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) {
return s.AcquireSessionCookieWithContext(context.Background(), username, password)
}
// SetBasicAuth sets username and password for the basic auth against the JIRA instance. // SetBasicAuth sets username and password for the basic auth against the JIRA instance.
// //
// Deprecated: Use BasicAuthTransport instead // Deprecated: Use BasicAuthTransport instead
@ -113,19 +121,19 @@ func (s *AuthenticationService) Authenticated() bool {
return false return false
} }
// Logout logs out the current user that has been authenticated and the session in the client is destroyed. // LogoutWithContext logs out the current user that has been authenticated and the session in the client is destroyed.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
// //
// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the // Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the
// client anymore // client anymore
func (s *AuthenticationService) Logout() error { func (s *AuthenticationService) LogoutWithContext(ctx context.Context) error {
if s.authType != authTypeSession || s.client.session == nil { if s.authType != authTypeSession || s.client.session == nil {
return fmt.Errorf("no user is authenticated") return fmt.Errorf("no user is authenticated")
} }
apiEndpoint := "rest/auth/1/session" apiEndpoint := "rest/auth/1/session"
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil { if err != nil {
return fmt.Errorf("creating the request to log the user out failed : %s", err) return fmt.Errorf("creating the request to log the user out failed : %s", err)
} }
@ -145,10 +153,18 @@ func (s *AuthenticationService) Logout() error {
} }
// GetCurrentUser gets the details of the current user. // Logout wraps LogoutWithContext using the background context.
//
// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the
// client anymore
func (s *AuthenticationService) Logout() error {
return s.LogoutWithContext(context.Background())
}
// GetCurrentUserWithContext gets the details of the current user.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
func (s *AuthenticationService) GetCurrentUser() (*Session, error) { func (s *AuthenticationService) GetCurrentUserWithContext(ctx context.Context) (*Session, error) {
if s == nil { if s == nil {
return nil, fmt.Errorf("authenticaiton Service is not instantiated") return nil, fmt.Errorf("authenticaiton Service is not instantiated")
} }
@ -157,7 +173,7 @@ func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
} }
apiEndpoint := "rest/auth/1/session" apiEndpoint := "rest/auth/1/session"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not create request for getting user info : %s", err) return nil, fmt.Errorf("could not create request for getting user info : %s", err)
} }
@ -185,3 +201,8 @@ func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
return ret, nil return ret, nil
} }
// GetCurrentUser wraps GetCurrentUserWithContext using the background context.
func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
return s.GetCurrentUserWithContext(context.Background())
}

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"fmt" "fmt"
"strconv" "strconv"
"time" "time"
@ -124,16 +125,16 @@ type BoardConfigurationColumnStatus struct {
Self string `json:"self"` Self string `json:"self"`
} }
// GetAllBoards will returns all boards. This only includes boards that the user has permission to view. // GetAllBoardsWithContext will returns all boards. This only includes boards that the user has permission to view.
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards // JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Response, error) { func (s *BoardService) GetAllBoardsWithContext(ctx context.Context, opt *BoardListOptions) (*BoardsList, *Response, error) {
apiEndpoint := "rest/agile/1.0/board" apiEndpoint := "rest/agile/1.0/board"
url, err := addOptions(apiEndpoint, opt) url, err := addOptions(apiEndpoint, opt)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest("GET", url, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -148,13 +149,18 @@ func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Respon
return boards, resp, err return boards, resp, err
} }
// GetBoard will returns the board for the given boardID. // GetAllBoards wraps GetAllBoardsWithContext using the background context.
func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Response, error) {
return s.GetAllBoardsWithContext(context.Background(), opt)
}
// GetBoardWithContext will returns the board for the given boardID.
// This board will only be returned if the user has permission to view it. // This board will only be returned if the user has permission to view it.
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getBoard // JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getBoard
func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) { func (s *BoardService) GetBoardWithContext(ctx context.Context, boardID int) (*Board, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID) apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -169,7 +175,12 @@ func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) {
return board, resp, nil return board, resp, nil
} }
// CreateBoard creates a new board. Board name, type and filter Id is required. // GetBoard wraps GetBoardWithContext using the background context.
func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) {
return s.GetBoardWithContext(context.Background(), boardID)
}
// CreateBoardWithContext creates a new board. Board name, type and filter Id is required.
// name - Must be less than 255 characters. // name - Must be less than 255 characters.
// type - Valid values: scrum, kanban // type - Valid values: scrum, kanban
// filterId - Id of a filter that the user has permissions to view. // filterId - Id of a filter that the user has permissions to view.
@ -177,9 +188,9 @@ func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) {
// board will be created instead (remember that board sharing depends on the filter sharing). // board will be created instead (remember that board sharing depends on the filter sharing).
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-createBoard // JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-createBoard
func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) { func (s *BoardService) CreateBoardWithContext(ctx context.Context, board *Board) (*Board, *Response, error) {
apiEndpoint := "rest/agile/1.0/board" apiEndpoint := "rest/agile/1.0/board"
req, err := s.client.NewRequest("POST", apiEndpoint, board) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, board)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -194,12 +205,17 @@ func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) {
return responseBoard, resp, nil return responseBoard, resp, nil
} }
// DeleteBoard will delete an agile board. // CreateBoard wraps CreateBoardWithContext using the background context.
func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) {
return s.CreateBoardWithContext(context.Background(), board)
}
// DeleteBoardWithContext will delete an agile board.
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-deleteBoard // JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-deleteBoard
func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) { func (s *BoardService) DeleteBoardWithContext(ctx context.Context, boardID int) (*Board, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID) apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID)
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -211,11 +227,16 @@ func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
return nil, resp, err return nil, resp, err
} }
// GetAllSprints will return all sprints from a board, for a given board Id. // DeleteBoard wraps DeleteBoardWithContext using the background context.
func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
return s.DeleteBoardWithContext(context.Background(), boardID)
}
// GetAllSprintsWithContext will return all sprints from a board, for a given board Id.
// This only includes sprints that the user has permission to view. // This only includes sprints that the user has permission to view.
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint // JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error) { func (s *BoardService) GetAllSprintsWithContext(ctx context.Context, boardID string) ([]Sprint, *Response, error) {
id, err := strconv.Atoi(boardID) id, err := strconv.Atoi(boardID)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -229,17 +250,22 @@ func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error
return result.Values, response, nil return result.Values, response, nil
} }
// GetAllSprintsWithOptions will return sprints from a board, for a given board Id and filtering options // GetAllSprints wraps GetAllSprintsWithContext using the background context.
func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error) {
return s.GetAllSprintsWithContext(context.Background(), boardID)
}
// GetAllSprintsWithOptionsWithContext will return sprints from a board, for a given board Id and filtering options
// This only includes sprints that the user has permission to view. // This only includes sprints that the user has permission to view.
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint // JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) { func (s *BoardService) GetAllSprintsWithOptionsWithContext(ctx context.Context, boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/sprint", boardID) apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/sprint", boardID)
url, err := addOptions(apiEndpoint, options) url, err := addOptions(apiEndpoint, options)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest("GET", url, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -253,12 +279,17 @@ func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSpri
return result, resp, err return result, resp, err
} }
// GetBoardConfiguration will return a board configuration for a given board Id // GetAllSprintsWithOptions wraps GetAllSprintsWithOptionsWithContext using the background context.
func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) {
return s.GetAllSprintsWithOptionsWithContext(context.Background(), boardID, options)
}
// GetBoardConfigurationWithContext will return a board configuration for a given board Id
// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get // Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get
func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration, *Response, error) { func (s *BoardService) GetBoardConfigurationWithContext(ctx context.Context, boardID int) (*BoardConfiguration, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/configuration", boardID) apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/configuration", boardID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -273,3 +304,8 @@ func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration,
return result, resp, err return result, resp, err
} }
// GetBoardConfiguration wraps GetBoardConfigurationWithContext using the background context.
func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration, *Response, error) {
return s.GetBoardConfigurationWithContext(context.Background(), boardID)
}

View File

@ -1,5 +1,7 @@
package jira package jira
import "context"
// ComponentService handles components for the JIRA instance / API. // ComponentService handles components for the JIRA instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.1/#api/2/component // JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.1/#api/2/component
@ -19,10 +21,10 @@ type CreateComponentOptions struct {
ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"` ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"`
} }
// Create creates a new JIRA component based on the given options. // CreateWithContext creates a new JIRA component based on the given options.
func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComponent, *Response, error) { func (s *ComponentService) CreateWithContext(ctx context.Context, options *CreateComponentOptions) (*ProjectComponent, *Response, error) {
apiEndpoint := "rest/api/2/component" apiEndpoint := "rest/api/2/component"
req, err := s.client.NewRequest("POST", apiEndpoint, options) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, options)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -36,3 +38,8 @@ func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComp
return component, resp, nil return component, resp, nil
} }
// Create wraps CreateWithContext using the background context.
func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComponent, *Response, error) {
return s.CreateWithContext(context.Background(), options)
}

View File

@ -1,5 +1,7 @@
package jira package jira
import "context"
// FieldService handles fields for the JIRA instance / API. // FieldService handles fields for the JIRA instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Field // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Field
@ -24,12 +26,12 @@ type FieldSchema struct {
System string `json:"system,omitempty" structs:"system,omitempty"` System string `json:"system,omitempty" structs:"system,omitempty"`
} }
// GetList gets all fields from JIRA // GetListWithContext gets all fields from JIRA
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-field-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-field-get
func (s *FieldService) GetList() ([]Field, *Response, error) { func (s *FieldService) GetListWithContext(ctx context.Context) ([]Field, *Response, error) {
apiEndpoint := "rest/api/2/field" apiEndpoint := "rest/api/2/field"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -41,3 +43,8 @@ func (s *FieldService) GetList() ([]Field, *Response, error) {
} }
return fieldList, resp, nil return fieldList, resp, nil
} }
// GetList wraps GetListWithContext using the background context.
func (s *FieldService) GetList() ([]Field, *Response, error) {
return s.GetListWithContext(context.Background())
}

View File

@ -1,6 +1,9 @@
package jira package jira
import "github.com/google/go-querystring/query" import (
"context"
"github.com/google/go-querystring/query"
)
import "fmt" import "fmt"
// FilterService handles fields for the JIRA instance / API. // FilterService handles fields for the JIRA instance / API.
@ -116,12 +119,12 @@ type FilterSearchOptions struct {
Expand string `url:"expand,omitempty"` Expand string `url:"expand,omitempty"`
} }
// GetList retrieves all filters from Jira // GetListWithContext retrieves all filters from Jira
func (fs *FilterService) GetList() ([]*Filter, *Response, error) { func (fs *FilterService) GetListWithContext(ctx context.Context) ([]*Filter, *Response, error) {
options := &GetQueryOptions{} options := &GetQueryOptions{}
apiEndpoint := "rest/api/2/filter" apiEndpoint := "rest/api/2/filter"
req, err := fs.client.NewRequest("GET", apiEndpoint, nil) req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -143,10 +146,15 @@ func (fs *FilterService) GetList() ([]*Filter, *Response, error) {
return filters, resp, err return filters, resp, err
} }
// GetFavouriteList retrieves the user's favourited filters from Jira // GetList wraps GetListWithContext using the background context.
func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) { func (fs *FilterService) GetList() ([]*Filter, *Response, error) {
return fs.GetListWithContext(context.Background())
}
// GetFavouriteListWithContext retrieves the user's favourited filters from Jira
func (fs *FilterService) GetFavouriteListWithContext(ctx context.Context) ([]*Filter, *Response, error) {
apiEndpoint := "rest/api/2/filter/favourite" apiEndpoint := "rest/api/2/filter/favourite"
req, err := fs.client.NewRequest("GET", apiEndpoint, nil) req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -159,10 +167,15 @@ func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) {
return filters, resp, err return filters, resp, err
} }
// Get retrieves a single Filter from Jira // GetFavouriteList wraps GetFavouriteListWithContext using the background context.
func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) { func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) {
return fs.GetFavouriteListWithContext(context.Background())
}
// GetWithContext retrieves a single Filter from Jira
func (fs *FilterService) GetWithContext(ctx context.Context, filterID int) (*Filter, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/filter/%d", filterID) apiEndpoint := fmt.Sprintf("rest/api/2/filter/%d", filterID)
req, err := fs.client.NewRequest("GET", apiEndpoint, nil) req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -176,16 +189,21 @@ func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) {
return filter, resp, err return filter, resp, err
} }
// GetMyFilters retrieves the my Filters. // Get wraps GetWithContext using the background context.
func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) {
return fs.GetWithContext(context.Background(), filterID)
}
// GetMyFiltersWithContext retrieves the my Filters.
// //
// https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-my-get // https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-my-get
func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) { func (fs *FilterService) GetMyFiltersWithContext(ctx context.Context, opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) {
apiEndpoint := "rest/api/3/filter/my" apiEndpoint := "rest/api/3/filter/my"
url, err := addOptions(apiEndpoint, opts) url, err := addOptions(apiEndpoint, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
req, err := fs.client.NewRequest("GET", url, nil) req, err := fs.client.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -199,16 +217,21 @@ func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter
return filters, resp, nil return filters, resp, nil
} }
// Search will search for filter according to the search options // GetMyFilters wraps GetMyFiltersWithContext using the background context.
func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) {
return fs.GetMyFiltersWithContext(context.Background(), opts)
}
// SearchWithContext will search for filter according to the search options
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get
func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Response, error) { func (fs *FilterService) SearchWithContext(ctx context.Context, opt *FilterSearchOptions) (*FiltersList, *Response, error) {
apiEndpoint := "rest/api/3/filter/search" apiEndpoint := "rest/api/3/filter/search"
url, err := addOptions(apiEndpoint, opt) url, err := addOptions(apiEndpoint, opt)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
req, err := fs.client.NewRequest("GET", url, nil) req, err := fs.client.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -222,3 +245,8 @@ func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Respon
return filters, resp, err return filters, resp, err
} }
// Search wraps SearchWithContext using the background context.
func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Response, error) {
return fs.SearchWithContext(context.Background(), opt)
}

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"fmt" "fmt"
"net/url" "net/url"
) )
@ -58,16 +59,16 @@ type GroupSearchOptions struct {
IncludeInactiveUsers bool IncludeInactiveUsers bool
} }
// Get returns a paginated list of users who are members of the specified group and its subgroups. // GetWithContext returns a paginated list of users who are members of the specified group and its subgroups.
// Users in the page are ordered by user names. // Users in the page are ordered by user names.
// User of this resource is required to have sysadmin or admin permissions. // User of this resource is required to have sysadmin or admin permissions.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup // JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup
// //
// WARNING: This API only returns the first page of group members // WARNING: This API only returns the first page of group members
func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) { func (s *GroupService) GetWithContext(ctx context.Context, name string) ([]GroupMember, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name)) apiEndpoint := fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name))
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -81,12 +82,17 @@ func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) {
return group.Members, resp, nil return group.Members, resp, nil
} }
// GetWithOptions returns a paginated list of members of the specified group and its subgroups. // Get wraps GetWithContext using the background context.
func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) {
return s.GetWithContext(context.Background(), name)
}
// GetWithOptionsWithContext returns a paginated list of members of the specified group and its subgroups.
// Users in the page are ordered by user names. // Users in the page are ordered by user names.
// User of this resource is required to have sysadmin or admin permissions. // User of this resource is required to have sysadmin or admin permissions.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup // JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup
func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) { func (s *GroupService) GetWithOptionsWithContext(ctx context.Context, name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) {
var apiEndpoint string var apiEndpoint string
if options == nil { if options == nil {
apiEndpoint = fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name)) apiEndpoint = fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name))
@ -99,7 +105,7 @@ func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions)
options.IncludeInactiveUsers, options.IncludeInactiveUsers,
) )
} }
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -112,16 +118,21 @@ func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions)
return group.Members, resp, nil return group.Members, resp, nil
} }
// Add adds user to group // GetWithOptions wraps GetWithOptionsWithContext using the background context.
func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) {
return s.GetWithOptionsWithContext(context.Background(), name, options)
}
// AddWithContext adds user to group
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-addUserToGroup // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-addUserToGroup
func (s *GroupService) Add(groupname string, username string) (*Group, *Response, error) { func (s *GroupService) AddWithContext(ctx context.Context, groupname string, username string) (*Group, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s", groupname) apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s", groupname)
var user struct { var user struct {
Name string `json:"name"` Name string `json:"name"`
} }
user.Name = username user.Name = username
req, err := s.client.NewRequest("POST", apiEndpoint, &user) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, &user)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -136,12 +147,17 @@ func (s *GroupService) Add(groupname string, username string) (*Group, *Response
return responseGroup, resp, nil return responseGroup, resp, nil
} }
// Remove removes user from group // Add wraps AddWithContext using the background context.
func (s *GroupService) Add(groupname string, username string) (*Group, *Response, error) {
return s.AddWithContext(context.Background(), groupname, username)
}
// RemoveWithContext removes user from group
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-removeUserFromGroup // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-removeUserFromGroup
func (s *GroupService) Remove(groupname string, username string) (*Response, error) { func (s *GroupService) RemoveWithContext(ctx context.Context, groupname string, username string) (*Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s&username=%s", groupname, username) apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s&username=%s", groupname, username)
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -154,3 +170,8 @@ func (s *GroupService) Remove(groupname string, username string) (*Response, err
return resp, nil return resp, nil
} }
// Remove wraps RemoveWithContext using the background context.
func (s *GroupService) Remove(groupname string, username string) (*Response, error) {
return s.RemoveWithContext(context.Background(), groupname, username)
}

306
issue.go
View File

@ -2,6 +2,7 @@ package jira
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -588,7 +589,7 @@ type RemoteLinkStatus struct {
Icon *RemoteLinkIcon Icon *RemoteLinkIcon
} }
// Get returns a full representation of the issue for the given issue key. // GetWithContext returns a full representation of the issue for the given issue key.
// JIRA will attempt to identify the issue by the issueIdOrKey path parameter. // JIRA will attempt to identify the issue by the issueIdOrKey path parameter.
// This can be an issue id, or an issue key. // This can be an issue id, or an issue key.
// If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved. // If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved.
@ -596,9 +597,9 @@ type RemoteLinkStatus struct {
// The given options will be appended to the query string // The given options will be appended to the query string
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getIssue // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getIssue
func (s *IssueService) Get(issueID string, options *GetQueryOptions) (*Issue, *Response, error) { func (s *IssueService) GetWithContext(ctx context.Context, issueID string, options *GetQueryOptions) (*Issue, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -621,13 +622,18 @@ func (s *IssueService) Get(issueID string, options *GetQueryOptions) (*Issue, *R
return issue, resp, nil return issue, resp, nil
} }
// DownloadAttachment returns a Response of an attachment for a given attachmentID. // Get wraps GetWithContext using the background context.
func (s *IssueService) Get(issueID string, options *GetQueryOptions) (*Issue, *Response, error) {
return s.GetWithContext(context.Background(), issueID, options)
}
// DownloadAttachmentWithContext returns a Response of an attachment for a given attachmentID.
// The attachment is in the Response.Body of the response. // The attachment is in the Response.Body of the response.
// This is an io.ReadCloser. // This is an io.ReadCloser.
// The caller should close the resp.Body. // The caller should close the resp.Body.
func (s *IssueService) DownloadAttachment(attachmentID string) (*Response, error) { func (s *IssueService) DownloadAttachmentWithContext(ctx context.Context, attachmentID string) (*Response, error) {
apiEndpoint := fmt.Sprintf("secure/attachment/%s/", attachmentID) apiEndpoint := fmt.Sprintf("secure/attachment/%s/", attachmentID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -641,8 +647,13 @@ func (s *IssueService) DownloadAttachment(attachmentID string) (*Response, error
return resp, nil return resp, nil
} }
// PostAttachment uploads r (io.Reader) as an attachment to a given issueID // DownloadAttachment wraps DownloadAttachmentWithContext using the background context.
func (s *IssueService) PostAttachment(issueID string, r io.Reader, attachmentName string) (*[]Attachment, *Response, error) { func (s *IssueService) DownloadAttachment(attachmentID string) (*Response, error) {
return s.DownloadAttachmentWithContext(context.Background(), attachmentID)
}
// PostAttachmentWithContext uploads r (io.Reader) as an attachment to a given issueID
func (s *IssueService) PostAttachmentWithContext(ctx context.Context, issueID string, r io.Reader, attachmentName string) (*[]Attachment, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/attachments", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/attachments", issueID)
b := new(bytes.Buffer) b := new(bytes.Buffer)
@ -661,7 +672,7 @@ func (s *IssueService) PostAttachment(issueID string, r io.Reader, attachmentNam
} }
writer.Close() writer.Close()
req, err := s.client.NewMultiPartRequest("POST", apiEndpoint, b) req, err := s.client.NewMultiPartRequestWithContext(ctx, "POST", apiEndpoint, b)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -679,11 +690,16 @@ func (s *IssueService) PostAttachment(issueID string, r io.Reader, attachmentNam
return attachment, resp, nil return attachment, resp, nil
} }
// DeleteAttachment deletes an attachment of a given attachmentID // PostAttachment wraps PostAttachmentWithContext using the background context.
func (s *IssueService) DeleteAttachment(attachmentID string) (*Response, error) { func (s *IssueService) PostAttachment(issueID string, r io.Reader, attachmentName string) (*[]Attachment, *Response, error) {
return s.PostAttachmentWithContext(context.Background(), issueID, r, attachmentName)
}
// DeleteAttachmentWithContext deletes an attachment of a given attachmentID
func (s *IssueService) DeleteAttachmentWithContext(ctx context.Context, attachmentID string) (*Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/attachment/%s", attachmentID) apiEndpoint := fmt.Sprintf("rest/api/2/attachment/%s", attachmentID)
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -697,14 +713,19 @@ func (s *IssueService) DeleteAttachment(attachmentID string) (*Response, error)
return resp, nil return resp, nil
} }
// GetWorklogs gets all the worklogs for an issue. // DeleteAttachment wraps DeleteAttachmentWithContext using the background context.
func (s *IssueService) DeleteAttachment(attachmentID string) (*Response, error) {
return s.DeleteAttachmentWithContext(context.Background(), attachmentID)
}
// GetWorklogsWithContext gets all the worklogs for an issue.
// This method is especially important if you need to read all the worklogs, not just the first page. // This method is especially important if you need to read all the worklogs, not just the first page.
// //
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-getIssueWorklog // https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-getIssueWorklog
func (s *IssueService) GetWorklogs(issueID string, options ...func(*http.Request) error) (*Worklog, *Response, error) { func (s *IssueService) GetWorklogsWithContext(ctx context.Context, issueID string, options ...func(*http.Request) error) (*Worklog, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -721,6 +742,11 @@ func (s *IssueService) GetWorklogs(issueID string, options ...func(*http.Request
return v, resp, err return v, resp, err
} }
// GetWorklogs wraps GetWorklogsWithContext using the background context.
func (s *IssueService) GetWorklogs(issueID string, options ...func(*http.Request) error) (*Worklog, *Response, error) {
return s.GetWorklogsWithContext(context.Background(), issueID, options...)
}
// Applies query options to http request. // Applies query options to http request.
// This helper is meant to be used with all "QueryOptions" structs. // This helper is meant to be used with all "QueryOptions" structs.
func WithQueryOptions(options interface{}) func(*http.Request) error { func WithQueryOptions(options interface{}) func(*http.Request) error {
@ -737,14 +763,14 @@ func WithQueryOptions(options interface{}) func(*http.Request) error {
} }
} }
// Create creates an issue or a sub-task from a JSON representation. // CreateWithContext creates an issue or a sub-task from a JSON representation.
// Creating a sub-task is similar to creating a regular issue, with two important differences: // Creating a sub-task is similar to creating a regular issue, with two important differences:
// The issueType field must correspond to a sub-task issue type and you must provide a parent field in the issue create request containing the id or key of the parent issue. // The issueType field must correspond to a sub-task issue type and you must provide a parent field in the issue create request containing the id or key of the parent issue.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-createIssues // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-createIssues
func (s *IssueService) Create(issue *Issue) (*Issue, *Response, error) { func (s *IssueService) CreateWithContext(ctx context.Context, issue *Issue) (*Issue, *Response, error) {
apiEndpoint := "rest/api/2/issue" apiEndpoint := "rest/api/2/issue"
req, err := s.client.NewRequest("POST", apiEndpoint, issue) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, issue)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -767,17 +793,22 @@ func (s *IssueService) Create(issue *Issue) (*Issue, *Response, error) {
return responseIssue, resp, nil return responseIssue, resp, nil
} }
// UpdateWithOptions updates an issue from a JSON representation, // Create wraps CreateWithContext using the background context.
func (s *IssueService) Create(issue *Issue) (*Issue, *Response, error) {
return s.CreateWithContext(context.Background(), issue)
}
// UpdateWithOptionsWithContext updates an issue from a JSON representation,
// while also specifiying query params. The issue is found by key. // while also specifiying query params. The issue is found by key.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue
func (s *IssueService) UpdateWithOptions(issue *Issue, opts *UpdateQueryOptions) (*Issue, *Response, error) { func (s *IssueService) UpdateWithOptionsWithContext(ctx context.Context, issue *Issue, opts *UpdateQueryOptions) (*Issue, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", issue.Key) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", issue.Key)
url, err := addOptions(apiEndpoint, opts) url, err := addOptions(apiEndpoint, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest("PUT", url, issue) req, err := s.client.NewRequestWithContext(ctx, "PUT", url, issue)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -793,19 +824,29 @@ func (s *IssueService) UpdateWithOptions(issue *Issue, opts *UpdateQueryOptions)
return &ret, resp, nil return &ret, resp, nil
} }
// Update updates an issue from a JSON representation. The issue is found by key. // UpdateWithOptions wraps UpdateWithOptionsWithContext using the background context.
func (s *IssueService) UpdateWithOptions(issue *Issue, opts *UpdateQueryOptions) (*Issue, *Response, error) {
return s.UpdateWithOptionsWithContext(context.Background(), issue, opts)
}
// UpdateWithContext updates an issue from a JSON representation. The issue is found by key.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue
func (s *IssueService) Update(issue *Issue) (*Issue, *Response, error) { func (s *IssueService) UpdateWithContext(ctx context.Context, issue *Issue) (*Issue, *Response, error) {
return s.UpdateWithOptions(issue, nil) return s.UpdateWithOptions(issue, nil)
} }
// UpdateIssue updates an issue from a JSON representation. The issue is found by key. // Update wraps UpdateWithContext using the background context.
func (s *IssueService) Update(issue *Issue) (*Issue, *Response, error) {
return s.UpdateWithContext(context.Background(), issue)
}
// UpdateIssueWithContext updates an issue from a JSON representation. The issue is found by key.
// //
// https://docs.atlassian.com/jira/REST/7.4.0/#api/2/issue-editIssue // https://docs.atlassian.com/jira/REST/7.4.0/#api/2/issue-editIssue
func (s *IssueService) UpdateIssue(jiraID string, data map[string]interface{}) (*Response, error) { func (s *IssueService) UpdateIssueWithContext(ctx context.Context, jiraID string, data map[string]interface{}) (*Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", jiraID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", jiraID)
req, err := s.client.NewRequest("PUT", apiEndpoint, data) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -819,12 +860,17 @@ func (s *IssueService) UpdateIssue(jiraID string, data map[string]interface{}) (
return resp, nil return resp, nil
} }
// AddComment adds a new comment to issueID. // UpdateIssue wraps UpdateIssueWithContext using the background context.
func (s *IssueService) UpdateIssue(jiraID string, data map[string]interface{}) (*Response, error) {
return s.UpdateIssueWithContext(context.Background(), jiraID, data)
}
// AddCommentWithContext adds a new comment to issueID.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-addComment // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-addComment
func (s *IssueService) AddComment(issueID string, comment *Comment) (*Comment, *Response, error) { func (s *IssueService) AddCommentWithContext(ctx context.Context, issueID string, comment *Comment) (*Comment, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment", issueID)
req, err := s.client.NewRequest("POST", apiEndpoint, comment) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, comment)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -839,17 +885,22 @@ func (s *IssueService) AddComment(issueID string, comment *Comment) (*Comment, *
return responseComment, resp, nil return responseComment, resp, nil
} }
// UpdateComment updates the body of a comment, identified by comment.ID, on the issueID. // AddComment wraps AddCommentWithContext using the background context.
func (s *IssueService) AddComment(issueID string, comment *Comment) (*Comment, *Response, error) {
return s.AddCommentWithContext(context.Background(), issueID, comment)
}
// UpdateCommentWithContext updates the body of a comment, identified by comment.ID, on the issueID.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/comment-updateComment // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/comment-updateComment
func (s *IssueService) UpdateComment(issueID string, comment *Comment) (*Comment, *Response, error) { func (s *IssueService) UpdateCommentWithContext(ctx context.Context, issueID string, comment *Comment) (*Comment, *Response, error) {
reqBody := struct { reqBody := struct {
Body string `json:"body"` Body string `json:"body"`
}{ }{
Body: comment.Body, Body: comment.Body,
} }
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment/%s", issueID, comment.ID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment/%s", issueID, comment.ID)
req, err := s.client.NewRequest("PUT", apiEndpoint, reqBody) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, reqBody)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -863,12 +914,17 @@ func (s *IssueService) UpdateComment(issueID string, comment *Comment) (*Comment
return responseComment, resp, nil return responseComment, resp, nil
} }
// DeleteComment Deletes a comment from an issueID. // UpdateComment wraps UpdateCommentWithContext using the background context.
func (s *IssueService) UpdateComment(issueID string, comment *Comment) (*Comment, *Response, error) {
return s.UpdateCommentWithContext(context.Background(), issueID, comment)
}
// DeleteCommentWithContext Deletes a comment from an issueID.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-issue-issueIdOrKey-comment-id-delete // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-issue-issueIdOrKey-comment-id-delete
func (s *IssueService) DeleteComment(issueID, commentID string) error { func (s *IssueService) DeleteCommentWithContext(ctx context.Context, issueID, commentID string) error {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment/%s", issueID, commentID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment/%s", issueID, commentID)
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil { if err != nil {
return err return err
} }
@ -882,12 +938,17 @@ func (s *IssueService) DeleteComment(issueID, commentID string) error {
return nil return nil
} }
// AddWorklogRecord adds a new worklog record to issueID. // DeleteComment wraps DeleteCommentWithContext using the background context.
func (s *IssueService) DeleteComment(issueID, commentID string) error {
return s.DeleteCommentWithContext(context.Background(), issueID, commentID)
}
// AddWorklogRecordWithContext adds a new worklog record to issueID.
// //
// https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-worklog-post // https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-worklog-post
func (s *IssueService) AddWorklogRecord(issueID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) { func (s *IssueService) AddWorklogRecordWithContext(ctx context.Context, issueID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID)
req, err := s.client.NewRequest("POST", apiEndpoint, record) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, record)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -909,12 +970,17 @@ func (s *IssueService) AddWorklogRecord(issueID string, record *WorklogRecord, o
return responseRecord, resp, nil return responseRecord, resp, nil
} }
// UpdateWorklogRecord updates a worklog record. // AddWorklogRecord wraps AddWorklogRecordWithContext using the background context.
func (s *IssueService) AddWorklogRecord(issueID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) {
return s.AddWorklogRecordWithContext(context.Background(), issueID, record, options...)
}
// UpdateWorklogRecordWithContext updates a worklog record.
// //
// https://docs.atlassian.com/software/jira/docs/api/REST/7.1.2/#api/2/issue-updateWorklog // https://docs.atlassian.com/software/jira/docs/api/REST/7.1.2/#api/2/issue-updateWorklog
func (s *IssueService) UpdateWorklogRecord(issueID, worklogID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) { func (s *IssueService) UpdateWorklogRecordWithContext(ctx context.Context, issueID, worklogID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog/%s", issueID, worklogID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog/%s", issueID, worklogID)
req, err := s.client.NewRequest("PUT", apiEndpoint, record) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, record)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -936,12 +1002,17 @@ func (s *IssueService) UpdateWorklogRecord(issueID, worklogID string, record *Wo
return responseRecord, resp, nil return responseRecord, resp, nil
} }
// AddLink adds a link between two issues. // UpdateWorklogRecord wraps UpdateWorklogRecordWithContext using the background context.
func (s *IssueService) UpdateWorklogRecord(issueID, worklogID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) {
return s.UpdateWorklogRecordWithContext(context.Background(), issueID, worklogID, record, options...)
}
// AddLinkWithContext adds a link between two issues.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issueLink // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issueLink
func (s *IssueService) AddLink(issueLink *IssueLink) (*Response, error) { func (s *IssueService) AddLinkWithContext(ctx context.Context, issueLink *IssueLink) (*Response, error) {
apiEndpoint := "rest/api/2/issueLink" apiEndpoint := "rest/api/2/issueLink"
req, err := s.client.NewRequest("POST", apiEndpoint, issueLink) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, issueLink)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -954,10 +1025,15 @@ func (s *IssueService) AddLink(issueLink *IssueLink) (*Response, error) {
return resp, err return resp, err
} }
// Search will search for tickets according to the jql // AddLink wraps AddLinkWithContext using the background context.
func (s *IssueService) AddLink(issueLink *IssueLink) (*Response, error) {
return s.AddLinkWithContext(context.Background(), issueLink)
}
// SearchWithContext will search for tickets according to the jql
// //
// JIRA API docs: https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-query-issues // JIRA API docs: https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-query-issues
func (s *IssueService) Search(jql string, options *SearchOptions) ([]Issue, *Response, error) { func (s *IssueService) SearchWithContext(ctx context.Context, jql string, options *SearchOptions) ([]Issue, *Response, error) {
u := url.URL{ u := url.URL{
Path: "rest/api/2/search", Path: "rest/api/2/search",
} }
@ -967,6 +1043,7 @@ func (s *IssueService) Search(jql string, options *SearchOptions) ([]Issue, *Res
} }
if options != nil { if options != nil {
if options.StartAt != 0 { if options.StartAt != 0 {
uv.Add("startAt", strconv.Itoa(options.StartAt)) uv.Add("startAt", strconv.Itoa(options.StartAt))
} }
@ -986,7 +1063,7 @@ func (s *IssueService) Search(jql string, options *SearchOptions) ([]Issue, *Res
u.RawQuery = uv.Encode() u.RawQuery = uv.Encode()
req, err := s.client.NewRequest("GET", u.String(), nil) req, err := s.client.NewRequestWithContext(ctx, "GET", u.String(), nil)
if err != nil { if err != nil {
return []Issue{}, nil, err return []Issue{}, nil, err
} }
@ -999,10 +1076,15 @@ func (s *IssueService) Search(jql string, options *SearchOptions) ([]Issue, *Res
return v.Issues, resp, err return v.Issues, resp, err
} }
// SearchPages will get issues from all pages in a search // Search wraps SearchWithContext using the background context.
func (s *IssueService) Search(jql string, options *SearchOptions) ([]Issue, *Response, error) {
return s.SearchWithContext(context.Background(), jql, options)
}
// SearchPagesWithContext will get issues from all pages in a search
// //
// JIRA API docs: https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-query-issues // JIRA API docs: https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-query-issues
func (s *IssueService) SearchPages(jql string, options *SearchOptions, f func(Issue) error) error { func (s *IssueService) SearchPagesWithContext(ctx context.Context, jql string, options *SearchOptions, f func(Issue) error) error {
if options == nil { if options == nil {
options = &SearchOptions{ options = &SearchOptions{
StartAt: 0, StartAt: 0,
@ -1043,10 +1125,15 @@ func (s *IssueService) SearchPages(jql string, options *SearchOptions, f func(Is
} }
} }
// GetCustomFields returns a map of customfield_* keys with string values // SearchPages wraps SearchPagesWithContext using the background context.
func (s *IssueService) GetCustomFields(issueID string) (CustomFields, *Response, error) { func (s *IssueService) SearchPages(jql string, options *SearchOptions, f func(Issue) error) error {
return s.SearchPagesWithContext(context.Background(), jql, options, f)
}
// GetCustomFieldsWithContext returns a map of customfield_* keys with string values
func (s *IssueService) GetCustomFieldsWithContext(ctx context.Context, issueID string) (CustomFields, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -1080,13 +1167,18 @@ func (s *IssueService) GetCustomFields(issueID string) (CustomFields, *Response,
return cf, resp, nil return cf, resp, nil
} }
// GetTransitions gets a list of the transitions possible for this issue by the current user, // GetCustomFields wraps GetCustomFieldsWithContext using the background context.
func (s *IssueService) GetCustomFields(issueID string) (CustomFields, *Response, error) {
return s.GetCustomFieldsWithContext(context.Background(), issueID)
}
// GetTransitionsWithContext gets a list of the transitions possible for this issue by the current user,
// along with fields that are required and their types. // along with fields that are required and their types.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getTransitions // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getTransitions
func (s *IssueService) GetTransitions(id string) ([]Transition, *Response, error) { func (s *IssueService) GetTransitionsWithContext(ctx context.Context, id string) ([]Transition, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions?expand=transitions.fields", id) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions?expand=transitions.fields", id)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -1099,27 +1191,37 @@ func (s *IssueService) GetTransitions(id string) ([]Transition, *Response, error
return result.Transitions, resp, err return result.Transitions, resp, err
} }
// DoTransition performs a transition on an issue. // GetTransitions wraps GetTransitionsWithContext using the background context.
func (s *IssueService) GetTransitions(id string) ([]Transition, *Response, error) {
return s.GetTransitionsWithContext(context.Background(), id)
}
// DoTransitionWithContext performs a transition on an issue.
// When performing the transition you can update or set other issue fields. // When performing the transition you can update or set other issue fields.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition
func (s *IssueService) DoTransition(ticketID, transitionID string) (*Response, error) { func (s *IssueService) DoTransitionWithContext(ctx context.Context, ticketID, transitionID string) (*Response, error) {
payload := CreateTransitionPayload{ payload := CreateTransitionPayload{
Transition: TransitionPayload{ Transition: TransitionPayload{
ID: transitionID, ID: transitionID,
}, },
} }
return s.DoTransitionWithPayload(ticketID, payload) return s.DoTransitionWithPayloadWithContext(ctx, ticketID, payload)
} }
// DoTransitionWithPayload performs a transition on an issue using any payload. // DoTransition wraps DoTransitionWithContext using the background context.
func (s *IssueService) DoTransition(ticketID, transitionID string) (*Response, error) {
return s.DoTransitionWithContext(context.Background(), ticketID, transitionID)
}
// DoTransitionWithPayloadWithContext performs a transition on an issue using any payload.
// When performing the transition you can update or set other issue fields. // When performing the transition you can update or set other issue fields.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition
func (s *IssueService) DoTransitionWithPayload(ticketID, payload interface{}) (*Response, error) { func (s *IssueService) DoTransitionWithPayloadWithContext(ctx context.Context, ticketID, payload interface{}) (*Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions", ticketID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions", ticketID)
req, err := s.client.NewRequest("POST", apiEndpoint, payload) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1132,6 +1234,11 @@ func (s *IssueService) DoTransitionWithPayload(ticketID, payload interface{}) (*
return resp, err return resp, err
} }
// DoTransitionWithPayload wraps DoTransitionWithPayloadWithContext using the background context.
func (s *IssueService) DoTransitionWithPayload(ticketID, payload interface{}) (*Response, error) {
return s.DoTransitionWithPayloadWithContext(context.Background(), ticketID, payload)
}
// InitIssueWithMetaAndFields returns Issue with with values from fieldsConfig properly set. // InitIssueWithMetaAndFields returns Issue with with values from fieldsConfig properly set.
// * metaProject should contain metaInformation about the project where the issue should be created. // * metaProject should contain metaInformation about the project where the issue should be created.
// * metaIssuetype is the MetaInformation about the Issuetype that needs to be created. // * metaIssuetype is the MetaInformation about the Issuetype that needs to be created.
@ -1211,8 +1318,8 @@ func InitIssueWithMetaAndFields(metaProject *MetaProject, metaIssuetype *MetaIss
return issue, nil return issue, nil
} }
// Delete will delete a specified issue. // DeleteWithContext will delete a specified issue.
func (s *IssueService) Delete(issueID string) (*Response, error) { func (s *IssueService) DeleteWithContext(ctx context.Context, issueID string) (*Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID)
// to enable deletion of subtasks; without this, the request will fail if the issue has subtasks // to enable deletion of subtasks; without this, the request will fail if the issue has subtasks
@ -1220,7 +1327,7 @@ func (s *IssueService) Delete(issueID string) (*Response, error) {
deletePayload["deleteSubtasks"] = "true" deletePayload["deleteSubtasks"] = "true"
content, _ := json.Marshal(deletePayload) content, _ := json.Marshal(deletePayload)
req, err := s.client.NewRequest("DELETE", apiEndpoint, content) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, content)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1229,13 +1336,18 @@ func (s *IssueService) Delete(issueID string) (*Response, error) {
return resp, err return resp, err
} }
// GetWatchers wil return all the users watching/observing the given issue // Delete wraps DeleteWithContext using the background context.
func (s *IssueService) Delete(issueID string) (*Response, error) {
return s.DeleteWithContext(context.Background(), issueID)
}
// GetWatchersWithContext wil return all the users watching/observing the given issue
// //
// JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-getIssueWatchers // JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-getIssueWatchers
func (s *IssueService) GetWatchers(issueID string) (*[]User, *Response, error) { func (s *IssueService) GetWatchersWithContext(ctx context.Context, issueID string) (*[]User, *Response, error) {
watchesAPIEndpoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID) watchesAPIEndpoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID)
req, err := s.client.NewRequest("GET", watchesAPIEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", watchesAPIEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -1267,13 +1379,18 @@ func (s *IssueService) GetWatchers(issueID string) (*[]User, *Response, error) {
return &result, resp, nil return &result, resp, nil
} }
// AddWatcher adds watcher to the given issue // GetWatchers wraps GetWatchersWithContext using the background context.
func (s *IssueService) GetWatchers(issueID string) (*[]User, *Response, error) {
return s.GetWatchersWithContext(context.Background(), issueID)
}
// AddWatcherWithContext adds watcher to the given issue
// //
// JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-addWatcher // JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-addWatcher
func (s *IssueService) AddWatcher(issueID string, userName string) (*Response, error) { func (s *IssueService) AddWatcherWithContext(ctx context.Context, issueID string, userName string) (*Response, error) {
apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID) apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID)
req, err := s.client.NewRequest("POST", apiEndPoint, userName) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, userName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1286,13 +1403,18 @@ func (s *IssueService) AddWatcher(issueID string, userName string) (*Response, e
return resp, err return resp, err
} }
// RemoveWatcher removes given user from given issue // AddWatcher wraps AddWatcherWithContext using the background context.
func (s *IssueService) AddWatcher(issueID string, userName string) (*Response, error) {
return s.AddWatcherWithContext(context.Background(), issueID, userName)
}
// RemoveWatcherWithContext removes given user from given issue
// //
// JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-removeWatcher // JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-removeWatcher
func (s *IssueService) RemoveWatcher(issueID string, userName string) (*Response, error) { func (s *IssueService) RemoveWatcherWithContext(ctx context.Context, issueID string, userName string) (*Response, error) {
apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID) apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID)
req, err := s.client.NewRequest("DELETE", apiEndPoint, userName) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, userName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1305,13 +1427,18 @@ func (s *IssueService) RemoveWatcher(issueID string, userName string) (*Response
return resp, err return resp, err
} }
// UpdateAssignee updates the user assigned to work on the given issue // RemoveWatcher wraps RemoveWatcherWithContext using the background context.
func (s *IssueService) RemoveWatcher(issueID string, userName string) (*Response, error) {
return s.RemoveWatcherWithContext(context.Background(), issueID, userName)
}
// UpdateAssigneeWithContext updates the user assigned to work on the given issue
// //
// JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.2/#api/2/issue-assign // JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.2/#api/2/issue-assign
func (s *IssueService) UpdateAssignee(issueID string, assignee *User) (*Response, error) { func (s *IssueService) UpdateAssigneeWithContext(ctx context.Context, issueID string, assignee *User) (*Response, error) {
apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/assignee", issueID) apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/assignee", issueID)
req, err := s.client.NewRequest("PUT", apiEndPoint, assignee) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndPoint, assignee)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1324,6 +1451,11 @@ func (s *IssueService) UpdateAssignee(issueID string, assignee *User) (*Response
return resp, err return resp, err
} }
// UpdateAssignee wraps UpdateAssigneeWithContext using the background context.
func (s *IssueService) UpdateAssignee(issueID string, assignee *User) (*Response, error) {
return s.UpdateAssigneeWithContext(context.Background(), issueID, assignee)
}
func (c ChangelogHistory) CreatedTime() (time.Time, error) { func (c ChangelogHistory) CreatedTime() (time.Time, error) {
var t time.Time var t time.Time
// Ignore null // Ignore null
@ -1334,12 +1466,12 @@ func (c ChangelogHistory) CreatedTime() (time.Time, error) {
return t, err return t, err
} }
// GetRemoteLinks gets remote issue links on the issue. // GetRemoteLinksWithContext gets remote issue links on the issue.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getRemoteIssueLinks // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getRemoteIssueLinks
func (s *IssueService) GetRemoteLinks(id string) (*[]RemoteLink, *Response, error) { func (s *IssueService) GetRemoteLinksWithContext(ctx context.Context, id string) (*[]RemoteLink, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink", id) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink", id)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -1352,12 +1484,17 @@ func (s *IssueService) GetRemoteLinks(id string) (*[]RemoteLink, *Response, erro
return result, resp, err return result, resp, err
} }
// AddRemoteLink adds a remote link to issueID. // GetRemoteLinks wraps GetRemoteLinksWithContext using the background context.
func (s *IssueService) GetRemoteLinks(id string) (*[]RemoteLink, *Response, error) {
return s.GetRemoteLinksWithContext(context.Background(), id)
}
// AddRemoteLinkWithContext adds a remote link to issueID.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issue-issueIdOrKey-remotelink-post // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issue-issueIdOrKey-remotelink-post
func (s *IssueService) AddRemoteLink(issueID string, remotelink *RemoteLink) (*RemoteLink, *Response, error) { func (s *IssueService) AddRemoteLinkWithContext(ctx context.Context, issueID string, remotelink *RemoteLink) (*RemoteLink, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink", issueID) apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink", issueID)
req, err := s.client.NewRequest("POST", apiEndpoint, remotelink) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, remotelink)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -1371,3 +1508,8 @@ func (s *IssueService) AddRemoteLink(issueID string, remotelink *RemoteLink) (*R
return responseRemotelink, resp, nil return responseRemotelink, resp, nil
} }
// AddRemoteLink wraps AddRemoteLinkWithContext using the background context.
func (s *IssueService) AddRemoteLink(issueID string, remotelink *RemoteLink) (*RemoteLink, *Response, error) {
return s.AddRemoteLinkWithContext(context.Background(), issueID, remotelink)
}

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -13,12 +14,12 @@ type IssueLinkTypeService struct {
client *Client client *Client
} }
// GetList gets all of the issue link types from JIRA. // GetListWithContext gets all of the issue link types from JIRA.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-get
func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) { func (s *IssueLinkTypeService) GetListWithContext(ctx context.Context) ([]IssueLinkType, *Response, error) {
apiEndpoint := "rest/api/2/issueLinkType" apiEndpoint := "rest/api/2/issueLinkType"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -31,12 +32,17 @@ func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) {
return linkTypeList, resp, nil return linkTypeList, resp, nil
} }
// Get gets info of a specific issue link type from JIRA. // GetList wraps GetListWithContext using the background context.
func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) {
return s.GetListWithContext(context.Background())
}
// GetWithContext gets info of a specific issue link type from JIRA.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-get
func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error) { func (s *IssueLinkTypeService) GetWithContext(ctx context.Context, ID string) (*IssueLinkType, *Response, error) {
apiEndPoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID) apiEndPoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID)
req, err := s.client.NewRequest("GET", apiEndPoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -49,12 +55,17 @@ func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error)
return linkType, resp, nil return linkType, resp, nil
} }
// Create creates an issue link type in JIRA. // Get wraps GetWithContext using the background context.
func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error) {
return s.GetWithContext(context.Background(), ID)
}
// CreateWithContext creates an issue link type in JIRA.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-post // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-post
func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType, *Response, error) { func (s *IssueLinkTypeService) CreateWithContext(ctx context.Context, linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
apiEndpoint := "/rest/api/2/issueLinkType" apiEndpoint := "/rest/api/2/issueLinkType"
req, err := s.client.NewRequest("POST", apiEndpoint, linkType) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, linkType)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -79,12 +90,17 @@ func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType,
return linkType, resp, nil return linkType, resp, nil
} }
// Update updates an issue link type. The issue is found by key. // Create wraps CreateWithContext using the background context.
func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
return s.CreateWithContext(context.Background(), linkType)
}
// UpdateWithContext updates an issue link type. The issue is found by key.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-put // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-put
func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType, *Response, error) { func (s *IssueLinkTypeService) UpdateWithContext(ctx context.Context, linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", linkType.ID) apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", linkType.ID)
req, err := s.client.NewRequest("PUT", apiEndpoint, linkType) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, linkType)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -96,12 +112,17 @@ func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType,
return &ret, resp, nil return &ret, resp, nil
} }
// Delete deletes an issue link type based on provided ID. // Update wraps UpdateWithContext using the background context.
func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
return s.UpdateWithContext(context.Background(), linkType)
}
// DeleteWithContext deletes an issue link type based on provided ID.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-delete // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-delete
func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) { func (s *IssueLinkTypeService) DeleteWithContext(ctx context.Context, ID string) (*Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID) apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID)
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -109,3 +130,8 @@ func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) {
resp, err := s.client.Do(req, nil) resp, err := s.client.Do(req, nil)
return resp, err return resp, err
} }
// Delete wraps DeleteWithContext using the background context.
func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) {
return s.DeleteWithContext(context.Background(), ID)
}

34
jira.go
View File

@ -2,6 +2,7 @@ package jira
import ( import (
"bytes" "bytes"
"context"
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -105,10 +106,10 @@ func NewClient(httpClient httpClient, baseURL string) (*Client, error) {
return c, nil return c, nil
} }
// NewRawRequest creates an API request. // NewRawRequestWithContext creates an API request.
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client. // A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
// Allows using an optional native io.Reader for sourcing the request body. // Allows using an optional native io.Reader for sourcing the request body.
func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Request, error) { func (c *Client) NewRawRequestWithContext(ctx context.Context, method, urlStr string, body io.Reader) (*http.Request, error) {
rel, err := url.Parse(urlStr) rel, err := url.Parse(urlStr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -118,7 +119,7 @@ func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Req
u := c.baseURL.ResolveReference(rel) u := c.baseURL.ResolveReference(rel)
req, err := http.NewRequest(method, u.String(), body) req, err := newRequestWithContext(ctx, method, u.String(), body)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -143,10 +144,15 @@ func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Req
return req, nil return req, nil
} }
// NewRequest creates an API request. // NewRawRequest wraps NewRawRequestWithContext using the background context.
func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
return c.NewRawRequestWithContext(context.Background(), method, urlStr, body)
}
// NewRequestWithContext creates an API request.
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client. // A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
// If specified, the value pointed to by body is JSON encoded and included as the request body. // If specified, the value pointed to by body is JSON encoded and included as the request body.
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) { func (c *Client) NewRequestWithContext(ctx context.Context, method, urlStr string, body interface{}) (*http.Request, error) {
rel, err := url.Parse(urlStr) rel, err := url.Parse(urlStr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -165,7 +171,7 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
} }
} }
req, err := http.NewRequest(method, u.String(), buf) req, err := newRequestWithContext(ctx, method, u.String(), buf)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -190,6 +196,11 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
return req, nil return req, nil
} }
// NewRequest wraps NewRequestWithContext using the background context.
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
return c.NewRequestWithContext(context.Background(), method, urlStr, body)
}
// addOptions adds the parameters in opt as URL query parameters to s. opt // addOptions adds the parameters in opt as URL query parameters to s. opt
// must be a struct whose fields may contain "url" tags. // must be a struct whose fields may contain "url" tags.
func addOptions(s string, opt interface{}) (string, error) { func addOptions(s string, opt interface{}) (string, error) {
@ -212,10 +223,10 @@ func addOptions(s string, opt interface{}) (string, error) {
return u.String(), nil return u.String(), nil
} }
// NewMultiPartRequest creates an API request including a multi-part file. // NewMultiPartRequestWithContext creates an API request including a multi-part file.
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client. // A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
// If specified, the value pointed to by buf is a multipart form. // If specified, the value pointed to by buf is a multipart form.
func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (*http.Request, error) { func (c *Client) NewMultiPartRequestWithContext(ctx context.Context, method, urlStr string, buf *bytes.Buffer) (*http.Request, error) {
rel, err := url.Parse(urlStr) rel, err := url.Parse(urlStr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -225,7 +236,7 @@ func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (
u := c.baseURL.ResolveReference(rel) u := c.baseURL.ResolveReference(rel)
req, err := http.NewRequest(method, u.String(), buf) req, err := newRequestWithContext(ctx, method, u.String(), buf)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -251,6 +262,11 @@ func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (
return req, nil return req, nil
} }
// NewMultiPartRequest wraps NewMultiPartRequestWithContext using the background context.
func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (*http.Request, error) {
return c.NewMultiPartRequestWithContext(context.Background(), method, urlStr, buf)
}
// Do sends an API request and returns the API response. // Do sends an API request and returns the API response.
// The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred. // The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.
func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) { func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -47,16 +48,21 @@ type MetaIssueType struct {
Fields tcontainer.MarshalMap `json:"fields,omitempty"` Fields tcontainer.MarshalMap `json:"fields,omitempty"`
} }
// GetCreateMeta makes the api call to get the meta information required to create a ticket // GetCreateMetaWithContext makes the api call to get the meta information required to create a ticket
func (s *IssueService) GetCreateMeta(projectkeys string) (*CreateMetaInfo, *Response, error) { func (s *IssueService) GetCreateMetaWithContext(ctx context.Context, projectkeys string) (*CreateMetaInfo, *Response, error) {
return s.GetCreateMetaWithOptions(&GetQueryOptions{ProjectKeys: projectkeys, Expand: "projects.issuetypes.fields"}) return s.GetCreateMetaWithOptionsWithContext(ctx, &GetQueryOptions{ProjectKeys: projectkeys, Expand: "projects.issuetypes.fields"})
} }
// GetCreateMetaWithOptions makes the api call to get the meta information without requiring to have a projectKey // GetCreateMeta wraps GetCreateMetaWithContext using the background context.
func (s *IssueService) GetCreateMetaWithOptions(options *GetQueryOptions) (*CreateMetaInfo, *Response, error) { func (s *IssueService) GetCreateMeta(projectkeys string) (*CreateMetaInfo, *Response, error) {
return s.GetCreateMetaWithContext(context.Background(), projectkeys)
}
// GetCreateMetaWithOptionsWithContext makes the api call to get the meta information without requiring to have a projectKey
func (s *IssueService) GetCreateMetaWithOptionsWithContext(ctx context.Context, options *GetQueryOptions) (*CreateMetaInfo, *Response, error) {
apiEndpoint := "rest/api/2/issue/createmeta" apiEndpoint := "rest/api/2/issue/createmeta"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -78,11 +84,16 @@ func (s *IssueService) GetCreateMetaWithOptions(options *GetQueryOptions) (*Crea
return meta, resp, nil return meta, resp, nil
} }
// GetEditMeta makes the api call to get the edit meta information for an issue // GetCreateMetaWithOptions wraps GetCreateMetaWithOptionsWithContext using the background context.
func (s *IssueService) GetEditMeta(issue *Issue) (*EditMetaInfo, *Response, error) { func (s *IssueService) GetCreateMetaWithOptions(options *GetQueryOptions) (*CreateMetaInfo, *Response, error) {
return s.GetCreateMetaWithOptionsWithContext(context.Background(), options)
}
// GetEditMetaWithContext makes the api call to get the edit meta information for an issue
func (s *IssueService) GetEditMetaWithContext(ctx context.Context, issue *Issue) (*EditMetaInfo, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/issue/%s/editmeta", issue.Key) apiEndpoint := fmt.Sprintf("/rest/api/2/issue/%s/editmeta", issue.Key)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -97,6 +108,11 @@ func (s *IssueService) GetEditMeta(issue *Issue) (*EditMetaInfo, *Response, erro
return meta, resp, nil return meta, resp, nil
} }
// GetEditMeta wraps GetEditMetaWithContext using the background context.
func (s *IssueService) GetEditMeta(issue *Issue) (*EditMetaInfo, *Response, error) {
return s.GetEditMetaWithContext(context.Background(), issue)
}
// GetProjectWithName returns a project with "name" from the meta information received. If not found, this returns nil. // GetProjectWithName returns a project with "name" from the meta information received. If not found, this returns nil.
// The comparison of the name is case insensitive. // The comparison of the name is case insensitive.
func (m *CreateMetaInfo) GetProjectWithName(name string) *MetaProject { func (m *CreateMetaInfo) GetProjectWithName(name string) *MetaProject {

View File

@ -1,6 +1,9 @@
package jira package jira
import "fmt" import (
"context"
"fmt"
)
// PermissionSchemeService handles permissionschemes for the JIRA instance / API. // PermissionSchemeService handles permissionschemes for the JIRA instance / API.
// //
@ -25,12 +28,12 @@ type Holder struct {
Expand string `json:"expand" structs:"expand"` Expand string `json:"expand" structs:"expand"`
} }
// GetList returns a list of all permission schemes // GetListWithContext returns a list of all permission schemes
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-get
func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, error) { func (s *PermissionSchemeService) GetListWithContext(ctx context.Context) (*PermissionSchemes, *Response, error) {
apiEndpoint := "/rest/api/3/permissionscheme" apiEndpoint := "/rest/api/3/permissionscheme"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -45,12 +48,17 @@ func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, erro
return pss, resp, nil return pss, resp, nil
} }
// Get returns a full representation of the permission scheme for the schemeID // GetList wraps GetListWithContext using the background context.
func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, error) {
return s.GetListWithContext(context.Background())
}
// GetWithContext returns a full representation of the permission scheme for the schemeID
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-schemeId-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-schemeId-get
func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Response, error) { func (s *PermissionSchemeService) GetWithContext(ctx context.Context, schemeID int) (*PermissionScheme, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/3/permissionscheme/%d", schemeID) apiEndpoint := fmt.Sprintf("/rest/api/3/permissionscheme/%d", schemeID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -67,3 +75,8 @@ func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Respons
return ps, resp, nil return ps, resp, nil
} }
// Get wraps GetWithContext using the background context.
func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Response, error) {
return s.GetWithContext(context.Background(), schemeID)
}

View File

@ -1,5 +1,7 @@
package jira package jira
import "context"
// PriorityService handles priorities for the JIRA instance / API. // PriorityService handles priorities for the JIRA instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Priority // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Priority
@ -18,12 +20,12 @@ type Priority struct {
Description string `json:"description,omitempty" structs:"description,omitempty"` Description string `json:"description,omitempty" structs:"description,omitempty"`
} }
// GetList gets all priorities from JIRA // GetListWithContext gets all priorities from JIRA
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-priority-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-priority-get
func (s *PriorityService) GetList() ([]Priority, *Response, error) { func (s *PriorityService) GetListWithContext(ctx context.Context) ([]Priority, *Response, error) {
apiEndpoint := "rest/api/2/priority" apiEndpoint := "rest/api/2/priority"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -35,3 +37,8 @@ func (s *PriorityService) GetList() ([]Priority, *Response, error) {
} }
return priorityList, resp, nil return priorityList, resp, nil
} }
// GetList wraps GetListWithContext using the background context.
func (s *PriorityService) GetList() ([]Priority, *Response, error) {
return s.GetListWithContext(context.Background())
}

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"fmt" "fmt"
"github.com/google/go-querystring/query" "github.com/google/go-querystring/query"
@ -80,20 +81,25 @@ type PermissionScheme struct {
Permissions []Permission `json:"permissions" structs:"permissions,omitempty"` Permissions []Permission `json:"permissions" structs:"permissions,omitempty"`
} }
// GetList gets all projects form JIRA // GetListWithContext gets all projects form JIRA
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects
func (s *ProjectService) GetList() (*ProjectList, *Response, error) { func (s *ProjectService) GetListWithContext(ctx context.Context) (*ProjectList, *Response, error) {
return s.ListWithOptions(&GetQueryOptions{}) return s.ListWithOptionsWithContext(ctx, &GetQueryOptions{})
} }
// ListWithOptions gets all projects form JIRA with optional query params, like &GetQueryOptions{Expand: "issueTypes"} to get // GetList wraps GetListWithContext using the background context.
func (s *ProjectService) GetList() (*ProjectList, *Response, error) {
return s.GetListWithContext(context.Background())
}
// ListWithOptionsWithContext gets all projects form JIRA with optional query params, like &GetQueryOptions{Expand: "issueTypes"} to get
// a list of all projects and their supported issuetypes // a list of all projects and their supported issuetypes
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects
func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList, *Response, error) { func (s *ProjectService) ListWithOptionsWithContext(ctx context.Context, options *GetQueryOptions) (*ProjectList, *Response, error) {
apiEndpoint := "rest/api/2/project" apiEndpoint := "rest/api/2/project"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -116,14 +122,19 @@ func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList
return projectList, resp, nil return projectList, resp, nil
} }
// Get returns a full representation of the project for the given issue key. // ListWithOptions wraps ListWithOptionsWithContext using the background context.
func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList, *Response, error) {
return s.ListWithOptionsWithContext(context.Background(), options)
}
// GetWithContext returns a full representation of the project for the given issue key.
// JIRA will attempt to identify the project by the projectIdOrKey path parameter. // JIRA will attempt to identify the project by the projectIdOrKey path parameter.
// This can be an project id, or an project key. // This can be an project id, or an project key.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject
func (s *ProjectService) Get(projectID string) (*Project, *Response, error) { func (s *ProjectService) GetWithContext(ctx context.Context, projectID string) (*Project, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/project/%s", projectID) apiEndpoint := fmt.Sprintf("rest/api/2/project/%s", projectID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -138,14 +149,19 @@ func (s *ProjectService) Get(projectID string) (*Project, *Response, error) {
return project, resp, nil return project, resp, nil
} }
// GetPermissionScheme returns a full representation of the permission scheme for the project // Get wraps GetWithContext using the background context.
func (s *ProjectService) Get(projectID string) (*Project, *Response, error) {
return s.GetWithContext(context.Background(), projectID)
}
// GetPermissionSchemeWithContext returns a full representation of the permission scheme for the project
// JIRA will attempt to identify the project by the projectIdOrKey path parameter. // JIRA will attempt to identify the project by the projectIdOrKey path parameter.
// This can be an project id, or an project key. // This can be an project id, or an project key.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject // JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject
func (s *ProjectService) GetPermissionScheme(projectID string) (*PermissionScheme, *Response, error) { func (s *ProjectService) GetPermissionSchemeWithContext(ctx context.Context, projectID string) (*PermissionScheme, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/project/%s/permissionscheme", projectID) apiEndpoint := fmt.Sprintf("/rest/api/2/project/%s/permissionscheme", projectID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -159,3 +175,8 @@ func (s *ProjectService) GetPermissionScheme(projectID string) (*PermissionSchem
return ps, resp, nil return ps, resp, nil
} }
// GetPermissionScheme wraps GetPermissionSchemeWithContext using the background context.
func (s *ProjectService) GetPermissionScheme(projectID string) (*PermissionScheme, *Response, error) {
return s.GetPermissionSchemeWithContext(context.Background(), projectID)
}

23
request_context.go Normal file
View File

@ -0,0 +1,23 @@
// +build go1.13
// This file provides glue to use Context in `http.Request` with
// Go version 1.13 and higher.
// The function `http.NewRequestWithContext` has been added in Go 1.13.
// Before the release 1.13, to use Context we need creat `http.Request`
// then use the method `WithContext` to create a new `http.Request`
// with Context from the existing `http.Request`.
//
// Doc: https://golang.org/doc/go1.13#net/http
package jira
import (
"context"
"io"
"net/http"
)
func newRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) {
return http.NewRequestWithContext(ctx, method, url, body)
}

28
request_legacy.go Normal file
View File

@ -0,0 +1,28 @@
// +build !go1.13
// This file provides glue to use Context in `http.Request` with
// Go version before 1.13.
// The function `http.NewRequestWithContext` has been added in Go 1.13.
// Before the release 1.13, to use Context we need creat `http.Request`
// then use the method `WithContext` to create a new `http.Request`
// with Context from the existing `http.Request`.
//
// Doc: https://golang.org/doc/go1.13#net/http
package jira
import (
"context"
"io"
"net/http"
)
func newRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) {
r, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
return r.WithContext(ctx), nil
}

View File

@ -1,5 +1,7 @@
package jira package jira
import "context"
// ResolutionService handles resolutions for the JIRA instance / API. // ResolutionService handles resolutions for the JIRA instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Resolution // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Resolution
@ -16,12 +18,12 @@ type Resolution struct {
Name string `json:"name" structs:"name"` Name string `json:"name" structs:"name"`
} }
// GetList gets all resolutions from JIRA // GetListWithContext gets all resolutions from JIRA
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-resolution-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-resolution-get
func (s *ResolutionService) GetList() ([]Resolution, *Response, error) { func (s *ResolutionService) GetListWithContext(ctx context.Context) ([]Resolution, *Response, error) {
apiEndpoint := "rest/api/2/resolution" apiEndpoint := "rest/api/2/resolution"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -33,3 +35,8 @@ func (s *ResolutionService) GetList() ([]Resolution, *Response, error) {
} }
return resolutionList, resp, nil return resolutionList, resp, nil
} }
// GetList wraps GetListWithContext using the background context.
func (s *ResolutionService) GetList() ([]Resolution, *Response, error) {
return s.GetListWithContext(context.Background())
}

23
role.go
View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"fmt" "fmt"
) )
@ -35,12 +36,12 @@ type ActorUser struct {
AccountID string `json:"accountId" structs:"accountId"` AccountID string `json:"accountId" structs:"accountId"`
} }
// GetList returns a list of all available project roles // GetListWithContext returns a list of all available project roles
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-get
func (s *RoleService) GetList() (*[]Role, *Response, error) { func (s *RoleService) GetListWithContext(ctx context.Context) (*[]Role, *Response, error) {
apiEndpoint := "rest/api/3/role" apiEndpoint := "rest/api/3/role"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -53,12 +54,17 @@ func (s *RoleService) GetList() (*[]Role, *Response, error) {
return roles, resp, err return roles, resp, err
} }
// Get retreives a single Role from Jira // GetList wraps GetListWithContext using the background context.
func (s *RoleService) GetList() (*[]Role, *Response, error) {
return s.GetListWithContext(context.Background())
}
// GetWithContext retreives a single Role from Jira
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-id-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-id-get
func (s *RoleService) Get(roleID int) (*Role, *Response, error) { func (s *RoleService) GetWithContext(ctx context.Context, roleID int) (*Role, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/3/role/%d", roleID) apiEndpoint := fmt.Sprintf("rest/api/3/role/%d", roleID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -74,3 +80,8 @@ func (s *RoleService) Get(roleID int) (*Role, *Response, error) {
return role, resp, err return role, resp, err
} }
// Get wraps GetWithContext using the background context.
func (s *RoleService) Get(roleID int) (*Role, *Response, error) {
return s.GetWithContext(context.Background(), roleID)
}

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"fmt" "fmt"
"github.com/google/go-querystring/query" "github.com/google/go-querystring/query"
@ -22,17 +23,17 @@ type IssuesInSprintResult struct {
Issues []Issue `json:"issues"` Issues []Issue `json:"issues"`
} }
// MoveIssuesToSprint moves issues to a sprint, for a given sprint Id. // MoveIssuesToSprintWithContext moves issues to a sprint, for a given sprint Id.
// Issues can only be moved to open or active sprints. // Issues can only be moved to open or active sprints.
// The maximum number of issues that can be moved in one operation is 50. // The maximum number of issues that can be moved in one operation is 50.
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-moveIssuesToSprint // JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-moveIssuesToSprint
func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Response, error) { func (s *SprintService) MoveIssuesToSprintWithContext(ctx context.Context, sprintID int, issueIDs []string) (*Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID) apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID)
payload := IssuesWrapper{Issues: issueIDs} payload := IssuesWrapper{Issues: issueIDs}
req, err := s.client.NewRequest("POST", apiEndpoint, payload) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload)
if err != nil { if err != nil {
return nil, err return nil, err
@ -45,15 +46,20 @@ func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Re
return resp, err return resp, err
} }
// GetIssuesForSprint returns all issues in a sprint, for a given sprint Id. // MoveIssuesToSprint wraps MoveIssuesToSprintWithContext using the background context.
func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Response, error) {
return s.MoveIssuesToSprintWithContext(context.Background(), sprintID, issueIDs)
}
// GetIssuesForSprintWithContext returns all issues in a sprint, for a given sprint Id.
// This only includes issues that the user has permission to view. // This only includes issues that the user has permission to view.
// By default, the returned issues are ordered by rank. // By default, the returned issues are ordered by rank.
// //
// JIRA API Docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-getIssuesForSprint // JIRA API Docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-getIssuesForSprint
func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, error) { func (s *SprintService) GetIssuesForSprintWithContext(ctx context.Context, sprintID int) ([]Issue, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID) apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -68,7 +74,12 @@ func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, er
return result.Issues, resp, err return result.Issues, resp, err
} }
// GetIssue returns a full representation of the issue for the given issue key. // GetIssuesForSprint wraps GetIssuesForSprintWithContext using the background context.
func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, error) {
return s.GetIssuesForSprintWithContext(context.Background(), sprintID)
}
// GetIssueWithContext returns a full representation of the issue for the given issue key.
// JIRA will attempt to identify the issue by the issueIdOrKey path parameter. // JIRA will attempt to identify the issue by the issueIdOrKey path parameter.
// This can be an issue id, or an issue key. // This can be an issue id, or an issue key.
// If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved. // If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved.
@ -78,10 +89,10 @@ func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, er
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/7.3.1/#agile/1.0/issue-getIssue // JIRA API docs: https://docs.atlassian.com/jira-software/REST/7.3.1/#agile/1.0/issue-getIssue
// //
// TODO: create agile service for holding all agile apis' implementation // TODO: create agile service for holding all agile apis' implementation
func (s *SprintService) GetIssue(issueID string, options *GetQueryOptions) (*Issue, *Response, error) { func (s *SprintService) GetIssueWithContext(ctx context.Context, issueID string, options *GetQueryOptions) (*Issue, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/issue/%s", issueID) apiEndpoint := fmt.Sprintf("rest/agile/1.0/issue/%s", issueID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -105,3 +116,8 @@ func (s *SprintService) GetIssue(issueID string, options *GetQueryOptions) (*Iss
return issue, resp, nil return issue, resp, nil
} }
// GetIssue wraps GetIssueWithContext using the background context.
func (s *SprintService) GetIssue(issueID string, options *GetQueryOptions) (*Issue, *Response, error) {
return s.GetIssueWithContext(context.Background(), issueID, options)
}

View File

@ -1,5 +1,7 @@
package jira package jira
import "context"
// StatusService handles staties for the JIRA instance / API. // StatusService handles staties for the JIRA instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Workflow-statuses // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Workflow-statuses
@ -19,12 +21,12 @@ type Status struct {
StatusCategory StatusCategory `json:"statusCategory" structs:"statusCategory"` StatusCategory StatusCategory `json:"statusCategory" structs:"statusCategory"`
} }
// GetAllStatuses returns a list of all statuses associated with workflows. // GetAllStatusesWithContext returns a list of all statuses associated with workflows.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-status-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-status-get
func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) { func (s *StatusService) GetAllStatusesWithContext(ctx context.Context) ([]Status, *Response, error) {
apiEndpoint := "rest/api/2/status" apiEndpoint := "rest/api/2/status"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -38,3 +40,8 @@ func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) {
return statusList, resp, nil return statusList, resp, nil
} }
// GetAllStatuses wraps GetAllStatusesWithContext using the background context.
func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) {
return s.GetAllStatusesWithContext(context.Background())
}

View File

@ -1,5 +1,7 @@
package jira package jira
import "context"
// StatusCategoryService handles status categories for the JIRA instance / API. // StatusCategoryService handles status categories for the JIRA instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Statuscategory // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Statuscategory
@ -25,12 +27,12 @@ const (
StatusCategoryUndefined = "undefined" StatusCategoryUndefined = "undefined"
) )
// GetList gets all status categories from JIRA // GetListWithContext gets all status categories from JIRA
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-statuscategory-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-statuscategory-get
func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) { func (s *StatusCategoryService) GetListWithContext(ctx context.Context) ([]StatusCategory, *Response, error) {
apiEndpoint := "rest/api/2/statuscategory" apiEndpoint := "rest/api/2/statuscategory"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx,"GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -42,3 +44,8 @@ func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) {
} }
return statusCategoryList, resp, nil return statusCategoryList, resp, nil
} }
// GetList wraps GetListWithContext using the background context.
func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) {
return s.GetListWithContext(context.Background())
}

78
user.go
View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -47,16 +48,16 @@ type userSearch []userSearchParam
type userSearchF func(userSearch) userSearch type userSearchF func(userSearch) userSearch
// Get gets user info from JIRA // GetWithContext gets user info from JIRA
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser
// //
// /!\ Deprecation notice: https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-user-privacy-api-migration-guide/ // /!\ Deprecation notice: https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-user-privacy-api-migration-guide/
// By 29 April 2019, we will remove personal data from the API that is used to identify users, // By 29 April 2019, we will remove personal data from the API that is used to identify users,
// such as username and userKey, and instead use the Atlassian account ID (accountId). // such as username and userKey, and instead use the Atlassian account ID (accountId).
func (s *UserService) Get(username string) (*User, *Response, error) { func (s *UserService) GetWithContext(ctx context.Context, username string) (*User, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username) apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -69,12 +70,17 @@ func (s *UserService) Get(username string) (*User, *Response, error) {
return user, resp, nil return user, resp, nil
} }
// Get gets user info from JIRA // Get wraps GetWithContext using the background context.
func (s *UserService) Get(username string) (*User, *Response, error) {
return s.GetWithContext(context.Background(), username)
}
// GetByAccountIDWithContext gets user info from JIRA
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser
func (s *UserService) GetByAccountID(accountID string) (*User, *Response, error) { func (s *UserService) GetByAccountIDWithContext(ctx context.Context, accountID string) (*User, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountID) apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -87,12 +93,17 @@ func (s *UserService) GetByAccountID(accountID string) (*User, *Response, error)
return user, resp, nil return user, resp, nil
} }
// Create creates an user in JIRA. // GetByAccountID wraps GetByAccountIDWithContext using the background context.
func (s *UserService) GetByAccountID(accountID string) (*User, *Response, error) {
return s.GetByAccountIDWithContext(context.Background(), accountID)
}
// CreateWithContext creates an user in JIRA.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-createUser // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-createUser
func (s *UserService) Create(user *User) (*User, *Response, error) { func (s *UserService) CreateWithContext(ctx context.Context, user *User) (*User, *Response, error) {
apiEndpoint := "/rest/api/2/user" apiEndpoint := "/rest/api/2/user"
req, err := s.client.NewRequest("POST", apiEndpoint, user) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, user)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -117,13 +128,18 @@ func (s *UserService) Create(user *User) (*User, *Response, error) {
return responseUser, resp, nil return responseUser, resp, nil
} }
// Delete deletes an user from JIRA. // Create wraps CreateWithContext using the background context.
func (s *UserService) Create(user *User) (*User, *Response, error) {
return s.CreateWithContext(context.Background(), user)
}
// DeleteWithContext deletes an user from JIRA.
// Returns http.StatusNoContent on success. // Returns http.StatusNoContent on success.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-user-delete // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-user-delete
func (s *UserService) Delete(username string) (*Response, error) { func (s *UserService) DeleteWithContext(ctx context.Context, username string) (*Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username) apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username)
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -135,12 +151,17 @@ func (s *UserService) Delete(username string) (*Response, error) {
return resp, nil return resp, nil
} }
// GetGroups returns the groups which the user belongs to // Delete wraps DeleteWithContext using the background context.
func (s *UserService) Delete(username string) (*Response, error) {
return s.DeleteWithContext(context.Background(), username)
}
// GetGroupsWithContext returns the groups which the user belongs to
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUserGroups // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUserGroups
func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error) { func (s *UserService) GetGroupsWithContext(ctx context.Context, username string) (*[]UserGroup, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/user/groups?username=%s", username) apiEndpoint := fmt.Sprintf("/rest/api/2/user/groups?username=%s", username)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -153,12 +174,17 @@ func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error
return userGroups, resp, nil return userGroups, resp, nil
} }
// Get information about the current logged-in user // GetGroups wraps GetGroupsWithContext using the background context.
func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error) {
return s.GetGroupsWithContext(context.Background(), username)
}
// GetSelfWithContext information about the current logged-in user
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-myself-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-myself-get
func (s *UserService) GetSelf() (*User, *Response, error) { func (s *UserService) GetSelfWithContext(ctx context.Context) (*User, *Response, error) {
const apiEndpoint = "rest/api/2/myself" const apiEndpoint = "rest/api/2/myself"
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -170,6 +196,11 @@ func (s *UserService) GetSelf() (*User, *Response, error) {
return &user, resp, nil return &user, resp, nil
} }
// GetSelf wraps GetSelfWithContext using the background context.
func (s *UserService) GetSelf() (*User, *Response, error) {
return s.GetSelfWithContext(context.Background())
}
// WithMaxResults sets the max results to return // WithMaxResults sets the max results to return
func WithMaxResults(maxResults int) userSearchF { func WithMaxResults(maxResults int) userSearchF {
return func(s userSearch) userSearch { return func(s userSearch) userSearch {
@ -202,11 +233,11 @@ func WithInactive(inactive bool) userSearchF {
} }
} }
// Find searches for user info from JIRA: // FindWithContext searches for user info from JIRA:
// It can find users by email, username or name // It can find users by email, username or name
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-findUsers // JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-findUsers
func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Response, error) { func (s *UserService) FindWithContext(ctx context.Context, property string, tweaks ...userSearchF) ([]User, *Response, error) {
search := []userSearchParam{ search := []userSearchParam{
{ {
name: "username", name: "username",
@ -223,7 +254,7 @@ func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Res
} }
apiEndpoint := fmt.Sprintf("/rest/api/2/user/search?%s", queryString[:len(queryString)-1]) apiEndpoint := fmt.Sprintf("/rest/api/2/user/search?%s", queryString[:len(queryString)-1])
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -235,3 +266,8 @@ func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Res
} }
return users, resp, nil return users, resp, nil
} }
// Find wraps FindWithContext using the background context.
func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Response, error) {
return s.FindWithContext(context.Background(), property, tweaks...)
}

View File

@ -1,6 +1,7 @@
package jira package jira
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -27,12 +28,12 @@ type Version struct {
StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"` StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"`
} }
// Get gets version info from JIRA // GetWithContext gets version info from JIRA
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-get // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-get
func (s *VersionService) Get(versionID int) (*Version, *Response, error) { func (s *VersionService) GetWithContext(ctx context.Context, versionID int) (*Version, *Response, error) {
apiEndpoint := fmt.Sprintf("/rest/api/2/version/%v", versionID) apiEndpoint := fmt.Sprintf("/rest/api/2/version/%v", versionID)
req, err := s.client.NewRequest("GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -45,12 +46,17 @@ func (s *VersionService) Get(versionID int) (*Version, *Response, error) {
return version, resp, nil return version, resp, nil
} }
// Create creates a version in JIRA. // Get wraps GetWithContext using the background context.
func (s *VersionService) Get(versionID int) (*Version, *Response, error) {
return s.GetWithContext(context.Background(), versionID)
}
// CreateWithContext creates a version in JIRA.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-post // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-post
func (s *VersionService) Create(version *Version) (*Version, *Response, error) { func (s *VersionService) CreateWithContext(ctx context.Context, version *Version) (*Version, *Response, error) {
apiEndpoint := "/rest/api/2/version" apiEndpoint := "/rest/api/2/version"
req, err := s.client.NewRequest("POST", apiEndpoint, version) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, version)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -75,12 +81,17 @@ func (s *VersionService) Create(version *Version) (*Version, *Response, error) {
return responseVersion, resp, nil return responseVersion, resp, nil
} }
// Update updates a version from a JSON representation. // Create wraps CreateWithContext using the background context.
func (s *VersionService) Create(version *Version) (*Version, *Response, error) {
return s.CreateWithContext(context.Background(), version)
}
// UpdateWithContext updates a version from a JSON representation.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-put // JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-put
func (s *VersionService) Update(version *Version) (*Version, *Response, error) { func (s *VersionService) UpdateWithContext(ctx context.Context, version *Version) (*Version, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/version/%v", version.ID) apiEndpoint := fmt.Sprintf("rest/api/2/version/%v", version.ID)
req, err := s.client.NewRequest("PUT", apiEndpoint, version) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, version)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -95,3 +106,8 @@ func (s *VersionService) Update(version *Version) (*Version, *Response, error) {
ret := *version ret := *version
return &ret, resp, nil return &ret, resp, nil
} }
// Update wraps UpdateWithContext using the background context.
func (s *VersionService) Update(version *Version) (*Version, *Response, error) {
return s.UpdateWithContext(context.Background(), version)
}