This repository has been archived by the owner on Jan 9, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Because - We need a Jira component to complete some development automation tasks - Related Issue: instill-ai/instill-core#1022 This commit - Support get boards/issue/epic/sprint TODO - [x] TASK_LIST_BOARDS: list all boards in Jira - [x] TASK_LIST_ISSUES: list issues in Jira by various methods - [x] TASK_GET_ISSUE: get an issue by ID or key - Note: This API can get issue/epic with the key since they use the same indexing system. - [x] TASK_GET_SPRINT: get a sprint by ID Next PR - create issue - create epic - create sprint Added by @chuang8511 to visualise Jira's design ![image](https://github.com/user-attachments/assets/17ff0aaf-5ab0-458c-95cd-a147f12e314a) --------- Co-authored-by: Chang, Hui-Tang <[email protected]>
- Loading branch information
Showing
17 changed files
with
3,435 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
--- | ||
title: "Jira" | ||
lang: "en-US" | ||
draft: false | ||
description: "Learn about how to set up a VDP Jira component https://github.com/instill-ai/instill-core" | ||
--- | ||
|
||
The Jira component is an application component that allows users to do anything available on Jira. | ||
It can carry out the following tasks: | ||
|
||
- [List Boards](#list-boards) | ||
- [List Issues](#list-issues) | ||
- [List Sprints](#list-sprints) | ||
- [Get Issue](#get-issue) | ||
- [Get Sprint](#get-sprint) | ||
|
||
|
||
|
||
## Release Stage | ||
|
||
`Alpha` | ||
|
||
|
||
|
||
## Configuration | ||
|
||
The component configuration is defined and maintained [here](https://github.com/instill-ai/component/blob/main/application/jira/v0/config/definition.json). | ||
|
||
|
||
|
||
|
||
## Setup | ||
|
||
|
||
| Field | Field ID | Type | Note | | ||
| :--- | :--- | :--- | :--- | | ||
| Token (required) | `token` | string | Fill in your Jira API token. You can generate one from your Jira account "settings > security > API tokens". | | ||
| Base URL (required) | `base-url` | string | Fill in your Jira base URL. For example, if your Jira URL is https://mycompany.atlassian.net, then your base URL is https://mycompany.atlassian.net. | | ||
| Email (required) | `email` | string | Fill in your Jira email address. | | ||
|
||
|
||
|
||
|
||
## Supported Tasks | ||
|
||
### List Boards | ||
|
||
List all boards in Jira | ||
|
||
|
||
| Input | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Task ID (required) | `task` | string | `TASK_LIST_BOARDS` | | ||
| Project Key or ID | `project-key-or-id` | string | This filters results to boards that are relevant to a project. Relevance meaning that the JQL filter defined in board contains a reference to a project. | | ||
| Board Type | `board-type` | string | The type of board, can be: scrum, kanban, simple. Default is simple | | ||
| Name | `name` | string | Name filters results to boards that match or partially match the specified name. Default is empty | | ||
| Start At | `start-at` | integer | The starting index of the returned boards. Base index: 0. Default is 0 | | ||
| Max Results | `max-results` | integer | The maximum number of boards to return. Default is 50 | | ||
|
||
|
||
|
||
| Output | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Boards (optional) | `boards` | array[object] | A array of boards in Jira | | ||
| Start At | `start-at` | integer | The starting index of the returned boards. Base index: 0 | | ||
| Max Results | `max-results` | integer | The maximum number of boards | | ||
| Total | `total` | integer | The total number of boards | | ||
| Is Last | `is-last` | boolean | Whether the last board is reached | | ||
|
||
|
||
|
||
|
||
|
||
|
||
### List Issues | ||
|
||
List issues in Jira | ||
|
||
|
||
| Input | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Task ID (required) | `task` | string | `TASK_LIST_ISSUES` | | ||
| Board ID (required) | `board-id` | integer | The ID of the board | | ||
| Range | `range` | object | Choose the range of issues to return. Default is `all` | | ||
| Start At | `start-at` | integer | The starting index of the returned boards. Base index: 0. Default is 0 | | ||
| Max Results | `max-results` | integer | The maximum number of boards to return. Default is 50 | | ||
|
||
|
||
|
||
| Output | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Issues (optional) | `issues` | array[object] | A array of issues in Jira | | ||
| Start At | `start-at` | integer | The starting index of the returned boards. Base index: 0 | | ||
| Max Results | `max-results` | integer | The maximum number of boards | | ||
| Total | `total` | integer | The total number of boards | | ||
|
||
|
||
|
||
|
||
|
||
|
||
### List Sprints | ||
|
||
List sprints in Jira | ||
|
||
|
||
| Input | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Task ID (required) | `task` | string | `TASK_LIST_SPRINTS` | | ||
| Board ID (required) | `board-id` | integer | The ID of the board | | ||
| Start At | `start-at` | integer | The starting index of the returned boards. Base index: 0. Default is 0 | | ||
| Max Results | `max-results` | integer | The maximum number of boards to return. Default is 50 | | ||
|
||
|
||
|
||
| Output | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Sprints (optional) | `sprints` | array[object] | A array of sprints in Jira | | ||
| Start At | `start-at` | integer | The starting index of the returned boards. Base index: 0 | | ||
| Max Results | `max-results` | integer | The maximum number of boards | | ||
| Total | `total` | integer | The total number of boards | | ||
|
||
|
||
|
||
|
||
|
||
|
||
### Get Issue | ||
|
||
Get an issue in Jira | ||
|
||
|
||
| Input | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Task ID (required) | `task` | string | `TASK_GET_ISSUE` | | ||
| Issue ID or Key (required) | `issue-id-or-key` | string | The ID or key of the issue | | ||
| Update History | `update-history` | boolean | Whether the project in which the issue is created is added to the user's Recently viewed project list, as shown under Projects in Jira. | | ||
|
||
|
||
|
||
| Output | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| ID | `id` | string | The ID of the issue | | ||
| Key | `key` | string | The key of the issue | | ||
| Self | `self` | string | The URL of the issue | | ||
| Fields | `fields` | object | The fields of the issue. All navigable and Agile fields are returned | | ||
| Issue Type (optional) | `issue-type` | string | The type of the issue, can be: `Task`, `Epic` | | ||
| Summary (optional) | `summary` | string | The summary of the issue | | ||
| Description (optional) | `description` | string | The description of the issue | | ||
| Status (optional) | `status` | string | The status of the issue, can be: `To Do`, `In Progress`, `Done` | | ||
|
||
|
||
|
||
|
||
|
||
|
||
### Get Sprint | ||
|
||
Get a sprint in Jira | ||
|
||
|
||
| Input | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| Task ID (required) | `task` | string | `TASK_GET_SPRINT` | | ||
| Sprint ID (required) | `sprint-id` | integer | The ID of the sprint. The sprint will only be returned if you can view the board that the sprint was created on, or view at least one of the issues in the sprint. | | ||
|
||
|
||
|
||
| Output | ID | Type | Description | | ||
| :--- | :--- | :--- | :--- | | ||
| ID (optional) | `id` | integer | The ID of the sprint | | ||
| Self (optional) | `self` | string | The URL of the sprint | | ||
| State (optional) | `state` | string | The state of the sprint, can be: `active`, `closed`, `future` | | ||
| Name (optional) | `name` | string | The name of the sprint | | ||
| Start Date (optional) | `start-date` | string | The start date of the sprint. In the RFC3339 format, e.g. 2018-03-05T00:00:00Z | | ||
| End Date (optional) | `end-date` | string | The end date of the sprint. In the RFC3339 format, e.g. 2018-03-05T00:00:00Z | | ||
| Complete Date (optional) | `complete-date` | string | The complete date of the sprint. In the RFC3339 format, e.g. 2018-03-05T00:00:00Z | | ||
| Origin Board ID (optional) | `origin-board-id` | integer | The ID of the origin board | | ||
| Goal (optional) | `goal` | string | The Goal of the sprint | | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package jira | ||
|
||
import ( | ||
"context" | ||
_ "embed" | ||
"fmt" | ||
|
||
"github.com/instill-ai/component/base" | ||
"github.com/instill-ai/x/errmsg" | ||
"google.golang.org/protobuf/types/known/structpb" | ||
) | ||
|
||
type Board struct { | ||
ID int `json:"id"` | ||
Name string `json:"name"` | ||
Self string `json:"self"` | ||
BoardType string `json:"type"` | ||
} | ||
|
||
type ListBoardsInput struct { | ||
ProjectKeyOrID string `json:"project-key-or-id,omitempty" api:"projectKeyOrId"` | ||
BoardType string `json:"board-type,omitempty" api:"type"` | ||
Name string `json:"name,omitempty" api:"name"` | ||
StartAt int `json:"start-at,omitempty" api:"startAt"` | ||
MaxResults int `json:"max-results,omitempty" api:"maxResults"` | ||
} | ||
type ListBoardsResp struct { | ||
Values []Board `json:"values"` | ||
StartAt int `json:"startAt"` | ||
MaxResults int `json:"maxResults"` | ||
Total int `json:"total"` | ||
IsLast bool `json:"isLast"` | ||
} | ||
|
||
type ListBoardsOutput struct { | ||
Boards []Board `json:"boards"` | ||
StartAt int `json:"start-at"` | ||
MaxResults int `json:"max-results"` | ||
Total int `json:"total"` | ||
IsLast bool `json:"is-last"` | ||
} | ||
|
||
func (jiraClient *Client) listBoardsTask(ctx context.Context, props *structpb.Struct) (*structpb.Struct, error) { | ||
var opt ListBoardsInput | ||
if err := base.ConvertFromStructpb(props, &opt); err != nil { | ||
return nil, err | ||
} | ||
|
||
boards, err := jiraClient.listBoards(ctx, &opt) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var output ListBoardsOutput | ||
output.Boards = append(output.Boards, boards.Values...) | ||
if output.Boards == nil { | ||
output.Boards = []Board{} | ||
} | ||
output.StartAt = boards.StartAt | ||
output.MaxResults = boards.MaxResults | ||
output.IsLast = boards.IsLast | ||
output.Total = boards.Total | ||
return base.ConvertToStructpb(output) | ||
} | ||
|
||
func (jiraClient *Client) listBoards(_ context.Context, opt *ListBoardsInput) (*ListBoardsResp, error) { | ||
apiEndpoint := "rest/agile/1.0/board" | ||
|
||
req := jiraClient.Client.R().SetResult(&ListBoardsResp{}) | ||
err := addQueryOptions(req, *opt) | ||
if err != nil { | ||
return nil, err | ||
} | ||
resp, err := req.Get(apiEndpoint) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
boards := resp.Result().(*ListBoardsResp) | ||
return boards, err | ||
} | ||
|
||
type GetBoardResp struct { | ||
Location struct { | ||
DisplayName string `json:"displayName"` | ||
Name string `json:"name"` | ||
ProjectKey string `json:"projectKey"` | ||
ProjectID int `json:"projectId"` | ||
ProjectName string `json:"projectName"` | ||
ProjectTypeKey string `json:"projectTypeKey"` | ||
UserAccountID string `json:"userAccountId"` | ||
UserID string `json:"userId"` | ||
} `json:"location"` | ||
Board | ||
} | ||
|
||
func (jiraClient *Client) getBoard(_ context.Context, boardID int) (*GetBoardResp, error) { | ||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID) | ||
|
||
req := jiraClient.Client.R().SetResult(&GetBoardResp{}) | ||
resp, err := req.Get(apiEndpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf( | ||
err.Error(), errmsg.Message(err), | ||
) | ||
} | ||
result := resp.Result().(*GetBoardResp) | ||
|
||
return result, err | ||
} |
Oops, something went wrong.