1
0
mirror of https://github.com/interviewstreet/go-jira.git synced 2025-06-25 00:16:45 +02:00

fix(product): Make product naming consistent, rename JIRA to Jira (#286)

Atlassian names the product "Jira".
In this library, the product name is used different (JIRA) and
inconsistent (sometimes JIRA, sometimes Jira).

closes issue #284
This commit is contained in:
Andy Grunwald
2020-05-14 17:18:31 +02:00
committed by GitHub
parent f6b1dcafcf
commit 146229d2ab
25 changed files with 239 additions and 239 deletions

View File

@ -4,23 +4,23 @@
[![Build Status](https://travis-ci.org/andygrunwald/go-jira.svg?branch=master)](https://travis-ci.org/andygrunwald/go-jira) [![Build Status](https://travis-ci.org/andygrunwald/go-jira.svg?branch=master)](https://travis-ci.org/andygrunwald/go-jira)
[![Go Report Card](https://goreportcard.com/badge/github.com/andygrunwald/go-jira)](https://goreportcard.com/report/github.com/andygrunwald/go-jira) [![Go Report Card](https://goreportcard.com/badge/github.com/andygrunwald/go-jira)](https://goreportcard.com/report/github.com/andygrunwald/go-jira)
[Go](https://golang.org/) client library for [Atlassian JIRA](https://www.atlassian.com/software/jira). [Go](https://golang.org/) client library for [Atlassian Jira](https://www.atlassian.com/software/jira).
![Go client library for Atlassian JIRA](./img/logo_small.png "Go client library for Atlassian JIRA.") ![Go client library for Atlassian Jira](./img/logo_small.png "Go client library for Atlassian Jira.")
## Features ## Features
* Authentication (HTTP Basic, OAuth, Session Cookie) * Authentication (HTTP Basic, OAuth, Session Cookie)
* Create and retrieve issues * Create and retrieve issues
* Create and retrieve issue transitions (status updates) * Create and retrieve issue transitions (status updates)
* Call every API endpoint of the JIRA, even if it is not directly implemented in this library * Call every API endpoint of the Jira, even if it is not directly implemented in this library
This package is not JIRA API complete (yet), but you can call every API endpoint you want. See [Call a not implemented API endpoint](#call-a-not-implemented-api-endpoint) how to do this. For all possible API endpoints of JIRA have a look at [latest JIRA REST API documentation](https://docs.atlassian.com/jira/REST/latest/). This package is not Jira API complete (yet), but you can call every API endpoint you want. See [Call a not implemented API endpoint](#call-a-not-implemented-api-endpoint) how to do this. For all possible API endpoints of Jira have a look at [latest Jira REST API documentation](https://docs.atlassian.com/jira/REST/latest/).
## Requirements ## Requirements
* Go >= 1.8 * Go >= 1.8
* JIRA v6.3.4 & v7.1.2. * Jira v6.3.4 & v7.1.2.
## Installation ## Installation
@ -52,7 +52,7 @@ go test -v ./...
Please have a look at the [GoDoc documentation](https://godoc.org/github.com/andygrunwald/go-jira) for a detailed API description. Please have a look at the [GoDoc documentation](https://godoc.org/github.com/andygrunwald/go-jira) for a detailed API description.
The [latest JIRA REST API documentation](https://docs.atlassian.com/jira/REST/latest/) was the base document for this package. The [latest Jira REST API documentation](https://docs.atlassian.com/jira/REST/latest/) was the base document for this package.
## Examples ## Examples
@ -113,12 +113,12 @@ func main() {
#### Authenticate with session cookie [DEPRECATED] #### Authenticate with session cookie [DEPRECATED]
JIRA [deprecated this authentication method.](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-basic-auth-and-cookie-based-auth/) It's not longer available for use. Jira [deprecated this authentication method.](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-basic-auth-and-cookie-based-auth/) It's not longer available for use.
#### Authenticate with OAuth #### Authenticate with OAuth
If you want to connect via OAuth to your JIRA Cloud instance checkout the [example of using OAuth authentication with JIRA in Go](https://gist.github.com/Lupus/edafe9a7c5c6b13407293d795442fe67) by [@Lupus](https://github.com/Lupus). If you want to connect via OAuth to your Jira Cloud instance checkout the [example of using OAuth authentication with Jira in Go](https://gist.github.com/Lupus/edafe9a7c5c6b13407293d795442fe67) by [@Lupus](https://github.com/Lupus).
For more details have a look at the [issue #56](https://github.com/andygrunwald/go-jira/issues/56). For more details have a look at the [issue #56](https://github.com/andygrunwald/go-jira/issues/56).
@ -175,9 +175,9 @@ func main() {
### Call a not implemented API endpoint ### Call a not implemented API endpoint
Not all API endpoints of the JIRA API are implemented into *go-jira*. Not all API endpoints of the Jira API are implemented into *go-jira*.
But you can call them anyway: But you can call them anyway:
Lets get all public projects of [Atlassian`s JIRA instance](https://jira.atlassian.com/). Lets get all public projects of [Atlassian`s Jira instance](https://jira.atlassian.com/).
```go ```go
package main package main
@ -209,7 +209,7 @@ func main() {
// ... // ...
// BAM: Bamboo // BAM: Bamboo
// BAMJ: Bamboo JIRA Plugin // BAMJ: Bamboo Jira Plugin
// CLOV: Clover // CLOV: Clover
// CONF: Confluence // CONF: Confluence
// ... // ...
@ -218,7 +218,7 @@ func main() {
## Implementations ## Implementations
* [andygrunwald/jitic](https://github.com/andygrunwald/jitic) - The JIRA Ticket Checker * [andygrunwald/jitic](https://github.com/andygrunwald/jitic) - The Jira Ticket Checker
## Code structure ## Code structure
@ -226,7 +226,7 @@ The code structure of this package was inspired by [google/go-github](https://gi
There is one main part (the client). There is one main part (the client).
Based on this main client the other endpoints, like Issues or Authentication are extracted in services. E.g. `IssueService` or `AuthenticationService`. Based on this main client the other endpoints, like Issues or Authentication are extracted in services. E.g. `IssueService` or `AuthenticationService`.
These services own a responsibility of the single endpoints / usecases of JIRA. These services own a responsibility of the single endpoints / usecases of Jira.
## Contribution ## Contribution

View File

@ -15,9 +15,9 @@ const (
authTypeSession = 2 authTypeSession = 2
) )
// AuthenticationService handles authentication for the JIRA instance / API. // AuthenticationService handles authentication for the Jira instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#authentication // Jira API docs: https://docs.atlassian.com/jira/REST/latest/#authentication
type AuthenticationService struct { type AuthenticationService struct {
client *Client client *Client
@ -31,7 +31,7 @@ type AuthenticationService struct {
password string password string
} }
// Session represents a Session JSON response by the JIRA API. // Session represents a Session JSON response by the Jira API.
type Session struct { type Session struct {
Self string `json:"self,omitempty"` Self string `json:"self,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
@ -48,13 +48,13 @@ type Session struct {
Cookies []*http.Cookie Cookies []*http.Cookie
} }
// AcquireSessionCookieWithContext 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.
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user). // However, this resource may be used to mimic the behaviour of Jira's log-in page (e.g. to display log-in errors to a 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
// //
// Deprecated: Use CookieAuthTransport instead // Deprecated: Use CookieAuthTransport instead
func (s *AuthenticationService) AcquireSessionCookieWithContext(ctx context.Context, username, password string) (bool, error) { func (s *AuthenticationService) AcquireSessionCookieWithContext(ctx context.Context, username, password string) (bool, error) {
@ -99,7 +99,7 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
return s.AcquireSessionCookieWithContext(context.Background(), username, password) 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
func (s *AuthenticationService) SetBasicAuth(username, password string) { func (s *AuthenticationService) SetBasicAuth(username, password string) {
@ -108,7 +108,7 @@ func (s *AuthenticationService) SetBasicAuth(username, password string) {
s.authType = authTypeBasic s.authType = authTypeBasic
} }
// Authenticated reports if the current Client has authentication details for JIRA // Authenticated reports if the current Client has authentication details for Jira
func (s *AuthenticationService) Authenticated() bool { func (s *AuthenticationService) Authenticated() bool {
if s != nil { if s != nil {
if s.authType == authTypeSession { if s.authType == authTypeSession {
@ -123,7 +123,7 @@ func (s *AuthenticationService) Authenticated() bool {
// LogoutWithContext 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
@ -163,7 +163,7 @@ func (s *AuthenticationService) Logout() error {
// GetCurrentUserWithContext gets the details of the current user. // 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) GetCurrentUserWithContext(ctx context.Context) (*Session, error) { func (s *AuthenticationService) GetCurrentUserWithContext(ctx context.Context) (*Session, error) {
if s == nil { if s == nil {
return nil, fmt.Errorf("authentication Service is not instantiated") return nil, fmt.Errorf("authentication Service is not instantiated")

View File

@ -7,9 +7,9 @@ import (
"time" "time"
) )
// BoardService handles Agile Boards for the JIRA instance / API. // BoardService handles Agile Boards for the Jira instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/server/ // Jira API docs: https://docs.atlassian.com/jira-software/REST/server/
type BoardService struct { type BoardService struct {
client *Client client *Client
} }
@ -23,7 +23,7 @@ type BoardsList struct {
Values []Board `json:"values" structs:"values"` Values []Board `json:"values" structs:"values"`
} }
// Board represents a JIRA agile board // Board represents a Jira agile board
type Board struct { type Board struct {
ID int `json:"id,omitempty" structs:"id,omitempty"` ID int `json:"id,omitempty" structs:"id,omitempty"`
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
@ -63,7 +63,7 @@ type SprintsList struct {
Values []Sprint `json:"values" structs:"values"` Values []Sprint `json:"values" structs:"values"`
} }
// Sprint represents a sprint on JIRA agile board // Sprint represents a sprint on Jira agile board
type Sprint struct { type Sprint struct {
ID int `json:"id" structs:"id"` ID int `json:"id" structs:"id"`
Name string `json:"name" structs:"name"` Name string `json:"name" structs:"name"`
@ -127,7 +127,7 @@ type BoardConfigurationColumnStatus struct {
// GetAllBoardsWithContext 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) GetAllBoardsWithContext(ctx context.Context, 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)
@ -157,7 +157,7 @@ func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Respon
// GetBoardWithContext will returns the board for the given boardID. // 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) GetBoardWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -187,7 +187,7 @@ func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) {
// Note, if the user does not have the 'Create shared objects' permission and tries to create a shared board, a private // Note, if the user does not have the 'Create shared objects' permission and tries to create a shared board, a private
// 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) CreateBoardWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, board) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, board)
@ -212,7 +212,7 @@ func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) {
// DeleteBoardWithContext will delete an agile 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) DeleteBoardWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
@ -235,7 +235,7 @@ func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
// GetAllSprintsWithContext will return all sprints from a board, for a given board Id. // 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) GetAllSprintsWithContext(ctx context.Context, 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 {
@ -258,7 +258,7 @@ func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error
// GetAllSprintsWithOptionsWithContext will return sprints from a board, for a given board Id and filtering options // 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) GetAllSprintsWithOptionsWithContext(ctx context.Context, 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)

View File

@ -2,14 +2,13 @@ package jira
import "context" 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
type ComponentService struct { type ComponentService struct {
client *Client client *Client
} }
// CreateComponentOptions are passed to the ComponentService.Create function to create a new JIRA component // CreateComponentOptions are passed to the ComponentService.Create function to create a new Jira component
type CreateComponentOptions struct { type CreateComponentOptions struct {
Name string `json:"name,omitempty" structs:"name,omitempty"` Name string `json:"name,omitempty" structs:"name,omitempty"`
Description string `json:"description,omitempty" structs:"description,omitempty"` Description string `json:"description,omitempty" structs:"description,omitempty"`
@ -21,7 +20,7 @@ type CreateComponentOptions struct {
ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"` ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"`
} }
// CreateWithContext creates a new JIRA component based on the given options. // CreateWithContext creates a new Jira component based on the given options.
func (s *ComponentService) CreateWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, options) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, options)

View File

@ -14,7 +14,7 @@ func TestComponentService_Create_Success(t *testing.T) {
testRequestURL(t, r, "/rest/api/2/component") testRequestURL(t, r, "/rest/api/2/component")
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
fmt.Fprint(w, `{ "self": "http://www.example.com/jira/rest/api/2/component/10000", "id": "10000", "name": "Component 1", "description": "This is a JIRA component", "lead": { "self": "http://www.example.com/jira/rest/api/2/user?username=fred", "name": "fred", "avatarUrls": { "48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", "24x24": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred", "16x16": "http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", "32x32": "http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred" }, "displayName": "Fred F. User", "active": false }, "assigneeType": "PROJECT_LEAD", "assignee": { "self": "http://www.example.com/jira/rest/api/2/user?username=fred", "name": "fred", "avatarUrls": { "48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", "24x24": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred", "16x16": "http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", "32x32": "http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred" }, "displayName": "Fred F. User", "active": false }, "realAssigneeType": "PROJECT_LEAD", "realAssignee": { "self": "http://www.example.com/jira/rest/api/2/user?username=fred", "name": "fred", "avatarUrls": { "48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", "24x24": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred", "16x16": "http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", "32x32": "http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred" }, "displayName": "Fred F. User", "active": false }, "isAssigneeTypeValid": false, "project": "HSP", "projectId": 10000 }`) fmt.Fprint(w, `{ "self": "http://www.example.com/jira/rest/api/2/component/10000", "id": "10000", "name": "Component 1", "description": "This is a Jira component", "lead": { "self": "http://www.example.com/jira/rest/api/2/user?username=fred", "name": "fred", "avatarUrls": { "48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", "24x24": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred", "16x16": "http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", "32x32": "http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred" }, "displayName": "Fred F. User", "active": false }, "assigneeType": "PROJECT_LEAD", "assignee": { "self": "http://www.example.com/jira/rest/api/2/user?username=fred", "name": "fred", "avatarUrls": { "48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", "24x24": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred", "16x16": "http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", "32x32": "http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred" }, "displayName": "Fred F. User", "active": false }, "realAssigneeType": "PROJECT_LEAD", "realAssignee": { "self": "http://www.example.com/jira/rest/api/2/user?username=fred", "name": "fred", "avatarUrls": { "48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", "24x24": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred", "16x16": "http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", "32x32": "http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred" }, "displayName": "Fred F. User", "active": false }, "isAssigneeTypeValid": false, "project": "HSP", "projectId": 10000 }`)
}) })
component, _, err := testClient.Component.Create(&CreateComponentOptions{ component, _, err := testClient.Component.Create(&CreateComponentOptions{

View File

@ -10,7 +10,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Error message from JIRA // Error message from Jira
// See https://docs.atlassian.com/jira/REST/cloud/#error-responses // See https://docs.atlassian.com/jira/REST/cloud/#error-responses
type Error struct { type Error struct {
HTTPError error HTTPError error

View File

@ -2,14 +2,14 @@ package jira
import "context" 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
type FieldService struct { type FieldService struct {
client *Client client *Client
} }
// Field represents a field of a JIRA issue. // Field represents a field of a Jira issue.
type Field struct { type Field struct {
ID string `json:"id,omitempty" structs:"id,omitempty"` ID string `json:"id,omitempty" structs:"id,omitempty"`
Key string `json:"key,omitempty" structs:"key,omitempty"` Key string `json:"key,omitempty" structs:"key,omitempty"`
@ -26,9 +26,9 @@ type FieldSchema struct {
System string `json:"system,omitempty" structs:"system,omitempty"` System string `json:"system,omitempty" structs:"system,omitempty"`
} }
// GetListWithContext 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) GetListWithContext(ctx context.Context) ([]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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

View File

@ -2,13 +2,14 @@ package jira
import ( import (
"context" "context"
"fmt"
"github.com/google/go-querystring/query" "github.com/google/go-querystring/query"
) )
import "fmt"
// FilterService handles fields for the JIRA instance / API. // FilterService handles fields for the Jira instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Filter // Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Filter
type FilterService struct { type FilterService struct {
client *Client client *Client
} }
@ -224,7 +225,7 @@ func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter
// SearchWithContext will search for filter according to the search options // 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) SearchWithContext(ctx context.Context, 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)

View File

@ -6,9 +6,9 @@ import (
"net/url" "net/url"
) )
// GroupService handles Groups for the JIRA instance / API. // GroupService handles Groups for the Jira instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group // Jira API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group
type GroupService struct { type GroupService struct {
client *Client client *Client
} }
@ -22,7 +22,7 @@ type groupMembersResult struct {
Members []GroupMember `json:"values"` Members []GroupMember `json:"values"`
} }
// Group represents a JIRA group // Group represents a Jira group
type Group struct { type Group struct {
ID string `json:"id"` ID string `json:"id"`
Title string `json:"title"` Title string `json:"title"`
@ -63,7 +63,7 @@ type GroupSearchOptions struct {
// 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) GetWithContext(ctx context.Context, name string) ([]GroupMember, *Response, error) { func (s *GroupService) GetWithContext(ctx context.Context, name string) ([]GroupMember, *Response, error) {
@ -91,7 +91,7 @@ func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) {
// 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) GetWithOptionsWithContext(ctx context.Context, 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 {
@ -125,7 +125,7 @@ func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions)
// AddWithContext adds user to group // 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) AddWithContext(ctx context.Context, 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 {
@ -154,7 +154,7 @@ func (s *GroupService) Add(groupname string, username string) (*Group, *Response
// RemoveWithContext removes user from group // 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) RemoveWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)

115
issue.go
View File

@ -21,13 +21,13 @@ import (
) )
const ( const (
// AssigneeAutomatic represents the value of the "Assignee: Automatic" of JIRA // AssigneeAutomatic represents the value of the "Assignee: Automatic" of Jira
AssigneeAutomatic = "-1" AssigneeAutomatic = "-1"
) )
// IssueService handles Issues for the JIRA instance / API. // IssueService handles Issues for the Jira instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue // Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue
type IssueService struct { type IssueService struct {
client *Client client *Client
} }
@ -39,7 +39,7 @@ type UpdateQueryOptions struct {
OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"` OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"`
} }
// Issue represents a JIRA issue. // Issue represents a Jira issue.
type Issue struct { type Issue struct {
Expand string `json:"expand,omitempty" structs:"expand,omitempty"` Expand string `json:"expand,omitempty" structs:"expand,omitempty"`
ID string `json:"id,omitempty" structs:"id,omitempty"` ID string `json:"id,omitempty" structs:"id,omitempty"`
@ -75,7 +75,7 @@ type Changelog struct {
Histories []ChangelogHistory `json:"histories,omitempty"` Histories []ChangelogHistory `json:"histories,omitempty"`
} }
// Attachment represents a JIRA attachment // Attachment represents a Jira attachment
type Attachment struct { type Attachment struct {
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
ID string `json:"id,omitempty" structs:"id,omitempty"` ID string `json:"id,omitempty" structs:"id,omitempty"`
@ -99,8 +99,8 @@ type Epic struct {
Done bool `json:"done" structs:"done"` Done bool `json:"done" structs:"done"`
} }
// IssueFields represents single fields of a JIRA issue. // IssueFields represents single fields of a Jira issue.
// Every JIRA issue has several fields attached. // Every Jira issue has several fields attached.
type IssueFields struct { type IssueFields struct {
// TODO Missing fields // TODO Missing fields
// * "workratio": -1, // * "workratio": -1,
@ -147,7 +147,7 @@ type IssueFields struct {
} }
// MarshalJSON is a custom JSON marshal function for the IssueFields structs. // MarshalJSON is a custom JSON marshal function for the IssueFields structs.
// It handles JIRA custom fields and maps those from / to "Unknowns" key. // It handles Jira custom fields and maps those from / to "Unknowns" key.
func (i *IssueFields) MarshalJSON() ([]byte, error) { func (i *IssueFields) MarshalJSON() ([]byte, error) {
m := structs.Map(i) m := structs.Map(i)
unknowns, okay := m["Unknowns"] unknowns, okay := m["Unknowns"]
@ -162,7 +162,7 @@ func (i *IssueFields) MarshalJSON() ([]byte, error) {
} }
// UnmarshalJSON is a custom JSON marshal function for the IssueFields structs. // UnmarshalJSON is a custom JSON marshal function for the IssueFields structs.
// It handles JIRA custom fields and maps those from / to "Unknowns" key. // It handles Jira custom fields and maps those from / to "Unknowns" key.
func (i *IssueFields) UnmarshalJSON(data []byte) error { func (i *IssueFields) UnmarshalJSON(data []byte) error {
// Do the normal unmarshalling first // Do the normal unmarshalling first
@ -210,7 +210,7 @@ func (i *IssueFields) UnmarshalJSON(data []byte) error {
} }
// IssueRenderedFields represents rendered fields of a JIRA issue. // IssueRenderedFields represents rendered fields of a Jira issue.
// Not all IssueFields are rendered. // Not all IssueFields are rendered.
type IssueRenderedFields struct { type IssueRenderedFields struct {
// TODO Missing fields // TODO Missing fields
@ -228,7 +228,7 @@ type IssueRenderedFields struct {
Description string `json:"description,omitempty" structs:"description,omitempty"` Description string `json:"description,omitempty" structs:"description,omitempty"`
} }
// IssueType represents a type of a JIRA issue. // IssueType represents a type of a Jira issue.
// Typical types are "Request", "Bug", "Story", ... // Typical types are "Request", "Bug", "Story", ...
type IssueType struct { type IssueType struct {
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
@ -240,7 +240,7 @@ type IssueType struct {
AvatarID int `json:"avatarId,omitempty" structs:"avatarId,omitempty"` AvatarID int `json:"avatarId,omitempty" structs:"avatarId,omitempty"`
} }
// Watches represents a type of how many and which user are "observing" a JIRA issue to track the status / updates. // Watches represents a type of how many and which user are "observing" a Jira issue to track the status / updates.
type Watches struct { type Watches struct {
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
WatchCount int `json:"watchCount,omitempty" structs:"watchCount,omitempty"` WatchCount int `json:"watchCount,omitempty" structs:"watchCount,omitempty"`
@ -265,35 +265,35 @@ type AvatarUrls struct {
Three2X32 string `json:"32x32,omitempty" structs:"32x32,omitempty"` Three2X32 string `json:"32x32,omitempty" structs:"32x32,omitempty"`
} }
// Component represents a "component" of a JIRA issue. // Component represents a "component" of a Jira issue.
// Components can be user defined in every JIRA instance. // Components can be user defined in every Jira instance.
type Component struct { type Component struct {
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
ID string `json:"id,omitempty" structs:"id,omitempty"` ID string `json:"id,omitempty" structs:"id,omitempty"`
Name string `json:"name,omitempty" structs:"name,omitempty"` Name string `json:"name,omitempty" structs:"name,omitempty"`
} }
// Progress represents the progress of a JIRA issue. // Progress represents the progress of a Jira issue.
type Progress struct { type Progress struct {
Progress int `json:"progress" structs:"progress"` Progress int `json:"progress" structs:"progress"`
Total int `json:"total" structs:"total"` Total int `json:"total" structs:"total"`
Percent int `json:"percent" structs:"percent"` Percent int `json:"percent" structs:"percent"`
} }
// Parent represents the parent of a JIRA issue, to be used with subtask issue types. // Parent represents the parent of a Jira issue, to be used with subtask issue types.
type Parent struct { type Parent struct {
ID string `json:"id,omitempty" structs:"id"` ID string `json:"id,omitempty" structs:"id"`
Key string `json:"key,omitempty" structs:"key"` Key string `json:"key,omitempty" structs:"key"`
} }
// Time represents the Time definition of JIRA as a time.Time of go // Time represents the Time definition of Jira as a time.Time of go
type Time time.Time type Time time.Time
func (t Time) Equal(u Time) bool { func (t Time) Equal(u Time) bool {
return time.Time(t).Equal(time.Time(u)) return time.Time(t).Equal(time.Time(u))
} }
// Date represents the Date definition of JIRA as a time.Time of go // Date represents the Date definition of Jira as a time.Time of go
type Date time.Time type Date time.Time
// Wrapper struct for search result // Wrapper struct for search result
@ -301,7 +301,7 @@ type transitionResult struct {
Transitions []Transition `json:"transitions" structs:"transitions"` Transitions []Transition `json:"transitions" structs:"transitions"`
} }
// Transition represents an issue transition in JIRA // Transition represents an issue transition in Jira
type Transition struct { type Transition struct {
ID string `json:"id" structs:"id"` ID string `json:"id" structs:"id"`
Name string `json:"name" structs:"name"` Name string `json:"name" structs:"name"`
@ -336,8 +336,8 @@ type Option struct {
Value string `json:"value" structs:"value"` Value string `json:"value" structs:"value"`
} }
// UnmarshalJSON will transform the JIRA time into a time.Time // UnmarshalJSON will transform the Jira time into a time.Time
// during the transformation of the JIRA JSON response // during the transformation of the Jira JSON response
func (t *Time) UnmarshalJSON(b []byte) error { func (t *Time) UnmarshalJSON(b []byte) error {
// Ignore null, like in the main JSON package. // Ignore null, like in the main JSON package.
if string(b) == "null" { if string(b) == "null" {
@ -351,14 +351,14 @@ func (t *Time) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// MarshalJSON will transform the time.Time into a JIRA time // MarshalJSON will transform the time.Time into a Jira time
// during the creation of a JIRA request // during the creation of a Jira request
func (t Time) MarshalJSON() ([]byte, error) { func (t Time) MarshalJSON() ([]byte, error) {
return []byte(time.Time(t).Format("\"2006-01-02T15:04:05.000-0700\"")), nil return []byte(time.Time(t).Format("\"2006-01-02T15:04:05.000-0700\"")), nil
} }
// UnmarshalJSON will transform the JIRA date into a time.Time // UnmarshalJSON will transform the Jira date into a time.Time
// during the transformation of the JIRA JSON response // during the transformation of the Jira JSON response
func (t *Date) UnmarshalJSON(b []byte) error { func (t *Date) UnmarshalJSON(b []byte) error {
// Ignore null, like in the main JSON package. // Ignore null, like in the main JSON package.
if string(b) == "null" { if string(b) == "null" {
@ -373,16 +373,16 @@ func (t *Date) UnmarshalJSON(b []byte) error {
} }
// MarshalJSON will transform the Date object into a short // MarshalJSON will transform the Date object into a short
// date string as JIRA expects during the creation of a // date string as Jira expects during the creation of a
// JIRA request // Jira request
func (t Date) MarshalJSON() ([]byte, error) { func (t Date) MarshalJSON() ([]byte, error) {
time := time.Time(t) time := time.Time(t)
return []byte(time.Format("\"2006-01-02\"")), nil return []byte(time.Format("\"2006-01-02\"")), nil
} }
// Worklog represents the work log of a JIRA issue. // Worklog represents the work log of a Jira issue.
// One Worklog contains zero or n WorklogRecords // One Worklog contains zero or n WorklogRecords
// JIRA Wiki: https://confluence.atlassian.com/jira/logging-work-on-an-issue-185729605.html // Jira Wiki: https://confluence.atlassian.com/jira/logging-work-on-an-issue-185729605.html
type Worklog struct { type Worklog struct {
StartAt int `json:"startAt" structs:"startAt"` StartAt int `json:"startAt" structs:"startAt"`
MaxResults int `json:"maxResults" structs:"maxResults"` MaxResults int `json:"maxResults" structs:"maxResults"`
@ -411,7 +411,7 @@ type EntityProperty struct {
Value interface{} `json:"value"` Value interface{} `json:"value"`
} }
// TimeTracking represents the timetracking fields of a JIRA issue. // TimeTracking represents the timetracking fields of a Jira issue.
type TimeTracking struct { type TimeTracking struct {
OriginalEstimate string `json:"originalEstimate,omitempty" structs:"originalEstimate,omitempty"` OriginalEstimate string `json:"originalEstimate,omitempty" structs:"originalEstimate,omitempty"`
RemainingEstimate string `json:"remainingEstimate,omitempty" structs:"remainingEstimate,omitempty"` RemainingEstimate string `json:"remainingEstimate,omitempty" structs:"remainingEstimate,omitempty"`
@ -429,7 +429,7 @@ type Subtasks struct {
Fields IssueFields `json:"fields" structs:"fields"` Fields IssueFields `json:"fields" structs:"fields"`
} }
// IssueLink represents a link between two issues in JIRA. // IssueLink represents a link between two issues in Jira.
type IssueLink struct { type IssueLink struct {
ID string `json:"id,omitempty" structs:"id,omitempty"` ID string `json:"id,omitempty" structs:"id,omitempty"`
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
@ -439,7 +439,7 @@ type IssueLink struct {
Comment *Comment `json:"comment,omitempty" structs:"comment,omitempty"` Comment *Comment `json:"comment,omitempty" structs:"comment,omitempty"`
} }
// IssueLinkType represents a type of a link between to issues in JIRA. // IssueLinkType represents a type of a link between to issues in Jira.
// Typical issue link types are "Related to", "Duplicate", "Is blocked by", etc. // Typical issue link types are "Related to", "Duplicate", "Is blocked by", etc.
type IssueLinkType struct { type IssueLinkType struct {
ID string `json:"id,omitempty" structs:"id,omitempty"` ID string `json:"id,omitempty" structs:"id,omitempty"`
@ -454,7 +454,7 @@ type Comments struct {
Comments []*Comment `json:"comments,omitempty" structs:"comments,omitempty"` Comments []*Comment `json:"comments,omitempty" structs:"comments,omitempty"`
} }
// Comment represents a comment by a person to an issue in JIRA. // Comment represents a comment by a person to an issue in Jira.
type Comment struct { type Comment struct {
ID string `json:"id,omitempty" structs:"id,omitempty"` ID string `json:"id,omitempty" structs:"id,omitempty"`
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
@ -493,7 +493,7 @@ type CommentVisibility struct {
// SearchOptions specifies the optional parameters to various List methods that // SearchOptions specifies the optional parameters to various List methods that
// support pagination. // support pagination.
// Pagination is used for the JIRA REST APIs to conserve server resources and limit // Pagination is used for the Jira REST APIs to conserve server resources and limit
// response size for resources that return potentially large collection of items. // response size for resources that return potentially large collection of items.
// A request to a pages API will result in a values array wrapped in a JSON object with some paging metadata // A request to a pages API will result in a values array wrapped in a JSON object with some paging metadata
// Default Pagination options // Default Pagination options
@ -547,8 +547,8 @@ type AddWorklogQueryOptions struct {
OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"` OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"`
} }
// CustomFields represents custom fields of JIRA // CustomFields represents custom fields of Jira
// This can heavily differ between JIRA instances // This can heavily differ between Jira instances
type CustomFields map[string]string type CustomFields map[string]string
// RemoteLink represents remote links which linked to issues // RemoteLink represents remote links which linked to issues
@ -590,13 +590,13 @@ type RemoteLinkStatus struct {
} }
// GetWithContext 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.
// //
// 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) GetWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -767,7 +767,7 @@ func WithQueryOptions(options interface{}) func(*http.Request) error {
// 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) CreateWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, issue) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, issue)
@ -801,7 +801,7 @@ func (s *IssueService) Create(issue *Issue) (*Issue, *Response, error) {
// UpdateWithOptionsWithContext updates an issue from a JSON representation, // UpdateWithOptionsWithContext updates an issue from a JSON representation,
// while also specifying query params. The issue is found by key. // while also specifying 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) UpdateWithOptionsWithContext(ctx context.Context, 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)
@ -831,7 +831,7 @@ func (s *IssueService) UpdateWithOptions(issue *Issue, opts *UpdateQueryOptions)
// UpdateWithContext updates an issue from a JSON representation. The issue is found by key. // 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) UpdateWithContext(ctx context.Context, 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)
} }
@ -867,7 +867,7 @@ func (s *IssueService) UpdateIssue(jiraID string, data map[string]interface{}) (
// AddCommentWithContext adds a new comment to issueID. // 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) AddCommentWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, comment) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, comment)
@ -892,7 +892,7 @@ func (s *IssueService) AddComment(issueID string, comment *Comment) (*Comment, *
// UpdateCommentWithContext updates the body of a comment, identified by comment.ID, on the issueID. // 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) UpdateCommentWithContext(ctx context.Context, 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"`
@ -921,7 +921,7 @@ func (s *IssueService) UpdateComment(issueID string, comment *Comment) (*Comment
// DeleteCommentWithContext Deletes a comment from an issueID. // 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) DeleteCommentWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
@ -1009,7 +1009,7 @@ func (s *IssueService) UpdateWorklogRecord(issueID, worklogID string, record *Wo
// AddLinkWithContext adds a link between two issues. // 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) AddLinkWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, issueLink) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, issueLink)
@ -1032,7 +1032,7 @@ func (s *IssueService) AddLink(issueLink *IssueLink) (*Response, error) {
// SearchWithContext will search for tickets according to the jql // 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) SearchWithContext(ctx context.Context, 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",
@ -1043,7 +1043,6 @@ func (s *IssueService) SearchWithContext(ctx context.Context, jql string, option
} }
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))
} }
@ -1083,7 +1082,7 @@ func (s *IssueService) Search(jql string, options *SearchOptions) ([]Issue, *Res
// SearchPagesWithContext will get issues from all pages in a search // 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) SearchPagesWithContext(ctx context.Context, 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{
@ -1175,7 +1174,7 @@ func (s *IssueService) GetCustomFields(issueID string) (CustomFields, *Response,
// GetTransitionsWithContext gets a list of the transitions possible for this issue by the current user, // 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) GetTransitionsWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -1199,7 +1198,7 @@ func (s *IssueService) GetTransitions(id string) ([]Transition, *Response, error
// DoTransitionWithContext performs a transition on an issue. // 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) DoTransitionWithContext(ctx context.Context, 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{
@ -1217,7 +1216,7 @@ func (s *IssueService) DoTransition(ticketID, transitionID string) (*Response, e
// DoTransitionWithPayloadWithContext performs a transition on an issue using any payload. // 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) DoTransitionWithPayloadWithContext(ctx context.Context, 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)
@ -1343,7 +1342,7 @@ func (s *IssueService) Delete(issueID string) (*Response, error) {
// GetWatchersWithContext wil return all the users watching/observing the given issue // 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) GetWatchersWithContext(ctx context.Context, 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)
@ -1386,7 +1385,7 @@ func (s *IssueService) GetWatchers(issueID string) (*[]User, *Response, error) {
// AddWatcherWithContext adds watcher to the given issue // 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) AddWatcherWithContext(ctx context.Context, 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)
@ -1410,7 +1409,7 @@ func (s *IssueService) AddWatcher(issueID string, userName string) (*Response, e
// RemoveWatcherWithContext removes given user from given issue // 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) RemoveWatcherWithContext(ctx context.Context, 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)
@ -1434,7 +1433,7 @@ func (s *IssueService) RemoveWatcher(issueID string, userName string) (*Response
// UpdateAssigneeWithContext updates the user assigned to work on the given issue // 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) UpdateAssigneeWithContext(ctx context.Context, 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)
@ -1468,7 +1467,7 @@ func (c ChangelogHistory) CreatedTime() (time.Time, error) {
// GetRemoteLinksWithContext 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) GetRemoteLinksWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -1491,7 +1490,7 @@ func (s *IssueService) GetRemoteLinks(id string) (*[]RemoteLink, *Response, erro
// AddRemoteLinkWithContext adds a remote link to issueID. // 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) AddRemoteLinkWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, remotelink) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, remotelink)

View File

@ -7,16 +7,16 @@ import (
"io/ioutil" "io/ioutil"
) )
// IssueLinkTypeService handles issue link types for the JIRA instance / API. // IssueLinkTypeService handles issue link types for the Jira instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Issue-link-types // Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Issue-link-types
type IssueLinkTypeService struct { type IssueLinkTypeService struct {
client *Client client *Client
} }
// GetListWithContext 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) GetListWithContext(ctx context.Context) ([]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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -37,9 +37,9 @@ func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) {
return s.GetListWithContext(context.Background()) return s.GetListWithContext(context.Background())
} }
// GetWithContext gets info of a specific issue link type from JIRA. // 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) GetWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil)
@ -60,9 +60,9 @@ func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error)
return s.GetWithContext(context.Background(), ID) return s.GetWithContext(context.Background(), ID)
} }
// CreateWithContext creates an issue link type in JIRA. // 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) CreateWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, linkType) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, linkType)
@ -97,7 +97,7 @@ func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType,
// UpdateWithContext updates an issue link type. The issue is found by key. // 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) UpdateWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "PUT", apiEndpoint, linkType) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, linkType)
@ -119,7 +119,7 @@ func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType,
// DeleteWithContext deletes an issue link type based on provided ID. // 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) DeleteWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)

18
jira.go
View File

@ -26,7 +26,7 @@ type httpClient interface {
Do(request *http.Request) (response *http.Response, err error) Do(request *http.Request) (response *http.Response, err error)
} }
// A Client manages communication with the JIRA API. // A Client manages communication with the Jira API.
type Client struct { type Client struct {
// HTTP client used to communicate with the API. // HTTP client used to communicate with the API.
client httpClient client httpClient
@ -37,7 +37,7 @@ type Client struct {
// Session storage if the user authenticates with a Session cookie // Session storage if the user authenticates with a Session cookie
session *Session session *Session
// Services used for talking to different parts of the JIRA API. // Services used for talking to different parts of the Jira API.
Authentication *AuthenticationService Authentication *AuthenticationService
Issue *IssueService Issue *IssueService
Project *ProjectService Project *ProjectService
@ -58,13 +58,13 @@ type Client struct {
IssueLinkType *IssueLinkTypeService IssueLinkType *IssueLinkTypeService
} }
// NewClient returns a new JIRA API client. // NewClient returns a new Jira API client.
// If a nil httpClient is provided, http.DefaultClient will be used. // If a nil httpClient is provided, http.DefaultClient will be used.
// To use API methods which require authentication you can follow the preferred solution and // To use API methods which require authentication you can follow the preferred solution and
// provide an http.Client that will perform the authentication for you with OAuth and HTTP Basic (such as that provided by the golang.org/x/oauth2 library). // provide an http.Client that will perform the authentication for you with OAuth and HTTP Basic (such as that provided by the golang.org/x/oauth2 library).
// As an alternative you can use Session Cookie based authentication provided by this package as well. // As an alternative you can use Session Cookie based authentication provided by this package as well.
// See https://docs.atlassian.com/jira/REST/latest/#authentication // See https://docs.atlassian.com/jira/REST/latest/#authentication
// baseURL is the HTTP endpoint of your JIRA instance and should always be specified with a trailing slash. // baseURL is the HTTP endpoint of your Jira instance and should always be specified with a trailing slash.
func NewClient(httpClient httpClient, baseURL string) (*Client, error) { func NewClient(httpClient httpClient, baseURL string) (*Client, error) {
if httpClient == nil { if httpClient == nil {
httpClient = http.DefaultClient httpClient = http.DefaultClient
@ -295,7 +295,7 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
// CheckResponse checks the API response for errors, and returns them if present. // CheckResponse checks the API response for errors, and returns them if present.
// A response is considered an error if it has a status code outside the 200 range. // A response is considered an error if it has a status code outside the 200 range.
// The caller is responsible to analyze the response body. // The caller is responsible to analyze the response body.
// The body can contain JSON (if the error is intended) or xml (sometimes JIRA just failes). // The body can contain JSON (if the error is intended) or xml (sometimes Jira just failes).
func CheckResponse(r *http.Response) error { func CheckResponse(r *http.Response) error {
if c := r.StatusCode; 200 <= c && c <= 299 { if c := r.StatusCode; 200 <= c && c <= 299 {
return nil return nil
@ -311,7 +311,7 @@ func (c *Client) GetBaseURL() url.URL {
return *c.baseURL return *c.baseURL
} }
// Response represents JIRA API response. It wraps http.Response returned from // Response represents Jira API response. It wraps http.Response returned from
// API and provides information about paging. // API and provides information about paging.
type Response struct { type Response struct {
*http.Response *http.Response
@ -382,9 +382,9 @@ func (t *BasicAuthTransport) transport() http.RoundTripper {
// using Jira's cookie-based authentication. // using Jira's cookie-based authentication.
// //
// Note that it is generally preferable to use HTTP BASIC authentication with the REST API. // Note that it is generally preferable to use HTTP BASIC authentication with the REST API.
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user). // However, this resource may be used to mimic the behaviour of Jira's log-in page (e.g. to display log-in errors to a 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
type CookieAuthTransport struct { type CookieAuthTransport struct {
Username string Username string
Password string Password string
@ -479,7 +479,7 @@ func (t *CookieAuthTransport) transport() http.RoundTripper {
// //
// NOTE: this form of auth should be used by add-ons installed from the Atlassian marketplace. // NOTE: this form of auth should be used by add-ons installed from the Atlassian marketplace.
// //
// JIRA docs: https://developer.atlassian.com/cloud/jira/platform/understanding-jwt // Jira docs: https://developer.atlassian.com/cloud/jira/platform/understanding-jwt
// Examples in other languages: // Examples in other languages:
// https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/d44a8e7a4649e4f23edaa784402655fda7c816ea/lib/atlassian/jwt.rb // https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/d44a8e7a4649e4f23edaa784402655fda7c816ea/lib/atlassian/jwt.rb
// https://bitbucket.org/atlassian/atlassian-jwt-py/src/master/atlassian_jwt/url_utils.py // https://bitbucket.org/atlassian/atlassian-jwt-py/src/master/atlassian_jwt/url_utils.py

View File

@ -14,14 +14,14 @@ import (
) )
const ( const (
testJIRAInstanceURL = "https://issues.apache.org/jira/" testJiraInstanceURL = "https://issues.apache.org/jira/"
) )
var ( var (
// testMux is the HTTP request multiplexer used with the test server. // testMux is the HTTP request multiplexer used with the test server.
testMux *http.ServeMux testMux *http.ServeMux
// testClient is the JIRA client being tested. // testClient is the Jira client being tested.
testClient *Client testClient *Client
// testServer is a test HTTP server used to provide mock API responses. // testServer is a test HTTP server used to provide mock API responses.
@ -86,7 +86,8 @@ func TestNewClient_WrongUrl(t *testing.T) {
func TestNewClient_WithHttpClient(t *testing.T) { func TestNewClient_WithHttpClient(t *testing.T) {
httpClient := http.DefaultClient httpClient := http.DefaultClient
httpClient.Timeout = 10 * time.Minute httpClient.Timeout = 10 * time.Minute
c, err := NewClient(httpClient, testJIRAInstanceURL)
c, err := NewClient(httpClient, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("Got an error: %s", err) t.Errorf("Got an error: %s", err)
} }
@ -100,7 +101,7 @@ func TestNewClient_WithHttpClient(t *testing.T) {
} }
func TestNewClient_WithServices(t *testing.T) { func TestNewClient_WithServices(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("Got an error: %s", err) t.Errorf("Got an error: %s", err)
@ -156,12 +157,12 @@ func TestCheckResponse(t *testing.T) {
} }
func TestClient_NewRequest(t *testing.T) { func TestClient_NewRequest(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
inURL, outURL := "rest/api/2/issue/", testJIRAInstanceURL+"rest/api/2/issue/" inURL, outURL := "rest/api/2/issue/", testJiraInstanceURL+"rest/api/2/issue/"
inBody, outBody := &Issue{Key: "MESOS"}, `{"key":"MESOS"}`+"\n" inBody, outBody := &Issue{Key: "MESOS"}, `{"key":"MESOS"}`+"\n"
req, _ := c.NewRequest("GET", inURL, inBody) req, _ := c.NewRequest("GET", inURL, inBody)
@ -178,12 +179,12 @@ func TestClient_NewRequest(t *testing.T) {
} }
func TestClient_NewRawRequest(t *testing.T) { func TestClient_NewRawRequest(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
inURL, outURL := "rest/api/2/issue/", testJIRAInstanceURL+"rest/api/2/issue/" inURL, outURL := "rest/api/2/issue/", testJiraInstanceURL+"rest/api/2/issue/"
outBody := `{"key":"MESOS"}` + "\n" outBody := `{"key":"MESOS"}` + "\n"
inBody := outBody inBody := outBody
@ -211,7 +212,7 @@ func testURLParseError(t *testing.T, err error) {
} }
func TestClient_NewRequest_BadURL(t *testing.T) { func TestClient_NewRequest_BadURL(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
@ -220,7 +221,7 @@ func TestClient_NewRequest_BadURL(t *testing.T) {
} }
func TestClient_NewRequest_SessionCookies(t *testing.T) { func TestClient_NewRequest_SessionCookies(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
@ -249,7 +250,7 @@ func TestClient_NewRequest_SessionCookies(t *testing.T) {
} }
func TestClient_NewRequest_BasicAuth(t *testing.T) { func TestClient_NewRequest_BasicAuth(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
@ -275,7 +276,7 @@ func TestClient_NewRequest_BasicAuth(t *testing.T) {
// since there is no difference between an HTTP request body that is an empty string versus one that is not set at all. // since there is no difference between an HTTP request body that is an empty string versus one that is not set at all.
// However in certain cases, intermediate systems may treat these differently resulting in subtle errors. // However in certain cases, intermediate systems may treat these differently resulting in subtle errors.
func TestClient_NewRequest_EmptyBody(t *testing.T) { func TestClient_NewRequest_EmptyBody(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
@ -289,7 +290,7 @@ func TestClient_NewRequest_EmptyBody(t *testing.T) {
} }
func TestClient_NewMultiPartRequest(t *testing.T) { func TestClient_NewMultiPartRequest(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
@ -322,7 +323,7 @@ func TestClient_NewMultiPartRequest(t *testing.T) {
} }
func TestClient_NewMultiPartRequest_BasicAuth(t *testing.T) { func TestClient_NewMultiPartRequest_BasicAuth(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("An error occurred. Expected nil. Got %+v.", err) t.Errorf("An error occurred. Expected nil. Got %+v.", err)
} }
@ -411,7 +412,7 @@ func TestClient_Do_HTTPError(t *testing.T) {
} }
// Test handling of an error caused by the internal http client's Do() function. // Test handling of an error caused by the internal http client's Do() function.
// A redirect loop is pretty unlikely to occur within the JIRA API, but does allow us to exercise the right code path. // A redirect loop is pretty unlikely to occur within the Jira API, but does allow us to exercise the right code path.
func TestClient_Do_RedirectLoop(t *testing.T) { func TestClient_Do_RedirectLoop(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -432,12 +433,12 @@ func TestClient_Do_RedirectLoop(t *testing.T) {
} }
func TestClient_GetBaseURL_WithURL(t *testing.T) { func TestClient_GetBaseURL_WithURL(t *testing.T) {
u, err := url.Parse(testJIRAInstanceURL) u, err := url.Parse(testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("URL parsing -> Got an error: %s", err) t.Errorf("URL parsing -> Got an error: %s", err)
} }
c, err := NewClient(nil, testJIRAInstanceURL) c, err := NewClient(nil, testJiraInstanceURL)
if err != nil { if err != nil {
t.Errorf("Client creation -> Got an error: %s", err) t.Errorf("Client creation -> Got an error: %s", err)
} }

View File

@ -71,7 +71,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10004", "self": "https://test.jira.org/rest/api/2/status/10004",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "QA", "name": "QA",
"id": "10004", "id": "10004",
@ -85,7 +85,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10005", "self": "https://test.jira.org/rest/api/2/status/10005",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "Icebox", "name": "Icebox",
"id": "10005", "id": "10005",
@ -99,7 +99,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10006", "self": "https://test.jira.org/rest/api/2/status/10006",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "To Be Specced", "name": "To Be Specced",
"id": "10006", "id": "10006",
@ -113,7 +113,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10100", "self": "https://test.jira.org/rest/api/2/status/10100",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "Blocked", "name": "Blocked",
"id": "10100", "id": "10100",
@ -141,7 +141,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10205", "self": "https://test.jira.org/rest/api/2/status/10205",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "Validation", "name": "Validation",
"id": "10205", "id": "10205",
@ -155,7 +155,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10300", "self": "https://test.jira.org/rest/api/2/status/10300",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "Graveyard", "name": "Graveyard",
"id": "10300", "id": "10300",
@ -281,7 +281,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10510", "self": "https://test.jira.org/rest/api/2/status/10510",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "cannot reproduce", "name": "cannot reproduce",
"id": "10510", "id": "10510",
@ -295,7 +295,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10601", "self": "https://test.jira.org/rest/api/2/status/10601",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "Done", "name": "Done",
"id": "10601", "id": "10601",
@ -309,7 +309,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10602", "self": "https://test.jira.org/rest/api/2/status/10602",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "In Progress", "name": "In Progress",
"id": "10602", "id": "10602",
@ -323,7 +323,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10603", "self": "https://test.jira.org/rest/api/2/status/10603",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "Backlog", "name": "Backlog",
"id": "10603", "id": "10603",
@ -337,7 +337,7 @@
}, },
{ {
"self": "https://test.jira.org/rest/api/2/status/10700", "self": "https://test.jira.org/rest/api/2/status/10700",
"description": "This status is managed internally by JIRA Software", "description": "This status is managed internally by Jira Software",
"iconUrl": "https://test.jira.org/", "iconUrl": "https://test.jira.org/",
"name": "Specs Complete", "name": "Specs Complete",
"id": "10700", "id": "10700",

View File

@ -78,9 +78,9 @@
{ {
"self": "https://issues.apache.org/jira/rest/api/2/issuetype/8", "self": "https://issues.apache.org/jira/rest/api/2/issuetype/8",
"id": "8", "id": "8",
"description": "A request for a new JIRA project to be set up", "description": "A request for a new Jira project to be set up",
"iconUrl": "https://issues.apache.org/jira/images/icons/jiraman18.gif", "iconUrl": "https://issues.apache.org/jira/images/icons/jiraman18.gif",
"name": "New JIRA Project", "name": "New Jira Project",
"subtask": false "subtask": false
}, },
{ {
@ -102,7 +102,7 @@
{ {
"self": "https://issues.apache.org/jira/rest/api/2/issuetype/11", "self": "https://issues.apache.org/jira/rest/api/2/issuetype/11",
"id": "11", "id": "11",
"description": "A formal question. Initially added for the Legal JIRA.", "description": "A formal question. Initially added for the Legal Jira.",
"iconUrl": "https://issues.apache.org/jira/images/icons/issuetypes/genericissue.png", "iconUrl": "https://issues.apache.org/jira/images/icons/issuetypes/genericissue.png",
"name": "Question", "name": "Question",
"subtask": false "subtask": false
@ -134,7 +134,7 @@
{ {
"self": "https://issues.apache.org/jira/rest/api/2/issuetype/15", "self": "https://issues.apache.org/jira/rest/api/2/issuetype/15",
"id": "15", "id": "15",
"description": "Created by JIRA Agile - do not edit or delete. Issue type for a big user story that needs to be broken down.", "description": "Created by Jira Agile - do not edit or delete. Issue type for a big user story that needs to be broken down.",
"iconUrl": "https://issues.apache.org/jira/images/icons/issuetypes/epic.png", "iconUrl": "https://issues.apache.org/jira/images/icons/issuetypes/epic.png",
"name": "Epic", "name": "Epic",
"subtask": false "subtask": false
@ -142,7 +142,7 @@
{ {
"self": "https://issues.apache.org/jira/rest/api/2/issuetype/16", "self": "https://issues.apache.org/jira/rest/api/2/issuetype/16",
"id": "16", "id": "16",
"description": "Created by JIRA Agile - do not edit or delete. Issue type for a user story.", "description": "Created by Jira Agile - do not edit or delete. Issue type for a user story.",
"iconUrl": "https://issues.apache.org/jira/images/icons/issuetypes/story.png", "iconUrl": "https://issues.apache.org/jira/images/icons/issuetypes/story.png",
"name": "Story", "name": "Story",
"subtask": false "subtask": false
@ -278,7 +278,7 @@
{ {
"self": "https://issues.apache.org/jira/rest/api/2/issuetype/10300", "self": "https://issues.apache.org/jira/rest/api/2/issuetype/10300",
"id": "10300", "id": "10300",
"description": "For general IT problems and questions. Created by JIRA Service Desk.", "description": "For general IT problems and questions. Created by Jira Service Desk.",
"iconUrl": "https://issues.apache.org/jira/servicedesk/issue-type-icons?icon=it-help", "iconUrl": "https://issues.apache.org/jira/servicedesk/issue-type-icons?icon=it-help",
"name": "IT Help", "name": "IT Help",
"subtask": false "subtask": false
@ -286,7 +286,7 @@
{ {
"self": "https://issues.apache.org/jira/rest/api/2/issuetype/10301", "self": "https://issues.apache.org/jira/rest/api/2/issuetype/10301",
"id": "10301", "id": "10301",
"description": "For new system accounts or passwords. Created by JIRA Service Desk.", "description": "For new system accounts or passwords. Created by Jira Service Desk.",
"iconUrl": "https://issues.apache.org/jira/servicedesk/issue-type-icons?icon=access", "iconUrl": "https://issues.apache.org/jira/servicedesk/issue-type-icons?icon=access",
"name": "Access", "name": "Access",
"subtask": false "subtask": false

View File

@ -5,9 +5,9 @@ import (
"fmt" "fmt"
) )
// PermissionSchemeService handles permissionschemes for the JIRA instance / API. // PermissionSchemeService handles permissionschemes for the Jira instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Permissionscheme // Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Permissionscheme
type PermissionSchemeService struct { type PermissionSchemeService struct {
client *Client client *Client
} }
@ -30,7 +30,7 @@ type Holder struct {
// GetListWithContext 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) GetListWithContext(ctx context.Context) (*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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -55,7 +55,7 @@ func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, erro
// GetWithContext returns a full representation of the permission scheme for the schemeID // 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) GetWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

View File

@ -2,14 +2,14 @@ package jira
import "context" 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
type PriorityService struct { type PriorityService struct {
client *Client client *Client
} }
// Priority represents a priority of a JIRA issue. // Priority represents a priority of a Jira issue.
// Typical types are "Normal", "Moderate", "Urgent", ... // Typical types are "Normal", "Moderate", "Urgent", ...
type Priority struct { type Priority struct {
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
@ -20,9 +20,9 @@ type Priority struct {
Description string `json:"description,omitempty" structs:"description,omitempty"` Description string `json:"description,omitempty" structs:"description,omitempty"`
} }
// GetListWithContext 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) GetListWithContext(ctx context.Context) ([]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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

View File

@ -7,9 +7,9 @@ import (
"github.com/google/go-querystring/query" "github.com/google/go-querystring/query"
) )
// ProjectService handles projects for the JIRA instance / API. // ProjectService handles projects for the Jira instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project // Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project
type ProjectService struct { type ProjectService struct {
client *Client client *Client
} }
@ -35,7 +35,7 @@ type ProjectCategory struct {
Description string `json:"description" structs:"description,omitempty"` Description string `json:"description" structs:"description,omitempty"`
} }
// Project represents a JIRA Project. // Project represents a Jira Project.
type Project struct { type Project struct {
Expand string `json:"expand,omitempty" structs:"expand,omitempty"` Expand string `json:"expand,omitempty" structs:"expand,omitempty"`
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
@ -81,9 +81,9 @@ type PermissionScheme struct {
Permissions []Permission `json:"permissions" structs:"permissions,omitempty"` Permissions []Permission `json:"permissions" structs:"permissions,omitempty"`
} }
// GetListWithContext 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) GetListWithContext(ctx context.Context) (*ProjectList, *Response, error) { func (s *ProjectService) GetListWithContext(ctx context.Context) (*ProjectList, *Response, error) {
return s.ListWithOptionsWithContext(ctx, &GetQueryOptions{}) return s.ListWithOptionsWithContext(ctx, &GetQueryOptions{})
} }
@ -93,10 +93,10 @@ func (s *ProjectService) GetList() (*ProjectList, *Response, error) {
return s.GetListWithContext(context.Background()) return s.GetListWithContext(context.Background())
} }
// ListWithOptionsWithContext gets all projects form JIRA with optional query params, like &GetQueryOptions{Expand: "issueTypes"} to get // 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) ListWithOptionsWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -128,10 +128,10 @@ func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList
} }
// GetWithContext returns a full representation of the project for the given issue key. // 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) GetWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -155,10 +155,10 @@ func (s *ProjectService) Get(projectID string) (*Project, *Response, error) {
} }
// GetPermissionSchemeWithContext returns a full representation of the permission scheme for the project // 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) GetPermissionSchemeWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

View File

@ -2,14 +2,14 @@ package jira
import "context" 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
type ResolutionService struct { type ResolutionService struct {
client *Client client *Client
} }
// Resolution represents a resolution of a JIRA issue. // Resolution represents a resolution of a Jira issue.
// Typical types are "Fixed", "Suspended", "Won't Fix", ... // Typical types are "Fixed", "Suspended", "Won't Fix", ...
type Resolution struct { type Resolution struct {
Self string `json:"self" structs:"self"` Self string `json:"self" structs:"self"`
@ -18,9 +18,9 @@ type Resolution struct {
Name string `json:"name" structs:"name"` Name string `json:"name" structs:"name"`
} }
// GetListWithContext 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) GetListWithContext(ctx context.Context) ([]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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

12
role.go
View File

@ -5,14 +5,14 @@ import (
"fmt" "fmt"
) )
// RoleService handles roles for the JIRA instance / API. // RoleService handles roles for the Jira instance / API.
// //
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Role // Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Role
type RoleService struct { type RoleService struct {
client *Client client *Client
} }
// Role represents a JIRA product role // Role represents a Jira product role
type Role struct { type Role struct {
Self string `json:"self" structs:"self"` Self string `json:"self" structs:"self"`
Name string `json:"name" structs:"name"` Name string `json:"name" structs:"name"`
@ -21,7 +21,7 @@ type Role struct {
Actors []*Actor `json:"actors" structs:"actors"` Actors []*Actor `json:"actors" structs:"actors"`
} }
// Actor represents a JIRA actor // Actor represents a Jira actor
type Actor struct { type Actor struct {
ID int `json:"id" structs:"id"` ID int `json:"id" structs:"id"`
DisplayName string `json:"displayName" structs:"displayName"` DisplayName string `json:"displayName" structs:"displayName"`
@ -38,7 +38,7 @@ type ActorUser struct {
// GetListWithContext 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) GetListWithContext(ctx context.Context) (*[]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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -61,7 +61,7 @@ func (s *RoleService) GetList() (*[]Role, *Response, error) {
// GetWithContext retreives a single Role from Jira // 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) GetWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

View File

@ -7,7 +7,7 @@ import (
"github.com/google/go-querystring/query" "github.com/google/go-querystring/query"
) )
// SprintService handles sprints in JIRA Agile API. // SprintService handles sprints in Jira Agile API.
// See https://docs.atlassian.com/jira-software/REST/cloud/ // See https://docs.atlassian.com/jira-software/REST/cloud/
type SprintService struct { type SprintService struct {
client *Client client *Client
@ -27,7 +27,7 @@ type IssuesInSprintResult struct {
// 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) MoveIssuesToSprintWithContext(ctx context.Context, 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)
@ -55,7 +55,7 @@ func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Re
// 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) GetIssuesForSprintWithContext(ctx context.Context, 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)
@ -80,13 +80,13 @@ func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, er
} }
// GetIssueWithContext returns a full representation of the issue for the given issue key. // 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.
// //
// 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-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) GetIssueWithContext(ctx context.Context, issueID string, options *GetQueryOptions) (*Issue, *Response, error) { func (s *SprintService) GetIssueWithContext(ctx context.Context, issueID string, options *GetQueryOptions) (*Issue, *Response, error) {

View File

@ -2,16 +2,16 @@ package jira
import "context" 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
type StatusService struct { type StatusService struct {
client *Client client *Client
} }
// Status represents the current status of a JIRA issue. // Status represents the current status of a Jira issue.
// Typical status are "Open", "In Progress", "Closed", ... // Typical status are "Open", "In Progress", "Closed", ...
// Status can be user defined in every JIRA instance. // Status can be user defined in every Jira instance.
type Status struct { type Status struct {
Self string `json:"self" structs:"self"` Self string `json:"self" structs:"self"`
Description string `json:"description" structs:"description"` Description string `json:"description" structs:"description"`
@ -23,7 +23,7 @@ type Status struct {
// GetAllStatusesWithContext 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) GetAllStatusesWithContext(ctx context.Context) ([]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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

View File

@ -2,15 +2,15 @@ package jira
import "context" 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
type StatusCategoryService struct { type StatusCategoryService struct {
client *Client client *Client
} }
// StatusCategory represents the category a status belongs to. // StatusCategory represents the category a status belongs to.
// Those categories can be user defined in every JIRA instance. // Those categories can be user defined in every Jira instance.
type StatusCategory struct { type StatusCategory struct {
Self string `json:"self" structs:"self"` Self string `json:"self" structs:"self"`
ID int `json:"id" structs:"id"` ID int `json:"id" structs:"id"`
@ -19,7 +19,7 @@ type StatusCategory struct {
ColorName string `json:"colorName" structs:"colorName"` ColorName string `json:"colorName" structs:"colorName"`
} }
// These constants are the keys of the default JIRA status categories // These constants are the keys of the default Jira status categories
const ( const (
StatusCategoryComplete = "done" StatusCategoryComplete = "done"
StatusCategoryInProgress = "indeterminate" StatusCategoryInProgress = "indeterminate"
@ -27,9 +27,9 @@ const (
StatusCategoryUndefined = "undefined" StatusCategoryUndefined = "undefined"
) )
// GetListWithContext 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) GetListWithContext(ctx context.Context) ([]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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)

30
user.go
View File

@ -7,14 +7,14 @@ import (
"io/ioutil" "io/ioutil"
) )
// UserService handles users for the JIRA instance / API. // UserService handles users for the Jira instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user // Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user
type UserService struct { type UserService struct {
client *Client client *Client
} }
// User represents a JIRA user. // User represents a Jira user.
type User struct { type User struct {
Self string `json:"self,omitempty" structs:"self,omitempty"` Self string `json:"self,omitempty" structs:"self,omitempty"`
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"` AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"`
@ -48,9 +48,9 @@ type userSearch []userSearchParam
type userSearchF func(userSearch) userSearch type userSearchF func(userSearch) userSearch
// GetWithContext 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,
@ -75,9 +75,9 @@ func (s *UserService) Get(username string) (*User, *Response, error) {
return s.GetWithContext(context.Background(), username) return s.GetWithContext(context.Background(), username)
} }
// GetByAccountIDWithContext gets user info from JIRA // 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) GetByAccountIDWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -98,9 +98,9 @@ func (s *UserService) GetByAccountID(accountID string) (*User, *Response, error)
return s.GetByAccountIDWithContext(context.Background(), accountID) return s.GetByAccountIDWithContext(context.Background(), accountID)
} }
// CreateWithContext creates an user in JIRA. // 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) CreateWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, user) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, user)
@ -133,10 +133,10 @@ func (s *UserService) Create(user *User) (*User, *Response, error) {
return s.CreateWithContext(context.Background(), user) return s.CreateWithContext(context.Background(), user)
} }
// DeleteWithContext deletes an user from JIRA. // 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) DeleteWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
@ -158,7 +158,7 @@ func (s *UserService) Delete(username string) (*Response, error) {
// GetGroupsWithContext returns the groups which the user belongs to // 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) GetGroupsWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -181,7 +181,7 @@ func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error
// GetSelfWithContext information about the current logged-in user // 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) GetSelfWithContext(ctx context.Context) (*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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -233,10 +233,10 @@ func WithInactive(inactive bool) userSearchF {
} }
} }
// FindWithContext 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) FindWithContext(ctx context.Context, 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{
{ {

View File

@ -7,9 +7,9 @@ import (
"io/ioutil" "io/ioutil"
) )
// VersionService handles Versions for the JIRA instance / API. // VersionService handles Versions for the Jira instance / API.
// //
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/version // Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/version
type VersionService struct { type VersionService struct {
client *Client client *Client
} }
@ -28,9 +28,9 @@ type Version struct {
StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"` StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"`
} }
// GetWithContext 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) GetWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@ -51,9 +51,9 @@ func (s *VersionService) Get(versionID int) (*Version, *Response, error) {
return s.GetWithContext(context.Background(), versionID) return s.GetWithContext(context.Background(), versionID)
} }
// CreateWithContext creates a version in JIRA. // 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) CreateWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "POST", apiEndpoint, version) req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, version)
@ -88,7 +88,7 @@ func (s *VersionService) Create(version *Version) (*Version, *Response, error) {
// UpdateWithContext updates a version from a JSON representation. // 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) UpdateWithContext(ctx context.Context, 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.NewRequestWithContext(ctx, "PUT", apiEndpoint, version) req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, version)