Skip to content

Commit 3d958b8

Browse files
authored
[7.x] [Actions][Jira] Set parent issue for Sub-task issue type (#78772) (#79059)
1 parent dc658d6 commit 3d958b8

File tree

19 files changed

+733
-24
lines changed

19 files changed

+733
-24
lines changed

docs/user/alerting/action-types/jira.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ Priority:: The priority of the incident.
6969
Labels:: The labels of the incident.
7070
Title:: A title for the issue, used for searching the contents of the knowledge base.
7171
Description:: The details about the incident.
72+
Parent:: The parent issue id or key. Only for `Sub-task` issue types.
73+
Priority:: The priority of the incident.
7274
Additional comments:: Additional information for the client, such as how to troubleshoot the issue.
7375

7476
[[configuring-jira]]

x-pack/plugins/actions/README.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,12 @@ Running the action by scheduling a task means that we will no longer have a user
274274

275275
The following table describes the properties of the `options` object.
276276

277-
| Property | Description | Type |
278-
| -------- | ------------------------------------------------------------------------------------------------------ | ------ |
279-
| id | The id of the action you want to execute. | string |
280-
| params | The `params` value to give the action type executor. | object |
281-
| spaceId | The space id the action is within. | string |
282-
| apiKey | The Elasticsearch API key to use for context. (Note: only required and used when security is enabled). | string |
277+
| Property | Description | Type |
278+
| -------- | ------------------------------------------------------------------------------------------------------ | ---------------- |
279+
| id | The id of the action you want to execute. | string |
280+
| params | The `params` value to give the action type executor. | object |
281+
| spaceId | The space id the action is within. | string |
282+
| apiKey | The Elasticsearch API key to use for context. (Note: only required and used when security is enabled). | string |
283283
| source | The source of the execution, either an HTTP request or a reference to a Saved Object. | object, optional |
284284

285285
## Example
@@ -308,11 +308,11 @@ This api runs the action and asynchronously returns the result of running the ac
308308

309309
The following table describes the properties of the `options` object.
310310

311-
| Property | Description | Type |
312-
| -------- | ------------------------------------------------------------------------------------ | ------ |
313-
| id | The id of the action you want to execute. | string |
314-
| params | The `params` value to give the action type executor. | object |
315-
| source | The source of the execution, either an HTTP request or a reference to a Saved Object.| object, optional |
311+
| Property | Description | Type |
312+
| -------- | ------------------------------------------------------------------------------------- | ---------------- |
313+
| id | The id of the action you want to execute. | string |
314+
| params | The `params` value to give the action type executor. | object |
315+
| source | The source of the execution, either an HTTP request or a reference to a Saved Object. | object, optional |
316316

317317
## Example
318318

@@ -330,7 +330,7 @@ const result = await actionsClient.execute({
330330
},
331331
source: asSavedObjectExecutionSource({
332332
id: '573891ae-8c48-49cb-a197-0cd5ec34a88b',
333-
type: 'alert'
333+
type: 'alert',
334334
}),
335335
});
336336
```
@@ -620,6 +620,7 @@ The Jira action uses the [V2 API](https://developer.atlassian.com/cloud/jira/pla
620620
| issueType | The id of the issue type in Jira. | string _(optional)_ |
621621
| priority | The name of the priority in Jira. Example: `Medium`. | string _(optional)_ |
622622
| labels | An array of labels. | string[] _(optional)_ |
623+
| parent | The parent issue id or key. Only for `Sub-task` issue types. | string _(optional)_ |
623624
| comments | The comments of the case. A comment is of the form `{ commentId: string, version: string, comment: string }` | object[] _(optional)_ |
624625

625626
#### `subActionParams (issueTypes)`

x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ describe('api', () => {
9393
issueType: '10006',
9494
labels: ['kibana', 'elastic'],
9595
priority: 'High',
96+
parent: null,
9697
},
9798
});
9899
expect(externalService.updateIncident).not.toHaveBeenCalled();
@@ -252,6 +253,7 @@ describe('api', () => {
252253
issueType: '10006',
253254
labels: ['kibana', 'elastic'],
254255
priority: 'High',
256+
parent: null,
255257
},
256258
});
257259
expect(externalService.createIncident).not.toHaveBeenCalled();
@@ -380,6 +382,36 @@ describe('api', () => {
380382
});
381383
});
382384

385+
describe('getIssues', () => {
386+
test('it returns the issues correctly', async () => {
387+
const res = await api.issues({
388+
externalService,
389+
params: { title: 'Title test' },
390+
});
391+
expect(res).toEqual([
392+
{
393+
id: '10267',
394+
key: 'RJ-107',
395+
title: 'Test title',
396+
},
397+
]);
398+
});
399+
});
400+
401+
describe('getIssue', () => {
402+
test('it returns the issue correctly', async () => {
403+
const res = await api.issue({
404+
externalService,
405+
params: { id: 'RJ-107' },
406+
});
407+
expect(res).toEqual({
408+
id: '10267',
409+
key: 'RJ-107',
410+
title: 'Test title',
411+
});
412+
});
413+
});
414+
383415
describe('mapping variations', () => {
384416
test('overwrite & append', async () => {
385417
mapping.set('title', {

x-pack/plugins/actions/server/builtin_action_types/jira/api.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import {
1313
Incident,
1414
GetFieldsByIssueTypeHandlerArgs,
1515
GetIssueTypesHandlerArgs,
16+
GetIssuesHandlerArgs,
1617
PushToServiceApiParams,
1718
PushToServiceResponse,
19+
GetIssueHandlerArgs,
1820
} from './types';
1921

2022
// TODO: to remove, need to support Case
@@ -46,6 +48,18 @@ const getFieldsByIssueTypeHandler = async ({
4648
return res;
4749
};
4850

51+
const getIssuesHandler = async ({ externalService, params }: GetIssuesHandlerArgs) => {
52+
const { title } = params;
53+
const res = await externalService.getIssues(title);
54+
return res;
55+
};
56+
57+
const getIssueHandler = async ({ externalService, params }: GetIssueHandlerArgs) => {
58+
const { id } = params;
59+
const res = await externalService.getIssue(id);
60+
return res;
61+
};
62+
4963
const pushToServiceHandler = async ({
5064
externalService,
5165
mapping,
@@ -83,8 +97,8 @@ const pushToServiceHandler = async ({
8397
currentIncident,
8498
});
8599
} else {
86-
const { title, description, priority, labels, issueType } = params;
87-
incident = { summary: title, description, priority, labels, issueType };
100+
const { title, description, priority, labels, issueType, parent } = params;
101+
incident = { summary: title, description, priority, labels, issueType, parent };
88102
}
89103

90104
if (externalId != null) {
@@ -134,4 +148,6 @@ export const api: ExternalServiceApi = {
134148
getIncident: getIncidentHandler,
135149
issueTypes: getIssueTypesHandler,
136150
fieldsByIssueType: getFieldsByIssueTypeHandler,
151+
issues: getIssuesHandler,
152+
issue: getIssueHandler,
137153
};

x-pack/plugins/actions/server/builtin_action_types/jira/index.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
JiraExecutorResultData,
2626
ExecutorSubActionGetFieldsByIssueTypeParams,
2727
ExecutorSubActionGetIssueTypesParams,
28+
ExecutorSubActionGetIssuesParams,
29+
ExecutorSubActionGetIssueParams,
2830
} from './types';
2931
import * as i18n from './translations';
3032
import { Logger } from '../../../../../../src/core/server';
@@ -37,7 +39,13 @@ interface GetActionTypeParams {
3739
configurationUtilities: ActionsConfigurationUtilities;
3840
}
3941

40-
const supportedSubActions: string[] = ['pushToService', 'issueTypes', 'fieldsByIssueType'];
42+
const supportedSubActions: string[] = [
43+
'pushToService',
44+
'issueTypes',
45+
'fieldsByIssueType',
46+
'issues',
47+
'issue',
48+
];
4149

4250
// action type definition
4351
export function getActionType(
@@ -137,5 +145,21 @@ async function executor(
137145
});
138146
}
139147

148+
if (subAction === 'issues') {
149+
const getIssuesParams = subActionParams as ExecutorSubActionGetIssuesParams;
150+
data = await api.issues({
151+
externalService,
152+
params: getIssuesParams,
153+
});
154+
}
155+
156+
if (subAction === 'issue') {
157+
const getIssueParams = subActionParams as ExecutorSubActionGetIssueParams;
158+
data = await api.issue({
159+
externalService,
160+
params: getIssueParams,
161+
});
162+
}
163+
140164
return { status: 'ok', data: data ?? {}, actionId };
141165
}

x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ const createMock = (): jest.Mocked<ExternalService> => {
6161
defaultValue: { name: 'Medium', id: '3' },
6262
},
6363
})),
64+
getIssues: jest.fn().mockImplementation(() => [
65+
{
66+
id: '10267',
67+
key: 'RJ-107',
68+
title: 'Test title',
69+
},
70+
]),
71+
getIssue: jest.fn().mockImplementation(() => ({
72+
id: '10267',
73+
key: 'RJ-107',
74+
title: 'Test title',
75+
})),
6476
};
6577

6678
service.createComment.mockImplementationOnce(() =>
@@ -120,6 +132,7 @@ const executorParams: ExecutorSubActionPushParams = {
120132
labels: ['kibana', 'elastic'],
121133
priority: 'High',
122134
issueType: '10006',
135+
parent: null,
123136
comments: [
124137
{
125138
commentId: 'case-comment-1',

x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const ExecutorSubActionPushParamsSchema = schema.object({
4444
issueType: schema.nullable(schema.string()),
4545
priority: schema.nullable(schema.string()),
4646
labels: schema.nullable(schema.arrayOf(schema.string())),
47+
parent: schema.nullable(schema.string()),
4748
// TODO: modify later to string[] - need for support Case schema
4849
comments: schema.nullable(schema.arrayOf(CommentSchema)),
4950
...EntityInformation,
@@ -60,6 +61,8 @@ export const ExecutorSubActionGetIssueTypesParamsSchema = schema.object({});
6061
export const ExecutorSubActionGetFieldsByIssueTypeParamsSchema = schema.object({
6162
id: schema.string(),
6263
});
64+
export const ExecutorSubActionGetIssuesParamsSchema = schema.object({ title: schema.string() });
65+
export const ExecutorSubActionGetIssueParamsSchema = schema.object({ id: schema.string() });
6366

6467
export const ExecutorParamsSchema = schema.oneOf([
6568
schema.object({
@@ -82,4 +85,12 @@ export const ExecutorParamsSchema = schema.oneOf([
8285
subAction: schema.literal('fieldsByIssueType'),
8386
subActionParams: ExecutorSubActionGetFieldsByIssueTypeParamsSchema,
8487
}),
88+
schema.object({
89+
subAction: schema.literal('issues'),
90+
subActionParams: ExecutorSubActionGetIssuesParamsSchema,
91+
}),
92+
schema.object({
93+
subAction: schema.literal('issue'),
94+
subActionParams: ExecutorSubActionGetIssueParamsSchema,
95+
}),
8596
]);

0 commit comments

Comments
 (0)