diff --git a/packages/nodes-base/nodes/Gitlab/GenericFunctions.ts b/packages/nodes-base/nodes/Gitlab/GenericFunctions.ts index 3bb0e12c5..2a8736d62 100644 --- a/packages/nodes-base/nodes/Gitlab/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Gitlab/GenericFunctions.ts @@ -18,7 +18,7 @@ import { OptionsWithUri } from 'request'; * @param {object} body * @returns {Promise} */ -export async function gitlabApiRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: object, query?: object): Promise { // tslint:disable-line:no-any +export async function gitlabApiRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: object, query?: object, option: IDataObject = {}): Promise { // tslint:disable-line:no-any const options : OptionsWithUri = { method, headers: {}, @@ -28,6 +28,9 @@ export async function gitlabApiRequest(this: IHookFunctions | IExecuteFunctions, json: true, }; + if (Object.keys(option).length !== 0) { + Object.assign(options, option); + } if (query === undefined) { delete options.qs; } @@ -71,3 +74,22 @@ export async function gitlabApiRequest(this: IHookFunctions | IExecuteFunctions, throw error; } } + +export async function gitlabApiRequestAllItems(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + + query.per_page = 100; + query.page = 1; + + do { + responseData = await gitlabApiRequest.call(this, method, endpoint, body, query, { resolveWithFullResponse: true }); + query.page++; + returnData.push.apply(returnData, responseData.body); + } while ( + responseData.headers.link && responseData.headers.link.includes('next') + ); + return returnData; +} \ No newline at end of file diff --git a/packages/nodes-base/nodes/Gitlab/Gitlab.node.ts b/packages/nodes-base/nodes/Gitlab/Gitlab.node.ts index 6056af734..0e99f07fa 100644 --- a/packages/nodes-base/nodes/Gitlab/Gitlab.node.ts +++ b/packages/nodes-base/nodes/Gitlab/Gitlab.node.ts @@ -11,6 +11,7 @@ import { import { gitlabApiRequest, + gitlabApiRequestAllItems, } from './GenericFunctions'; export class Gitlab implements INodeType { @@ -209,6 +210,26 @@ export class Gitlab implements INodeType { value: 'create', description: 'Create a new release', }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a new release', + }, + { + name: 'Get', + value: 'get', + description: 'Get a new release', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all releases', + }, + { + name: 'Update', + value: 'update', + description: 'Update a new release', + }, ], default: 'create', description: 'The operation to perform.', @@ -692,8 +713,254 @@ export class Gitlab implements INodeType { ], }, + // ---------------------------------- + // release:get/delete + // ---------------------------------- + { + displayName: 'Project ID', + name: 'projectId', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + 'get', + ], + resource: [ + 'release', + ], + }, + }, + description: 'The ID or URL-encoded path of the project.', + }, + { + displayName: 'Tag Name', + name: 'tag_name', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + 'get', + ], + resource: [ + 'release', + ], + }, + }, + description: 'The Git tag the release is associated with.', + }, + // ---------------------------------- + // release:getAll + // ---------------------------------- + { + displayName: 'Project ID', + name: 'projectId', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'getAll', + ], + resource: [ + 'release', + ], + }, + }, + description: 'The ID or URL-encoded path of the project.', + }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'release', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'release', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 20, + description: 'How many results to return.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + typeOptions: { + multipleValueButtonText: 'Add Field', + }, + displayOptions: { + show: { + operation: [ + 'getAll', + ], + resource: [ + 'release', + ], + }, + }, + default: {}, + options: [ + { + displayName: 'Order by', + name: 'order_by', + type: 'options', + options: [ + { + name: 'Created At', + value: 'created_at', + }, + { + name: 'Released At', + value: 'released_at', + }, + ], + default: 'released_at', + description: 'The field to use as order.', + }, + { + displayName: 'Sort', + name: 'sort', + type: 'options', + options: [ + { + name: 'ASC', + value: 'asc', + }, + { + name: 'DESC', + value: 'desc', + }, + ], + default: 'desc', + description: 'The direction of the order. .', + }, + ], + }, + // ---------------------------------- + // release:update + // ---------------------------------- + { + displayName: 'Project ID', + name: 'projectId', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource: [ + 'release', + ], + }, + }, + description: 'The ID or URL-encoded path of the project.', + }, + { + displayName: 'Tag Name', + name: 'tag_name', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource: [ + 'release', + ], + }, + }, + description: 'The Git tag the release is associated with.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + typeOptions: { + multipleValueButtonText: 'Add Field', + }, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource: [ + 'release', + ], + }, + }, + default: {}, + options: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'The release name.', + }, + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + description: 'The description of the release. You can use Markdown.', + }, + { + displayName: 'Milestones', + name: 'milestones', + type: 'string', + default: '', + description: 'The title of each milestone to associate with the release (provide a titles list spearated with comma).', + }, + { + displayName: 'Released At', + name: 'released_at', + type: 'dateTime', + default: '', + description: 'The date when the release is/was ready..', + }, + ], + }, // ---------------------------------- // repository // ---------------------------------- @@ -856,16 +1123,20 @@ export class Gitlab implements INodeType { 'issue:edit', 'issue:get', 'release:create', + 'release:delete', + 'release:get', + 'release:update', 'repository:get', ]; // Operations which overwrite the returned data and return arrays // and has so to be merged with the data of other items const overwriteDataOperationsArray = [ + 'release:getAll', 'repository:getIssues', 'user:getRepositories', ]; - + let responseData; // For Post let body: IDataObject; // For Query string @@ -873,6 +1144,7 @@ export class Gitlab implements INodeType { let requestMethod: string; let endpoint: string; + let returnAll = false; const operation = this.getNodeParameter('operation', 0) as string; const resource = this.getNodeParameter('resource', 0) as string; @@ -984,6 +1256,69 @@ export class Gitlab implements INodeType { endpoint = `${baseEndpoint}/releases`; } + if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + + const id = this.getNodeParameter('projectId', i) as string; + + const tagName = this.getNodeParameter('tag_name', i) as string; + + endpoint = `/projects/${id}/releases/${tagName}`; + } + if (operation === 'get') { + // ---------------------------------- + // get + // ---------------------------------- + + requestMethod = 'GET'; + + const id = this.getNodeParameter('projectId', i) as string; + + const tagName = this.getNodeParameter('tag_name', i) as string; + + endpoint = `/projects/${id}/releases/${tagName}`; + } + if (operation === 'getAll') { + // ---------------------------------- + // getAll + // ---------------------------------- + + requestMethod = 'GET'; + + const id = this.getNodeParameter('projectId', i) as string; + + qs = this.getNodeParameter('additionalFields', i, {}) as IDataObject; + + returnAll = this.getNodeParameter('returnAll', 0) as boolean; + + if (returnAll === false) { + qs.per_page = this.getNodeParameter('limit', 0) as number; + } + + endpoint = `/projects/${id}/releases`; + } + if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PUT'; + + const id = this.getNodeParameter('projectId', i) as string; + + const tagName = this.getNodeParameter('tag_name', i) as string; + + body = this.getNodeParameter('additionalFields', i, {}) as IDataObject; + if(body.milestones){ + body.milestones = (body.milestones as string).split(','); + } + + endpoint = `/projects/${id}/releases/${tagName}`; + } } else if (resource === 'repository') { if (operation === 'get') { // ---------------------------------- @@ -1018,7 +1353,11 @@ export class Gitlab implements INodeType { throw new Error(`The resource "${resource}" is not known!`); } - const responseData = await gitlabApiRequest.call(this, requestMethod, endpoint, body, qs); + if (returnAll === true) { + responseData = await gitlabApiRequestAllItems.call(this, requestMethod, endpoint, body, qs); + } else { + responseData = await gitlabApiRequest.call(this, requestMethod, endpoint, body, qs); + } if (overwriteDataOperations.includes(fullOperation)) { returnData.push(responseData);