blob: 5b512b77bf348cb35b692d058eff580ed0930046 [file] [view]
---
title: "Jira"
description: >
Jira Plugin
---
## Summary
This plugin collects Jira data through Jira Cloud REST API. It then computes and visualizes various engineering metrics from the Jira data.
<img width="2035" alt="jira metric display" src="https://user-images.githubusercontent.com/2908155/132926143-7a31d37f-22e1-487d-92a3-cf62e402e5a8.png" />
## Project Metrics This Covers
| Metric Name | Description |
|:------------------------------------|:--------------------------------------------------------------------------------------------------|
| Requirement Count | Number of issues with type "Requirement" |
| Requirement Lead Time | Lead time of issues with type "Requirement" |
| Requirement Delivery Rate | Ratio of delivered requirements to all requirements |
| Requirement Granularity | Number of story points associated with an issue |
| Bug Count | Number of issues with type "Bug"<br/><i>bugs are found during testing</i> |
| Bug Age | Lead time of issues with type "Bug"<br/><i>both new and deleted lines count</i> |
| Bugs Count per 1k Lines of Code | Amount of bugs per 1000 lines of code |
| Incident Count | Number of issues with type "Incident"<br/><i>incidents are found when running in production</i> |
| Incident Age | Lead time of issues with type "Incident" |
| Incident Count per 1k Lines of Code | Amount of incidents per 1000 lines of code |
## Configuration
Configuring Jira via [config-ui](/UserManuals/ConfigUI/Jira.md).
## Collect Data From JIRA
To collect data, select `Advanced Mode` on the `Create Pipeline Run` page and paste a JSON config like the following:
> <font color="#ED6A45">Warning: Data collection only supports single-task execution, and the results of concurrent multi-task execution may not meet expectations.</font>
```
[
[
{
"plugin": "jira",
"options": {
"connectionId": 1,
"boardId": 8,
"since": "2006-01-02T15:04:05Z"
}
}
]
]
```
- `connectionId`: The `ID` field from **JIRA Integration** page.
- `boardId`: JIRA board id, see "Find Board Id" for details.
- `since`: optional, download data since a specified date only.
## API
### Data Connections
1. Get all data connection
```GET /plugins/jira/connections
[
{
"ID": 14,
"CreatedAt": "2021-10-11T11:49:19.029Z",
"UpdatedAt": "2021-10-11T11:49:19.029Z",
"name": "test-jira-connection",
"endpoint": "https://merico.atlassian.net/rest",
"basicAuthEncoded": "basicAuth",
"epicKeyField": "epicKeyField",
"storyPointField": "storyPointField"
}
]
```
2. Create a new data connection
```POST /plugins/jira/connections
{
"name": "jira data connection name",
"endpoint": "jira api endpoint, i.e. https://merico.atlassian.net/rest",
"basicAuthEncoded": "generated by `echo -n {jira login email}:{jira token} | base64`",
"epicKeyField": "name of customfield of epic key",
"storyPointField": "name of customfield of story point",
"typeMappings": { // optional, send empty object to delete all typeMappings of the data connection
"userType": {
"standardType": "devlake standard type"
}
}
}
```
3. Update data connection
```PUT /plugins/jira/connections/:connectionId
{
"name": "jira data connection name",
"endpoint": "jira api endpoint, i.e. https://merico.atlassian.net/rest",
"basicAuthEncoded": "generated by `echo -n {jira login email}:{jira token} | base64`",
"epicKeyField": "name of customfield of epic key",
"storyPointField": "name of customfield of story point",
"typeMappings": { // optional, send empty object to delete all typeMappings of the data connection
"userType": {
"standardType": "devlake standard type",
}
}
}
```
4. Get data connection detail
```GET /plugins/jira/connections/:connectionId
{
"name": "jira data connection name",
"endpoint": "jira api endpoint, i.e. https://merico.atlassian.net/rest",
"basicAuthEncoded": "generated by `echo -n {jira login email}:{jira token} | base64`",
"epicKeyField": "name of customfield of epic key",
"storyPointField": "name of customfield of story point",
"typeMappings": { // optional, send empty object to delete all typeMappings of the data connection
"userType": {
"standardType": "devlake standard type",
}
}
}
```
5. Delete data connection
```DELETE /plugins/jira/connections/:connectionId
```
### Type mappings setting
1. mappings struct
```json /blueprints/{blueprintId}
{
"settings": {
"connections":
[{
"scope":
[{
"transformation":
{
"epicKeyField": "",
"storyPointField": "",
"remotelinkCommitShaPattern": "",
"typeMappings":
{
"<USER_TYPE_1>":
{
"standardType": "<STD_TYPE_1>",
"statusMappings":
{
"<USER_STATUS_a_from_USER_TYPE_1>": { "standardStatus": "<STD_STATUS_1>" },
"<USER_STATUS_a_from_USER_TYPE_2>": { "standardStatus": "<STD_STATUS_2>" }
}
}
}
}
}]
}]
}
}
```
2. set mappings example:
```json PATCH /blueprints/{blueprintId}
{
"name": "jira-test",
"mode": "NORMAL",
"plan":
[
[
{
"plugin": "jira",
"subtasks":
[
"collectStatus",
"extractStatus",
"collectProjects",
"extractProjects",
"collectBoard",
"extractBoard",
"collectIssueTypes",
"extractIssueType",
"collectIssues",
"extractIssues",
"collectIssueChangelogs",
"extractIssueChangelogs",
"collectAccounts",
"collectWorklogs",
"extractWorklogs",
"collectRemotelinks",
"extractRemotelinks",
"collectSprints",
"extractSprints",
"convertBoard",
"convertIssues",
"convertWorklogs",
"convertIssueChangelogs",
"convertSprints",
"convertSprintIssues",
"convertIssueCommits",
"extractAccounts",
"convertAccounts",
"collectEpics",
"extractEpics"
]
}
]
],
"enable": true,
"cronConfig": "0 0 * * *",
"isManual": true,
"settings": {
"connections":
[{
"connectionId": 1,
"plugin": "jira",
"scope":
[{
"entities":
[
"TICKET",
"CROSS"
],
"options": { "boardId": 1 },
"transformation":
{
"epicKeyField": "",
"storyPointField": "",
"remotelinkCommitShaPattern": "",
"typeMappings":
{
"Task1":
{
"standardType": "Task1",
"statusMappings":
{
"done": { "standardStatus": "hello world" },
"new": { "standardStatus": "nice to meet you" }
}
},
"Task2":
{
"standardType": "Task2",
"statusMappings":
{
"done": { "standardStatus": "hello world" },
"new": { "standardStatus": "nice to meet you too" }
}
}
}
}
}]
}],
"version": "1.0.0"
},
"id": 1,
"createdAt": "2022-08-30T11:25:10.699Z",
"updatedAt": "2022-08-30T11:28:22.891Z"
}
```
3. API forwarding
For example:
Requests to `http://your_devlake_host/plugins/jira/connections/1/proxy/rest/agile/1.0/board/8/sprint`
would be forwarded to `https://your_jira_host/rest/agile/1.0/board/8/sprint`
```GET /plugins/jira/connections/:connectionId/proxy/rest/*path
{
"maxResults": 1,
"startAt": 0,
"isLast": false,
"values": [
{
"id": 7,
"self": "https://merico.atlassian.net/rest/agile/1.0/sprint/7",
"state": "closed",
"name": "EE Sprint 7",
"startDate": "2020-06-12T00:38:51.882Z",
"endDate": "2020-06-26T00:38:00.000Z",
"completeDate": "2020-06-22T05:59:58.980Z",
"originBoardId": 8,
"goal": ""
}
]
}
```