Skip to content

Commit 982a053

Browse files
authored
chore: add error details in create-jira action (#13)
* chore: add error details in create-jira action * fix * fix
1 parent ed1a63f commit 982a053

File tree

4 files changed

+191
-100
lines changed

4 files changed

+191
-100
lines changed

create-jira/__tests__/index.test.ts

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('Create Jira Issue Action', () => {
1010
jest.clearAllMocks();
1111
});
1212

13-
it('should create a Jira issue successfully', () => {
13+
it('should create a Jira issue successfully', async () => {
1414
const setOutputMock = jest.spyOn(core, 'setOutput');
1515
const setFailedMock = jest.spyOn(core, 'setFailed');
1616
const getInputMock = jest.spyOn(core, 'getInput');
@@ -56,7 +56,7 @@ describe('Create Jira Issue Action', () => {
5656
callback(null, responseMock, responseMock.body);
5757
});
5858

59-
main();
59+
await main();
6060

6161
expect(requestBody).toEqual({
6262
fields: {
@@ -70,11 +70,11 @@ describe('Create Jira Issue Action', () => {
7070
},
7171
customfield_10011: 'custom-value'
7272
} as JiraIssue)
73-
expect(setOutputMock).toHaveBeenCalledWith('issue-key', 'TEST-123');
7473
expect(setFailedMock).not.toHaveBeenCalled();
74+
expect(setOutputMock).toHaveBeenCalledWith('issue-key', 'TEST-123');
7575
});
7676

77-
it('should fail if request returns an error', () => {
77+
it('should fail if request returns an error', async () => {
7878
const setFailedMock = jest.spyOn(core, 'setFailed');
7979
const getInputMock = jest.spyOn(core, 'getInput');
8080

@@ -111,12 +111,12 @@ describe('Create Jira Issue Action', () => {
111111
callback(err, null, null);
112112
});
113113

114-
main();
114+
await main();
115115

116116
expect(setFailedMock).toHaveBeenCalledWith(err);
117117
});
118118

119-
it('should fail if response status code is >= 400', () => {
119+
it('should fail if response status code is >= 400', async () => {
120120
const setFailedMock = jest.spyOn(core, 'setFailed');
121121
const getInputMock = jest.spyOn(core, 'getInput');
122122

@@ -152,14 +152,55 @@ describe('Create Jira Issue Action', () => {
152152
statusMessage: 'Bad Request',
153153
};
154154

155-
const responseBody = {};
155+
const responseBody = {
156+
detail: "Bad Request"
157+
};
156158

157159
(request as unknown as jest.Mock).mockImplementation((options, callback) => {
158160
callback(null, responseMock, responseBody);
159161
});
160162

161-
main();
163+
await main();
164+
165+
const err = new Error("400 Bad Request\n{\"detail\":\"Bad Request\"}");
166+
167+
expect(setFailedMock).toHaveBeenCalledWith(err);
168+
});
169+
it('should fail if json is invalid', async () => {
170+
const setFailedMock = jest.spyOn(core, 'setFailed');
171+
const getInputMock = jest.spyOn(core, 'getInput');
172+
173+
getInputMock.mockImplementation((name: string) => {
174+
switch (name) {
175+
case 'token':
176+
return 'fake-token';
177+
case 'project-key':
178+
return 'TEST';
179+
case 'summary':
180+
return 'Test issue';
181+
case 'description':
182+
return 'Test description';
183+
case 'issuetype':
184+
return 'Task';
185+
case 'labels':
186+
return 'bug,urgent';
187+
case 'components':
188+
return 'backend,frontend';
189+
case 'assignee':
190+
return 'test-user';
191+
case 'extra-data':
192+
return '{invalid-json';
193+
case 'api-base':
194+
return 'https://jira.example.com';
195+
default:
196+
return '';
197+
}
198+
});
199+
200+
await main();
162201

163-
expect(setFailedMock).toHaveBeenCalledWith("400 Bad Request");
202+
const err = new Error("Error parsing extra-data: SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)");
203+
204+
expect(setFailedMock).toHaveBeenCalledWith(err);
164205
});
165206
});

create-jira/dist/index.js

Lines changed: 67 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -88261,46 +88261,35 @@ var lodashExports = lodash.exports;
8826188261
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8826288262
// See the License for the specific language governing permissions and
8826388263
// limitations under the License.
88264-
function main() {
88265-
try {
88266-
const token = coreExports.getInput('token');
88267-
const projectKey = coreExports.getInput('project-key');
88268-
const summary = coreExports.getInput('summary');
88269-
const description = coreExports.getInput('description');
88270-
const issuetype = coreExports.getInput('issuetype');
88271-
const labels = coreExports.getInput('labels');
88272-
const components = coreExports.getInput('components');
88273-
const assignee = coreExports.getInput('assignee');
88274-
const extraData = coreExports.getInput('extra-data');
88275-
const apiBase = coreExports.getInput('api-base');
88276-
const labelList = labels.split(",").filter(value => value != "");
88277-
const componentList = components.split(",").filter(value => value != "");
88278-
let body = { fields: { project: { key: projectKey }, summary: summary } };
88279-
if (description != "") {
88280-
body.fields.description = description;
88281-
}
88282-
if (issuetype != "") {
88283-
body.fields.issuetype = { name: issuetype };
88284-
}
88285-
if (assignee != "") {
88286-
body.fields.assignee = { name: assignee };
88287-
}
88288-
if (labelList.length != 0) {
88289-
body.fields.labels = labelList;
88290-
}
88291-
if (componentList.length != 0) {
88292-
body.fields.components = componentList.map(value => {
88293-
return { name: value };
88294-
});
88295-
}
88296-
if (extraData != "") {
88297-
const extraDataObject = JSON.parse(extraData);
88298-
lodashExports.mergeWith(body, extraDataObject, (dst, src) => {
88299-
if (lodashExports.isArray(dst)) {
88300-
return dst.concat(src);
88301-
}
88302-
});
88264+
function buildRequestBody(projectKey, summary, description, issuetype, labels, components, assignee, extraData) {
88265+
const body = { fields: { project: { key: projectKey }, summary: summary } };
88266+
if (description != "") {
88267+
body.fields.description = description;
88268+
}
88269+
if (issuetype != "") {
88270+
body.fields.issuetype = { name: issuetype };
88271+
}
88272+
if (assignee != "") {
88273+
body.fields.assignee = { name: assignee };
88274+
}
88275+
if (labels.length != 0) {
88276+
body.fields.labels = labels;
88277+
}
88278+
if (components.length != 0) {
88279+
body.fields.components = components.map(value => {
88280+
return { name: value };
88281+
});
88282+
}
88283+
lodashExports.mergeWith(body, extraData, (dst, src) => {
88284+
if (lodashExports.isArray(dst)) {
88285+
return dst.concat(src);
8830388286
}
88287+
});
88288+
return body;
88289+
}
88290+
async function createJiraIssue(token, apiBase, projectKey, summary, description, issuetype, labels, components, assignee, extraData) {
88291+
const body = buildRequestBody(projectKey, summary, description, issuetype, labels, components, assignee, extraData);
88292+
return await new Promise((resolve, reject) => {
8830488293
request$1({
8830588294
url: `${apiBase}/rest/api/2/issue`,
8830688295
method: "POST",
@@ -88312,20 +88301,54 @@ function main() {
8831288301
json: true
8831388302
}, (err, response, responseBody) => {
8831488303
if (err != null) {
88315-
return coreExports.setFailed(err);
88304+
reject(err);
88305+
return;
8831688306
}
8831788307
if (response.statusCode >= 400) {
88318-
return coreExports.setFailed(response.statusCode + " " + response.statusMessage);
88308+
reject(new Error(response.statusCode + " " + response.statusMessage + "\n" + JSON.stringify(responseBody)));
88309+
return;
8831988310
}
88320-
coreExports.setOutput("issue-key", responseBody.key);
88311+
resolve({
88312+
response, responseBody
88313+
});
8832188314
});
88315+
});
88316+
}
88317+
async function main() {
88318+
try {
88319+
const token = coreExports.getInput('token');
88320+
const projectKey = coreExports.getInput('project-key');
88321+
const summary = coreExports.getInput('summary');
88322+
const description = coreExports.getInput('description');
88323+
const issuetype = coreExports.getInput('issuetype');
88324+
const labels = coreExports.getInput('labels');
88325+
const components = coreExports.getInput('components');
88326+
const assignee = coreExports.getInput('assignee');
88327+
const extraData = coreExports.getInput('extra-data');
88328+
const apiBase = coreExports.getInput('api-base');
88329+
const labelList = labels.split(",").filter(value => value != "");
88330+
const componentList = components.split(",").filter(value => value != "");
88331+
let extraDataObject = undefined;
88332+
if (extraData != "") {
88333+
try {
88334+
extraDataObject = JSON.parse(extraData);
88335+
}
88336+
catch (error) {
88337+
throw new Error("Error parsing extra-data: " + error);
88338+
}
88339+
}
88340+
const { responseBody } = await createJiraIssue(token, apiBase, projectKey, summary, description, issuetype, labelList, componentList, assignee, extraDataObject);
88341+
if (!responseBody.key) {
88342+
throw new Error("No issue key found in response: " + JSON.stringify(responseBody));
88343+
}
88344+
coreExports.setOutput("issue-key", responseBody.key);
8832288345
}
8832388346
catch (error) {
8832488347
if (error instanceof Error) {
88325-
coreExports.setFailed(error.message);
88348+
coreExports.setFailed(error);
8832688349
}
8832788350
else {
88328-
coreExports.setFailed(String(error));
88351+
coreExports.setFailed(JSON.stringify(error));
8832988352
}
8833088353
}
8833188354
}

create-jira/dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

create-jira/src/index.ts

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -29,48 +29,37 @@ export interface JiraIssue {
2929
};
3030
}
3131

32-
export function main() {
33-
try {
34-
const token = core.getInput('token');
35-
const projectKey = core.getInput('project-key');
36-
const summary = core.getInput('summary');
37-
const description = core.getInput('description');
38-
const issuetype = core.getInput('issuetype');
39-
const labels = core.getInput('labels');
40-
const components = core.getInput('components');
41-
const assignee = core.getInput('assignee');
42-
const extraData = core.getInput('extra-data');
43-
const apiBase = core.getInput('api-base');
44-
const labelList = labels.split(",").filter(value => value != "");
45-
const componentList = components.split(",").filter(value => value != "");
46-
47-
let body: JiraIssue = { fields: { project: { key: projectKey }, summary: summary } };
48-
if (description != "") {
49-
body.fields.description = description;
50-
}
51-
if (issuetype != "") {
52-
body.fields.issuetype = { name: issuetype };
53-
}
54-
if (assignee != "") {
55-
body.fields.assignee = { name: assignee };
56-
}
57-
if (labelList.length != 0) {
58-
body.fields.labels = labelList;
59-
}
60-
if (componentList.length != 0) {
61-
body.fields.components = componentList.map(value => {
62-
return { name: value };
63-
});
64-
}
65-
if (extraData != "") {
66-
const extraDataObject = JSON.parse(extraData);
67-
mergeWith(body, extraDataObject, (dst, src) => {
68-
if (isArray(dst)) {
69-
return dst.concat(src);
70-
}
71-
});
32+
function buildRequestBody(projectKey: string, summary: string, description: string, issuetype: string, labels: string[], components: string[], assignee: string, extraData?: { [key: string]: any }): JiraIssue {
33+
const body: JiraIssue = { fields: { project: { key: projectKey }, summary: summary } };
34+
if (description != "") {
35+
body.fields.description = description;
36+
}
37+
if (issuetype != "") {
38+
body.fields.issuetype = { name: issuetype };
39+
}
40+
if (assignee != "") {
41+
body.fields.assignee = { name: assignee };
42+
}
43+
if (labels.length != 0) {
44+
body.fields.labels = labels;
45+
}
46+
if (components.length != 0) {
47+
body.fields.components = components.map(value => {
48+
return { name: value };
49+
});
50+
}
51+
mergeWith(body, extraData, (dst, src) => {
52+
if (isArray(dst)) {
53+
return dst.concat(src);
7254
}
55+
});
56+
return body;
57+
}
7358

59+
async function createJiraIssue(token: string, apiBase: string, projectKey: string, summary: string, description: string, issuetype: string, labels: string[], components: string[], assignee: string, extraData?: { [key: string]: any }): Promise<{ response: request.Response, responseBody: any }> {
60+
const body = buildRequestBody(projectKey, summary, description, issuetype, labels, components, assignee, extraData);
61+
62+
return await new Promise((resolve, reject) => {
7463
request({
7564
url: `${apiBase}/rest/api/2/issue`,
7665
method: "POST",
@@ -82,20 +71,58 @@ export function main() {
8271
json: true
8372
}, (err: any, response: request.Response, responseBody: any) => {
8473
if (err != null) {
85-
return core.setFailed(err);
74+
reject(err);
75+
return;
8676
}
8777
if (response.statusCode >= 400) {
88-
return core.setFailed(response.statusCode + " " + response.statusMessage);
78+
reject(new Error(response.statusCode + " " + response.statusMessage + "\n" + JSON.stringify(responseBody)));
79+
return;
8980
}
90-
core.setOutput("issue-key", responseBody.key);
81+
resolve({
82+
response, responseBody
83+
});
9184
});
85+
});
86+
}
87+
88+
export async function main() {
89+
try {
90+
const token = core.getInput('token');
91+
const projectKey = core.getInput('project-key');
92+
const summary = core.getInput('summary');
93+
const description = core.getInput('description');
94+
const issuetype = core.getInput('issuetype');
95+
const labels = core.getInput('labels');
96+
const components = core.getInput('components');
97+
const assignee = core.getInput('assignee');
98+
const extraData = core.getInput('extra-data');
99+
const apiBase = core.getInput('api-base');
100+
const labelList = labels.split(",").filter(value => value != "");
101+
const componentList = components.split(",").filter(value => value != "");
102+
103+
let extraDataObject: { [key: string]: any } | undefined = undefined;
104+
if (extraData != "") {
105+
try {
106+
extraDataObject = JSON.parse(extraData);
107+
} catch (error) {
108+
throw new Error("Error parsing extra-data: " + error);
109+
}
110+
}
111+
112+
const { responseBody } = await createJiraIssue(token, apiBase, projectKey, summary, description, issuetype, labelList, componentList, assignee, extraDataObject);
113+
114+
if (!responseBody.key) {
115+
throw new Error("No issue key found in response: " + JSON.stringify(responseBody));
116+
}
117+
118+
core.setOutput("issue-key", responseBody.key);
92119
} catch (error) {
93120
if (error instanceof Error) {
94-
core.setFailed(error.message);
121+
core.setFailed(error);
95122
} else {
96-
core.setFailed(String(error));
123+
core.setFailed(JSON.stringify(error));
97124
}
98125
}
99126
}
100127

101-
main();
128+
main();

0 commit comments

Comments
 (0)