mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
feat(GitHub Node): Add workflow resource operations (#10744)
This commit is contained in:
parent
4f1816e03d
commit
d309112647
|
@ -119,3 +119,13 @@ export function isBase64(content: string) {
|
|||
const base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
|
||||
return base64regex.test(content);
|
||||
}
|
||||
|
||||
export function validateJSON(json: string | undefined): any {
|
||||
let result;
|
||||
try {
|
||||
result = JSON.parse(json!);
|
||||
} catch (exception) {
|
||||
result = undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@ import {
|
|||
githubApiRequest,
|
||||
githubApiRequestAllItems,
|
||||
isBase64,
|
||||
validateJSON,
|
||||
} from './GenericFunctions';
|
||||
|
||||
import { getRepositories, getUsers } from './SearchFunctions';
|
||||
import { getRepositories, getUsers, getWorkflows } from './SearchFunctions';
|
||||
|
||||
export class Github implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -103,6 +103,10 @@ export class Github implements INodeType {
|
|||
name: 'User',
|
||||
value: 'user',
|
||||
},
|
||||
{
|
||||
name: 'Workflow',
|
||||
value: 'workflow',
|
||||
},
|
||||
],
|
||||
default: 'issue',
|
||||
},
|
||||
|
@ -391,6 +395,129 @@ export class Github implements INodeType {
|
|||
default: 'create',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// workflow
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['workflow'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Disable',
|
||||
value: 'disable',
|
||||
description: 'Disable a workflow',
|
||||
action: 'Disable a workflow',
|
||||
},
|
||||
{
|
||||
name: 'Dispatch',
|
||||
value: 'dispatch',
|
||||
description: 'Dispatch a workflow event',
|
||||
action: 'Dispatch a workflow event',
|
||||
},
|
||||
{
|
||||
name: 'Enable',
|
||||
value: 'enable',
|
||||
description: 'Enable a workflow',
|
||||
action: 'Enable a workflow',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a workflow',
|
||||
action: 'Get a workflow',
|
||||
},
|
||||
{
|
||||
name: 'Get Usage',
|
||||
value: 'getUsage',
|
||||
description: 'Get the usage of a workflow',
|
||||
action: 'Get the usage of a workflow',
|
||||
},
|
||||
{
|
||||
name: 'List',
|
||||
value: 'list',
|
||||
description: 'List workflows',
|
||||
action: 'List workflows',
|
||||
},
|
||||
],
|
||||
default: 'dispatch',
|
||||
},
|
||||
{
|
||||
displayName: 'Workflow',
|
||||
name: 'workflowId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Workflow',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
placeholder: 'Select a workflow...',
|
||||
typeOptions: {
|
||||
searchListMethod: 'getWorkflows',
|
||||
searchable: true,
|
||||
searchFilterRequired: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'By ID',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
placeholder: 'e.g. 12345678',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: '\\d+',
|
||||
errorMessage: 'Not a valid Github Workflow ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['workflow'],
|
||||
operation: ['disable', 'dispatch', 'get', 'getUsage', 'enable'],
|
||||
},
|
||||
},
|
||||
description: 'The workflow to dispatch',
|
||||
},
|
||||
{
|
||||
displayName: 'Ref',
|
||||
name: 'ref',
|
||||
type: 'string',
|
||||
default: 'main',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['workflow'],
|
||||
operation: ['dispatch'],
|
||||
},
|
||||
},
|
||||
description: 'The git reference for the workflow dispatch (branch, tag, or commit SHA)',
|
||||
},
|
||||
{
|
||||
displayName: 'Inputs',
|
||||
name: 'inputs',
|
||||
type: 'json',
|
||||
default: '{}',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['workflow'],
|
||||
operation: ['dispatch'],
|
||||
},
|
||||
},
|
||||
description: 'JSON object with input parameters for the workflow',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// shared
|
||||
// ----------------------------------
|
||||
|
@ -1854,6 +1981,7 @@ export class Github implements INodeType {
|
|||
listSearch: {
|
||||
getUsers,
|
||||
getRepositories,
|
||||
getWorkflows,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1886,6 +2014,12 @@ export class Github implements INodeType {
|
|||
'review:get',
|
||||
'review:update',
|
||||
'user:invite',
|
||||
'workflow:disable',
|
||||
'workflow:dispatch',
|
||||
'workflow:enable',
|
||||
'workflow:get',
|
||||
'workflow:getUsage',
|
||||
'workflow:list',
|
||||
];
|
||||
// Operations which overwrite the returned data and return arrays
|
||||
// and has so to be merged with the data of other items
|
||||
|
@ -2348,6 +2482,77 @@ export class Github implements INodeType {
|
|||
qs.per_page = this.getNodeParameter('limit', 0);
|
||||
}
|
||||
}
|
||||
} else if (resource === 'workflow') {
|
||||
if (operation === 'disable') {
|
||||
// ----------------------------------
|
||||
// disable
|
||||
// ----------------------------------
|
||||
|
||||
requestMethod = 'PUT';
|
||||
|
||||
const workflowId = this.getNodeParameter('workflowId', i) as string;
|
||||
|
||||
endpoint = `/repos/${owner}/${repository}/actions/workflows/${workflowId}/disable`;
|
||||
} else if (operation === 'dispatch') {
|
||||
// ----------------------------------
|
||||
// dispatch
|
||||
// ----------------------------------
|
||||
|
||||
requestMethod = 'POST';
|
||||
|
||||
const workflowId = this.getNodeParameter('workflowId', i) as string;
|
||||
|
||||
endpoint = `/repos/${owner}/${repository}/actions/workflows/${workflowId}/dispatches`;
|
||||
body.ref = this.getNodeParameter('ref', i) as string;
|
||||
|
||||
const inputs = validateJSON(
|
||||
this.getNodeParameter('inputs', i) as string,
|
||||
) as IDataObject;
|
||||
if (inputs === undefined) {
|
||||
throw new NodeOperationError(this.getNode(), 'Inputs: Invalid JSON', {
|
||||
itemIndex: i,
|
||||
});
|
||||
}
|
||||
body.inputs = inputs;
|
||||
} else if (operation === 'enable') {
|
||||
// ----------------------------------
|
||||
// enable
|
||||
// ----------------------------------
|
||||
|
||||
requestMethod = 'PUT';
|
||||
|
||||
const workflowId = this.getNodeParameter('workflowId', i) as string;
|
||||
|
||||
endpoint = `/repos/${owner}/${repository}/actions/workflows/${workflowId}/enable`;
|
||||
} else if (operation === 'get') {
|
||||
// ----------------------------------
|
||||
// get
|
||||
// ----------------------------------
|
||||
|
||||
requestMethod = 'GET';
|
||||
|
||||
const workflowId = this.getNodeParameter('workflowId', i) as string;
|
||||
|
||||
endpoint = `/repos/${owner}/${repository}/actions/workflows/${workflowId}`;
|
||||
} else if (operation === 'getUsage') {
|
||||
// ----------------------------------
|
||||
// getUsage
|
||||
// ----------------------------------
|
||||
|
||||
requestMethod = 'GET';
|
||||
|
||||
const workflowId = this.getNodeParameter('workflowId', i) as string;
|
||||
|
||||
endpoint = `/repos/${owner}/${repository}/actions/workflows/${workflowId}/timing`;
|
||||
} else if (operation === 'list') {
|
||||
// ----------------------------------
|
||||
// list
|
||||
// ----------------------------------
|
||||
|
||||
requestMethod = 'GET';
|
||||
|
||||
endpoint = `/repos/${owner}/${repository}/actions/workflows`;
|
||||
}
|
||||
} else {
|
||||
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, {
|
||||
itemIndex: i,
|
||||
|
|
|
@ -85,3 +85,32 @@ export async function getRepositories(
|
|||
const nextPaginationToken = page * per_page < responseData.total_count ? page + 1 : undefined;
|
||||
return { results, paginationToken: nextPaginationToken };
|
||||
}
|
||||
|
||||
export async function getWorkflows(
|
||||
this: ILoadOptionsFunctions,
|
||||
paginationToken?: string,
|
||||
): Promise<INodeListSearchResult> {
|
||||
const owner = this.getCurrentNodeParameter('owner', { extractValue: true });
|
||||
const repository = this.getCurrentNodeParameter('repository', { extractValue: true });
|
||||
const page = paginationToken ? +paginationToken : 1;
|
||||
const per_page = 100;
|
||||
const endpoint = `/repos/${owner}/${repository}/actions/workflows`;
|
||||
let responseData: { workflows: Array<{ id: string; name: string }>; total_count: number } = {
|
||||
workflows: [],
|
||||
total_count: 0,
|
||||
};
|
||||
|
||||
try {
|
||||
responseData = await githubApiRequest.call(this, 'GET', endpoint, {}, { page, per_page });
|
||||
} catch {
|
||||
// will fail if the repository does not have any workflows
|
||||
}
|
||||
|
||||
const results: INodeListSearchItems[] = responseData.workflows.map((workflow) => ({
|
||||
name: workflow.name,
|
||||
value: workflow.id,
|
||||
}));
|
||||
|
||||
const nextPaginationToken = page * per_page < responseData.total_count ? page + 1 : undefined;
|
||||
return { results, paginationToken: nextPaginationToken };
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue