mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 00:24:07 -08:00
0da398b0e4
* ✨ change FE to handle new object type * 🚸 improve UX of handling invalid credentials * 🚧 WIP * 🎨 fix typescript issues * 🐘 add migrations for all supported dbs * ✏️ add description to migrations * ⚡ add credential update on import * ⚡ resolve after merge issues * 👕 fix lint issues * ⚡ check credentials on workflow create/update * update interface * 👕 fix ts issues * ⚡ adaption to new credentials UI * 🐛 intialize cache on BE for credentials check * 🐛 fix undefined oldCredentials * 🐛 fix deleting credential * 🐛 fix check for undefined keys * 🐛 fix disabling edit in execution * 🎨 just show credential name on execution view * ✏️ remove TODO * ⚡ implement review suggestions * ⚡ add cache to getCredentialsByType * ⏪ use getter instead of cache * ✏️ fix variable name typo * 🐘 include waiting nodes to migrations * 🐛 fix reverting migrations command * ⚡ update typeorm command * ✨ create db:revert command * 👕 fix lint error * ✨ Add optional authenticate method to credentials * ⚡ Simplify code and add authentication support to MattermostApi * 👕 Fix lint issue * ⚡ Add support to own-mode * 👕 Fix lint issue * ✨ Add support for predefined auth types bearer and headerAuth * ⚡ Make sure that DateTime Node always returns strings * ⚡ Add support for moment types to If Node * ⚡ Make it possible for HTTP Request Node to use all credential types * ✨ Add basicAuth support * Add a new dropcontact node * ✨ First basic implementation of mainly JSON based nodes * ✨ Add fixedCollection support, added value parameter and expression support for value and property * Improvements to #2389 * ⚡ Add credentials verification * ⚡ Small improvement * ⚡ set default time to 45 seconds * ✨ Add support for preSend and postReceive methods * ➕ Add lodash merge and set depedency to workflow * 👕 Fix lint issue * ⚡ Improvements * ⚡ Improvements * ⚡ Improvements * ⚡ Improvements * ⚡ Improvements * 🐛 Set siren and language correctly * ⚡ Add support for requestDefaults * ⚡ Add support for baseURL to httpRequest * ⚡ Move baseURL to correct location * ✨ Add support for options loading * 🐛 Fix error with fullAccess nodes * ✨ Add credential test functionality * 🐛 Fix issue with OAuth autentication and lint issue * ⚡ Fix build issue * 🐛 Fix issue that url got always overwritten to empty * ✨ Add pagination support * ⚡ Code fix required after merge * ⚡ Remove not needed imports * ⚡ Fix credential test * ✨ Add expression support for request properties and $self support on properties * ⚡ Rename $self to $value * 👕 Fix lint issue * ⚡ Add example how to send data in path * ✨ Make it possible to not sent in dot notation * ✨ Add support for postReceive:rootProperty * ⚡ Fix typo * ✨ Add support for postReceive:set * ⚡ Some fixes * ⚡ Small improvement * ;zap: Separate RoutingNode code * ⚡ Simplify code and fix bug * ⚡ Remove unused code * ✨ Make it possible to define "request" and "requestProperty" on options * 👕 Fix lint issue * ⚡ Change $credentials variables name * ✨ Enable expressions and access to credentials in requestDefaults * ⚡ Make parameter option loading use RoutingNode.makeRoutingRequest * ✨ Allow requestOperations overwrite on LoadOptions * ✨ Make it possible to access current node parameters in loadOptions * ⚡ Rename parameters variable to make future proof * ⚡ Make it possible to use offset-pagination with body * ✨ Add support for queryAuth * ⚡ Never return more items than requested * ✨ Make it possible to overwrite requestOperations on parameter and option level * 👕 Fix lint issue * ✨ Allow simplified auth also with regular nodes * ✨ Add support for receiving binary data * 🐛 Fix example node * ⚡ Rename property "name" to "displayName" in loadOptions * ⚡ Send data by default as "query" if nothing is set * ⚡ Rename $self to $parent * ⚡ Change to work with INodeExecutionData instead of IDataObject * ⚡ Improve binaryData handling * ⚡ Property design improvements * ⚡ Fix property name * 🚨 Add some tests * ⚡ Add also test for request * ⚡ Improve test and fix issues * ⚡ Improvements to loadOptions * ⚡ Normalize loadOptions with rest of code * ⚡ Add info text * ✨ Add support for $value in postReceive * 🚨 Add tests for RoutingNode.runNode * ⚡ Remove TODOs and make url property optional * ⚡ Fix bug and lint issue * 🐛 Fix bug that not the correct property got used * 🚨 Add tests for CredentialsHelper.authenticate * ⚡ Improve code and resolve expressions also everywhere for loadOptions and credential test requests * ✨ Make it possible to define multiple preSend and postReceive actions * ✨ Allow to define tests on credentials * ⚡ Remove test data * ⬆️ Update package-lock.json file * ⚡ Remove old not longer used code Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com> Co-authored-by: Mutasem <mutdmour@gmail.com> Co-authored-by: PaulineDropcontact <pauline@dropcontact.io> Co-authored-by: ricardo <ricardoespinoza105@gmail.com>
683 lines
16 KiB
TypeScript
683 lines
16 KiB
TypeScript
import {
|
||
IExecuteFunctions,
|
||
} from 'n8n-core';
|
||
|
||
import {
|
||
ICredentialsDecrypted,
|
||
ICredentialTestFunctions,
|
||
IDataObject,
|
||
ILoadOptionsFunctions,
|
||
INodeCredentialTestResult,
|
||
INodeExecutionData,
|
||
INodePropertyOptions,
|
||
INodeType,
|
||
INodeTypeDescription,
|
||
NodeApiError,
|
||
} from 'n8n-workflow';
|
||
|
||
import {
|
||
jenkinsApiRequest,
|
||
tolerateTrailingSlash
|
||
} from './GenericFunctions';
|
||
|
||
export type JenkinsApiCredentials = {
|
||
username: string;
|
||
apiKey: string;
|
||
baseUrl: string;
|
||
};
|
||
|
||
export class Jenkins implements INodeType {
|
||
description: INodeTypeDescription = {
|
||
displayName: 'Jenkins',
|
||
name: 'jenkins',
|
||
icon: 'file:jenkins.svg',
|
||
group: ['output'],
|
||
version: 1,
|
||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||
description: 'Consume Jenkins API',
|
||
defaults: {
|
||
name: 'Jenkins',
|
||
color: '#04AA51',
|
||
},
|
||
inputs: ['main'],
|
||
outputs: ['main'],
|
||
credentials: [
|
||
{
|
||
name: 'jenkinsApi',
|
||
required: true,
|
||
testedBy: 'jenkinApiCredentialTest',
|
||
},
|
||
],
|
||
properties: [
|
||
{
|
||
displayName: 'Resource',
|
||
name: 'resource',
|
||
type: 'options',
|
||
options: [
|
||
{
|
||
name: 'Build',
|
||
value: 'build',
|
||
},
|
||
{
|
||
name: 'Instance',
|
||
value: 'instance',
|
||
},
|
||
{
|
||
name: 'Job',
|
||
value: 'job',
|
||
},
|
||
],
|
||
default: 'job',
|
||
noDataExpression: true,
|
||
},
|
||
|
||
// --------------------------------------------------------------------------------------------------------
|
||
// Job Operations
|
||
// --------------------------------------------------------------------------------------------------------
|
||
{
|
||
displayName: 'Operation',
|
||
name: 'operation',
|
||
type: 'options',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'job',
|
||
],
|
||
},
|
||
},
|
||
options: [
|
||
{
|
||
name: 'Copy',
|
||
value: 'copy',
|
||
description: 'Copy a specific job',
|
||
},
|
||
{
|
||
name: 'Create',
|
||
value: 'create',
|
||
description: 'Create a new job',
|
||
},
|
||
{
|
||
name: 'Trigger',
|
||
value: 'trigger',
|
||
description: 'Trigger a specific job',
|
||
},
|
||
{
|
||
name: 'Trigger with Parameters',
|
||
value: 'triggerParams',
|
||
description: 'Trigger a specific job',
|
||
},
|
||
],
|
||
default: 'trigger',
|
||
description: 'Possible operations',
|
||
noDataExpression: true,
|
||
},
|
||
{
|
||
displayName: 'Make sure the job is setup to support triggering with parameters. <a href="https://wiki.jenkins.io/display/JENKINS/Parameterized+Build" target="_blank">More info</a>',
|
||
name: 'triggerParamsNotice',
|
||
type: 'notice',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'job',
|
||
],
|
||
operation: [
|
||
'triggerParams',
|
||
],
|
||
},
|
||
},
|
||
default: '',
|
||
},
|
||
{
|
||
displayName: 'Job Name',
|
||
name: 'job',
|
||
type: 'options',
|
||
typeOptions: {
|
||
loadOptionsMethod: 'getJobs',
|
||
},
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'job',
|
||
],
|
||
operation: [
|
||
'trigger',
|
||
'triggerParams',
|
||
'copy',
|
||
],
|
||
},
|
||
},
|
||
required: true,
|
||
default: '',
|
||
description: 'Name of the job',
|
||
},
|
||
|
||
// --------------------------------------------------------------------------------------------------------
|
||
// Trigger a Job
|
||
// --------------------------------------------------------------------------------------------------------
|
||
{
|
||
displayName: 'Parameters',
|
||
name: 'param',
|
||
type: 'fixedCollection',
|
||
placeholder: 'Add Parameter',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'job',
|
||
],
|
||
operation: [
|
||
'triggerParams',
|
||
],
|
||
},
|
||
},
|
||
required: true,
|
||
default: '',
|
||
typeOptions: {
|
||
multipleValues: true,
|
||
},
|
||
options: [
|
||
{
|
||
name: 'params',
|
||
displayName: 'Parameters',
|
||
values: [
|
||
{
|
||
displayName: 'Name',
|
||
name: 'name',
|
||
type: 'options',
|
||
typeOptions: {
|
||
loadOptionsMethod: 'getJobParameters',
|
||
loadOptionsDependsOn: [
|
||
'job',
|
||
],
|
||
},
|
||
default: '',
|
||
},
|
||
{
|
||
displayName: 'Value',
|
||
name: 'value',
|
||
type: 'string',
|
||
default: '',
|
||
},
|
||
],
|
||
},
|
||
],
|
||
description: 'Parameters for Jenkins job',
|
||
},
|
||
|
||
// --------------------------------------------------------------------------------------------------------
|
||
// Copy or Create a Job
|
||
// --------------------------------------------------------------------------------------------------------
|
||
{
|
||
displayName: 'New Job Name',
|
||
name: 'newJob',
|
||
type: 'string',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'job',
|
||
],
|
||
operation: [
|
||
'copy',
|
||
'create',
|
||
],
|
||
},
|
||
},
|
||
required: true,
|
||
default: '',
|
||
description: 'Name of the new Jenkins job',
|
||
},
|
||
{
|
||
displayName: 'XML',
|
||
name: 'xml',
|
||
type: 'string',
|
||
typeOptions: {
|
||
alwaysOpenEditWindow: true,
|
||
},
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'job',
|
||
],
|
||
operation: [
|
||
'create',
|
||
],
|
||
},
|
||
},
|
||
required: true,
|
||
default: '',
|
||
description: 'XML of Jenkins config',
|
||
},
|
||
{
|
||
displayName: 'To get the XML of an existing job, add ‘config.xml’ to the end of the job URL',
|
||
name: 'createNotice',
|
||
type: 'notice',
|
||
default: '',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'job',
|
||
],
|
||
operation: [
|
||
'create',
|
||
],
|
||
},
|
||
},
|
||
},
|
||
|
||
// --------------------------------------------------------------------------------------------------------
|
||
// Jenkins operations
|
||
// --------------------------------------------------------------------------------------------------------
|
||
{
|
||
displayName: 'Operation',
|
||
name: 'operation',
|
||
type: 'options',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'instance',
|
||
],
|
||
},
|
||
},
|
||
options: [
|
||
{
|
||
name: 'Cancel Quiet Down',
|
||
value: 'cancelQuietDown',
|
||
description: 'Cancel quiet down state',
|
||
},
|
||
{
|
||
name: 'Quiet Down',
|
||
value: 'quietDown',
|
||
description: 'Put Jenkins in quiet mode, no builds can be started, Jenkins is ready for shutdown',
|
||
},
|
||
{
|
||
name: 'Restart',
|
||
value: 'restart',
|
||
description: 'Restart Jenkins immediately on environments where it is possible',
|
||
},
|
||
{
|
||
name: 'Safely Restart',
|
||
value: 'safeRestart',
|
||
description: 'Restart Jenkins once no jobs are running on environments where it is possible',
|
||
},
|
||
{
|
||
name: 'Safely Shutdown',
|
||
value: 'safeExit',
|
||
description: 'Shutdown once no jobs are running',
|
||
},
|
||
{
|
||
name: 'Shutdown',
|
||
value: 'exit',
|
||
description: 'Shutdown Jenkins immediately',
|
||
},
|
||
],
|
||
default: 'safeRestart',
|
||
description: 'Jenkins instance operations',
|
||
noDataExpression: true,
|
||
},
|
||
{
|
||
displayName: 'Reason',
|
||
name: 'reason',
|
||
type: 'string',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'instance',
|
||
],
|
||
operation: [
|
||
'quietDown',
|
||
],
|
||
},
|
||
},
|
||
required: false,
|
||
default: '',
|
||
description: 'Freeform reason for quiet down mode',
|
||
},
|
||
{
|
||
displayName: 'Instance operation can shutdown Jenkins instance and make it unresponsive. Some commands may not be available depending on instance implementation.',
|
||
name: 'instanceNotice',
|
||
type: 'notice',
|
||
default: '',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'instance',
|
||
],
|
||
},
|
||
},
|
||
},
|
||
|
||
// --------------------------------------------------------------------------------------------------------
|
||
// Builds operations
|
||
// --------------------------------------------------------------------------------------------------------
|
||
{
|
||
displayName: 'Operation',
|
||
name: 'operation',
|
||
type: 'options',
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'build',
|
||
],
|
||
},
|
||
},
|
||
options: [
|
||
{
|
||
name: 'Get All',
|
||
value: 'getAll',
|
||
description: 'List Builds',
|
||
},
|
||
],
|
||
default: 'getAll',
|
||
noDataExpression: true,
|
||
},
|
||
{
|
||
displayName: 'Job Name',
|
||
name: 'job',
|
||
type: 'options',
|
||
typeOptions: {
|
||
loadOptionsMethod: 'getJobs',
|
||
},
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'build',
|
||
],
|
||
operation: [
|
||
'getAll',
|
||
],
|
||
},
|
||
},
|
||
required: true,
|
||
default: '',
|
||
description: 'Name of the job',
|
||
},
|
||
{
|
||
displayName: 'Return All',
|
||
name: 'returnAll',
|
||
type: 'boolean',
|
||
default: false,
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'build',
|
||
],
|
||
operation: [
|
||
'getAll',
|
||
],
|
||
},
|
||
},
|
||
description: 'Whether to return all results or only up to a given limit',
|
||
},
|
||
{
|
||
displayName: 'Limit',
|
||
name: 'limit',
|
||
type: 'number',
|
||
default: 50,
|
||
typeOptions: {
|
||
minValue: 1,
|
||
},
|
||
displayOptions: {
|
||
show: {
|
||
resource: [
|
||
'build',
|
||
],
|
||
operation: [
|
||
'getAll',
|
||
],
|
||
returnAll: [
|
||
false,
|
||
],
|
||
},
|
||
},
|
||
description: 'Max number of results to return',
|
||
},
|
||
],
|
||
};
|
||
|
||
methods = {
|
||
credentialTest: {
|
||
async jenkinApiCredentialTest(
|
||
this: ICredentialTestFunctions,
|
||
credential: ICredentialsDecrypted,
|
||
): Promise<INodeCredentialTestResult> {
|
||
const { baseUrl, username, apiKey } = credential.data as JenkinsApiCredentials;
|
||
|
||
const url = tolerateTrailingSlash(baseUrl);
|
||
const endpoint = '/api/json';
|
||
|
||
const options = {
|
||
auth: {
|
||
username,
|
||
password: apiKey,
|
||
},
|
||
method: 'GET',
|
||
body: {},
|
||
qs: {},
|
||
uri: `${url}${endpoint}`,
|
||
json: true,
|
||
};
|
||
|
||
try {
|
||
await this.helpers.request(options);
|
||
return {
|
||
status: 'OK',
|
||
message: 'Authentication successful',
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
status: 'Error',
|
||
message: error.message,
|
||
};
|
||
}
|
||
},
|
||
},
|
||
loadOptions: {
|
||
async getJobs(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||
const returnData: INodePropertyOptions[] = [];
|
||
const endpoint = `/api/json`;
|
||
const { jobs } = await jenkinsApiRequest.call(this, 'GET', endpoint);
|
||
for (const job of jobs) {
|
||
returnData.push({
|
||
name: job.name,
|
||
value: job.name,
|
||
});
|
||
}
|
||
returnData.sort((a, b) => {
|
||
if (a.name < b.name) { return -1; }
|
||
if (a.name > b.name) { return 1; }
|
||
return 0;
|
||
});
|
||
|
||
return returnData;
|
||
},
|
||
async getJobParameters(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||
const job = this.getCurrentNodeParameter('job') as string;
|
||
const returnData: INodePropertyOptions[] = [];
|
||
const endpoint = `/job/${job}/api/json?tree=actions[parameterDefinitions[*]]`;
|
||
const { actions } = await jenkinsApiRequest.call(this, 'GET', endpoint);
|
||
for (const { _class, parameterDefinitions } of actions) {
|
||
if (_class?.includes('ParametersDefinitionProperty')) {
|
||
for (const { name, type } of parameterDefinitions) {
|
||
returnData.push({
|
||
name: `${name} - (${type})`,
|
||
value: name,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
returnData.sort((a, b) => {
|
||
if (a.name < b.name) { return -1; }
|
||
if (a.name > b.name) { return 1; }
|
||
return 0;
|
||
});
|
||
|
||
return returnData;
|
||
},
|
||
},
|
||
};
|
||
|
||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||
const items = this.getInputData();
|
||
const returnData: IDataObject[] = [];
|
||
const length = items.length as unknown as number;
|
||
let responseData;
|
||
const resource = this.getNodeParameter('resource', 0) as string;
|
||
const operation = this.getNodeParameter('operation', 0) as string;
|
||
|
||
for (let i = 0; i < length; i++) {
|
||
try {
|
||
if (resource === 'job') {
|
||
if (operation === 'trigger') {
|
||
const job = this.getNodeParameter('job', i) as string;
|
||
const endpoint = `/job/${job}/build`;
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint);
|
||
responseData = { success: true };
|
||
}
|
||
if (operation === 'triggerParams') {
|
||
const job = this.getNodeParameter('job', i) as string;
|
||
const params = this.getNodeParameter('param.params', i, []) as [];
|
||
let body = {};
|
||
if (params.length) {
|
||
body = params.reduce((body: IDataObject, param: { name: string; value: string }) => {
|
||
body[param.name] = param.value;
|
||
return body;
|
||
}, {});
|
||
}
|
||
const endpoint = `/job/${job}/buildWithParameters`;
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint, {}, {},
|
||
{
|
||
form: body,
|
||
headers: {
|
||
'content-type': 'application/x-www-form-urlencoded',
|
||
},
|
||
},
|
||
);
|
||
responseData = { success: true };
|
||
}
|
||
if (operation === 'copy') {
|
||
const job = this.getNodeParameter('job', i) as string;
|
||
const name = this.getNodeParameter('newJob', i) as string;
|
||
const queryParams = {
|
||
name,
|
||
mode: 'copy',
|
||
from: job,
|
||
};
|
||
|
||
const endpoint = `/createItem`;
|
||
try {
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint, queryParams);
|
||
responseData = { success: true };
|
||
}
|
||
catch (error) {
|
||
if (error.httpCode === '302') {
|
||
responseData = { success: true };
|
||
} else {
|
||
throw new NodeApiError(this.getNode(), error);
|
||
}
|
||
}
|
||
}
|
||
if (operation === 'create') {
|
||
const name = this.getNodeParameter('newJob', i) as string;
|
||
const queryParams = {
|
||
name,
|
||
};
|
||
const headers = {
|
||
'content-type': 'application/xml',
|
||
};
|
||
|
||
const body = this.getNodeParameter('xml', i) as string;
|
||
|
||
const endpoint = `/createItem`;
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint, queryParams, body, { headers, json: false });
|
||
responseData = { success: true };
|
||
}
|
||
}
|
||
|
||
if (resource === 'instance') {
|
||
if (operation === 'quietDown') {
|
||
const reason = this.getNodeParameter('reason', i) as string;
|
||
|
||
let queryParams;
|
||
if (reason) {
|
||
queryParams = {
|
||
reason,
|
||
};
|
||
}
|
||
|
||
const endpoint = `/quietDown`;
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint, queryParams);
|
||
responseData = { success: true };
|
||
}
|
||
if (operation === 'cancelQuietDown') {
|
||
const endpoint = `/cancelQuietDown`;
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint);
|
||
responseData = { success: true };
|
||
}
|
||
if (operation === 'restart') {
|
||
const endpoint = `/restart`;
|
||
try {
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint);
|
||
} catch (error) {
|
||
if (error.httpCode === '503') {
|
||
responseData = { success: true };
|
||
} else {
|
||
throw new NodeApiError(this.getNode(), error);
|
||
}
|
||
}
|
||
}
|
||
if (operation === 'safeRestart') {
|
||
const endpoint = `/safeRestart`;
|
||
try {
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint);
|
||
} catch (error) {
|
||
if (error.httpCode === '503') {
|
||
responseData = { success: true };
|
||
} else {
|
||
throw new NodeApiError(this.getNode(), error);
|
||
}
|
||
}
|
||
}
|
||
if (operation === 'exit') {
|
||
const endpoint = `/exit`;
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint);
|
||
responseData = { success: true };
|
||
}
|
||
if (operation === 'safeExit') {
|
||
const endpoint = `/safeExit`;
|
||
await jenkinsApiRequest.call(this, 'POST', endpoint);
|
||
responseData = { success: true };
|
||
}
|
||
}
|
||
|
||
if (resource === 'build') {
|
||
if (operation === 'getAll') {
|
||
const job = this.getNodeParameter('job', i) as string;
|
||
let endpoint = `/job/${job}/api/json?tree=builds[*]`;
|
||
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||
|
||
if (!returnAll) {
|
||
const limit = this.getNodeParameter('limit', i) as number;
|
||
endpoint += `{0,${limit}}`;
|
||
}
|
||
|
||
responseData = await jenkinsApiRequest.call(this, 'GET', endpoint);
|
||
responseData = responseData.builds;
|
||
}
|
||
}
|
||
|
||
if (Array.isArray(responseData)) {
|
||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||
} else {
|
||
returnData.push(responseData as IDataObject);
|
||
}
|
||
} catch (error) {
|
||
if (this.continueOnFail()) {
|
||
returnData.push({ error: error.message });
|
||
continue;
|
||
}
|
||
throw error;
|
||
}
|
||
}
|
||
return [this.helpers.returnJsonArray(returnData)];
|
||
}
|
||
}
|