mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-22 20:41:50 +02:00
Convert `githubTrigger` in place and delete `githubDeclarativeTrigger`. Two node types put a duplicate entry in the nodes panel and gave existing workflows nothing, because the declarative twin was a separate node they could not reach. RSS was already converted in place, so Github was the outlier. `checkExists`, `delete` and the delivery handler are now config. Registration stays a function: Github answers a duplicate URL with 422, and adopting that hook takes a GET/compare/PATCH sequence with per-status messages that `create.routing` cannot express. Properties, credentials, version and the resource locators are untouched, and the lifecycle writes the same static-data keys, so active webhooks survive the change. Add two engine options the conversion needs, both general: - `checkExists.requireKeys` marks a stored hook absent while a key it needs is empty. A hook kept without its signing secret fails every signature check, so "present but unusable" has to read as absent or the trigger serves 401s until someone re-activates by hand. - `trigger.managedKeys` names the static-data keys a trigger owns. They were read from `create.store`, so a node using the documented function escape hatch for `create` silently stopped clearing them on delete and on a checkExists not-found. `GithubTriggerHelpers.verifySignature` is dead once the engine verifies deliveries, so it goes with its test. The node test now drives the synthesized handler with real HMAC digests, where the old one stubbed verification out and never checked the signature contract. Also narrow a trigger union in the RSS test, which stopped `pnpm typecheck` in nodes-base.
701 lines
21 KiB
TypeScript
701 lines
21 KiB
TypeScript
import { randomBytes } from 'crypto';
|
|
import type {
|
|
IHookFunctions,
|
|
IDataObject,
|
|
INodeType,
|
|
INodeTypeDescription,
|
|
JsonObject,
|
|
} from 'n8n-workflow';
|
|
import { NodeConnectionTypes, NodeApiError, NodeOperationError } from 'n8n-workflow';
|
|
|
|
import { githubApiRequest } from './GenericFunctions';
|
|
import { getRepositories, getUsers } from './SearchFunctions';
|
|
|
|
const CANNOT_CREATE_MESSAGE = 'Github refused to create the webhook for this workflow';
|
|
|
|
/** Github's reason is in `description`; NodeApiError overwrites `message` on a 4XX. */
|
|
function describeGithubRejection(error: unknown): string {
|
|
const reason = (error as { description?: string } | undefined)?.description;
|
|
const advice =
|
|
'If a webhook for this URL already exists on the repository, delete it there and activate the workflow again.';
|
|
|
|
return reason ? `Github said: ${reason}. ${advice}` : advice;
|
|
}
|
|
|
|
/**
|
|
* Registration stays a function while the declarative lifecycle has no
|
|
* conditional-request shape: Github answers a duplicate URL with 422, and
|
|
* adopting that hook takes a GET/compare/PATCH sequence plus per-status
|
|
* messages that `create.routing` cannot express.
|
|
*/
|
|
async function createWebhook(this: IHookFunctions): Promise<boolean> {
|
|
const webhookUrl = this.getNodeWebhookUrl('default') as string;
|
|
|
|
if (webhookUrl.includes('//localhost')) {
|
|
throw new NodeOperationError(
|
|
this.getNode(),
|
|
'The Webhook can not work on "localhost". Please setup n8n on a custom domain.',
|
|
);
|
|
}
|
|
|
|
const owner = this.getNodeParameter('owner', '', { extractValue: true }) as string;
|
|
const repository = this.getNodeParameter('repository', '', {
|
|
extractValue: true,
|
|
}) as string;
|
|
const events = this.getNodeParameter('events', []);
|
|
|
|
const endpoint = `/repos/${owner}/${repository}/hooks`;
|
|
const options = this.getNodeParameter('options') as { insecureSSL: boolean };
|
|
|
|
// Generate a secure random secret for webhook signature verification
|
|
const webhookSecret = randomBytes(32).toString('hex');
|
|
|
|
const body = {
|
|
name: 'web',
|
|
config: {
|
|
url: webhookUrl,
|
|
content_type: 'json',
|
|
insecure_ssl: options.insecureSSL ? '1' : '0',
|
|
secret: webhookSecret,
|
|
},
|
|
events,
|
|
active: true,
|
|
};
|
|
|
|
const webhookData = this.getWorkflowStaticData('node');
|
|
|
|
let responseData;
|
|
try {
|
|
responseData = await githubApiRequest.call(this, 'POST', endpoint, body);
|
|
} catch (error) {
|
|
if (error.httpCode === '422') {
|
|
// Webhook exists already
|
|
|
|
// Without a stored id there is no hook to fetch, so nothing is adoptable.
|
|
if (webhookData.webhookId === undefined) {
|
|
throw new NodeOperationError(this.getNode(), CANNOT_CREATE_MESSAGE, {
|
|
description: describeGithubRejection(error),
|
|
level: 'warning',
|
|
});
|
|
}
|
|
|
|
// Asking for it by id is what makes adopting someone else's hook
|
|
// impossible: Github never returns a hook's secret, so rotating ours onto a
|
|
// foreign hook would silently rewrite their config.
|
|
let existingWebhook: IDataObject;
|
|
try {
|
|
existingWebhook = await githubApiRequest.call(
|
|
this,
|
|
'GET',
|
|
`${endpoint}/${webhookData.webhookId}`,
|
|
{},
|
|
);
|
|
} catch (error2) {
|
|
if (error2.httpCode === '404') {
|
|
// Ours is gone, so whatever Github is objecting to is not ours to fix.
|
|
throw new NodeOperationError(this.getNode(), CANNOT_CREATE_MESSAGE, {
|
|
description: describeGithubRejection(error),
|
|
level: 'warning',
|
|
});
|
|
}
|
|
|
|
throw error2;
|
|
}
|
|
|
|
// A different URL means some other hook is the one Github is objecting to,
|
|
// and repointing this one would leave two hooks on the same URL.
|
|
if ((existingWebhook.config as IDataObject | undefined)?.url !== webhookUrl) {
|
|
throw new NodeOperationError(this.getNode(), CANNOT_CREATE_MESSAGE, {
|
|
description: describeGithubRejection(error),
|
|
level: 'warning',
|
|
});
|
|
}
|
|
|
|
// `active` is re-asserted so a disabled hook cannot look like a successful
|
|
// activation.
|
|
let patchResponse;
|
|
try {
|
|
patchResponse = await githubApiRequest.call(
|
|
this,
|
|
'PATCH',
|
|
`${endpoint}/${existingWebhook.id}`,
|
|
{ config: body.config, events, active: true },
|
|
);
|
|
} catch (patchError) {
|
|
// Re-label in place: NodeApiError's constructor hands back the instance it
|
|
// is given unchanged, so building a new one would drop this message.
|
|
if (patchError instanceof NodeApiError) {
|
|
patchError.message =
|
|
'The Github webhook for this URL already exists but could not be updated with a signing secret';
|
|
patchError.description = [
|
|
patchError.description,
|
|
"Check that the credential is allowed to manage this repository's webhooks, or delete the webhook on Github and activate the workflow again.",
|
|
]
|
|
.filter(Boolean)
|
|
.join(' ');
|
|
}
|
|
|
|
throw patchError;
|
|
}
|
|
|
|
if (patchResponse?.active !== true) {
|
|
throw new NodeApiError(this.getNode(), (patchResponse ?? {}) as JsonObject, {
|
|
message: 'Github did not apply the update to the existing webhook',
|
|
description:
|
|
'The webhook exists but could not be enabled with a signing secret. Delete it on Github and activate the workflow again.',
|
|
level: 'warning',
|
|
});
|
|
}
|
|
|
|
webhookData.webhookId = String(existingWebhook.id);
|
|
webhookData.webhookEvents = existingWebhook.events as string[];
|
|
webhookData.webhookSecret = webhookSecret;
|
|
|
|
return true;
|
|
}
|
|
|
|
if (error.httpCode === '404') {
|
|
throw new NodeOperationError(
|
|
this.getNode(),
|
|
'Check that the repository exists and that you have permission to create the webhooks this node requires',
|
|
{ level: 'warning' },
|
|
);
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
|
|
if (responseData.id === undefined || responseData.active !== true) {
|
|
// Required data is missing so was not successful
|
|
throw new NodeApiError(this.getNode(), responseData as JsonObject, {
|
|
message: 'Github webhook creation response did not contain the expected data.',
|
|
});
|
|
}
|
|
|
|
const strandedWebhookId = webhookData.webhookId;
|
|
|
|
webhookData.webhookId = responseData.id as string;
|
|
webhookData.webhookEvents = responseData.events as string[];
|
|
webhookData.webhookSecret = webhookSecret;
|
|
|
|
if (strandedWebhookId !== undefined) {
|
|
this.logger.warn(
|
|
`Github Trigger "${this.getNode().name}" registered a new webhook. Webhook ${String(strandedWebhookId)} may still be on the repository and is no longer tracked; check the repository's webhook settings.`,
|
|
{ workflowId: this.getWorkflow().id, strandedWebhookId },
|
|
);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/** URL of the repository hook this node registered. */
|
|
const HOOK_URL =
|
|
'={{ "/repos/" + $parameter.owner + "/" + $parameter.repository + "/hooks/" + $staticData.webhookId }}';
|
|
|
|
export class GithubTrigger implements INodeType {
|
|
description: INodeTypeDescription = {
|
|
displayName: 'Github Trigger',
|
|
name: 'githubTrigger',
|
|
icon: { light: 'file:github.svg', dark: 'file:github.dark.svg' },
|
|
group: ['trigger'],
|
|
version: 1,
|
|
subtitle:
|
|
'={{$parameter["owner"] + "/" + $parameter["repository"] + ": " + $parameter["events"].join(", ")}}',
|
|
description: 'Starts the workflow when Github events occur',
|
|
defaults: {
|
|
name: 'Github Trigger',
|
|
},
|
|
inputs: [],
|
|
outputs: [NodeConnectionTypes.Main],
|
|
credentials: [
|
|
{
|
|
name: 'githubApi',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
authentication: ['accessToken'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'githubOAuth2Api',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
authentication: ['oAuth2'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'githubAppApi',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
authentication: ['githubAppApi'],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
webhooks: [
|
|
{
|
|
name: 'default',
|
|
httpMethod: 'POST',
|
|
responseMode: 'onReceived',
|
|
path: 'webhook',
|
|
},
|
|
],
|
|
requestDefaults: {
|
|
baseURL: '={{ $credentials.server || "https://api.github.com" }}',
|
|
json: true,
|
|
},
|
|
trigger: {
|
|
type: 'webhook',
|
|
lifecycle: {
|
|
checkExists: {
|
|
routing: { request: { method: 'GET', url: HOOK_URL } },
|
|
// A blank secret must not count as present here and absent in
|
|
// `handler.verification`; re-register rather than serve 401s forever.
|
|
requireKeys: ['webhookSecret'],
|
|
notFoundHttpCodes: [404],
|
|
},
|
|
create: createWebhook,
|
|
delete: {
|
|
routing: { request: { method: 'DELETE', url: HOOK_URL } },
|
|
},
|
|
},
|
|
// Spelled out because `create` is a function, so there is no `store` to
|
|
// read the owned keys from.
|
|
managedKeys: ['webhookId', 'webhookEvents', 'webhookSecret'],
|
|
handler: {
|
|
// Github signs the raw body and sends `sha256=<hex digest>`. A delivery that
|
|
// fails this, or arrives while no secret is stored, is answered 401.
|
|
verification: {
|
|
algorithm: 'hmac-sha256',
|
|
signatureHeader: 'x-hub-signature-256',
|
|
secret: '={{ $staticData.webhookSecret }}',
|
|
encoding: 'hex',
|
|
prefix: 'sha256=',
|
|
signedPayload: 'rawBody',
|
|
},
|
|
// Github's post-registration liveness check: answer, start nothing. Read
|
|
// from the body, the same test the programmatic handler used.
|
|
ping: {
|
|
when: '={{ $request.body.hook_id !== undefined && $request.body.action === undefined }}',
|
|
response: 'OK',
|
|
},
|
|
// No event filter: Github delivers only what the hook subscribes to, and
|
|
// dropping anything else here would be a silent no-op this node never did.
|
|
output: { includeMeta: true },
|
|
},
|
|
},
|
|
properties: [
|
|
{
|
|
displayName:
|
|
'Only members with owner privileges for an organization or admin privileges for a repository can set up the webhooks this node requires.',
|
|
name: 'notice',
|
|
type: 'notice',
|
|
default: '',
|
|
},
|
|
{
|
|
displayName: 'Authentication',
|
|
name: 'authentication',
|
|
type: 'options',
|
|
options: [
|
|
{
|
|
name: 'Access Token',
|
|
value: 'accessToken',
|
|
},
|
|
{
|
|
name: 'OAuth2',
|
|
value: 'oAuth2',
|
|
},
|
|
{
|
|
name: 'GitHub App',
|
|
value: 'githubAppApi',
|
|
},
|
|
],
|
|
default: 'accessToken',
|
|
},
|
|
{
|
|
displayName: 'Repository Owner',
|
|
name: 'owner',
|
|
type: 'resourceLocator',
|
|
default: { mode: 'list', value: '' },
|
|
required: true,
|
|
modes: [
|
|
{
|
|
displayName: 'Repository Owner',
|
|
name: 'list',
|
|
type: 'list',
|
|
placeholder: 'Select an owner...',
|
|
typeOptions: {
|
|
searchListMethod: 'getUsers',
|
|
searchable: true,
|
|
searchFilterRequired: true,
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Link',
|
|
name: 'url',
|
|
type: 'string',
|
|
placeholder: 'e.g. https://github.com/n8n-io',
|
|
extractValue: {
|
|
type: 'regex',
|
|
regex: 'https:\\/\\/(?:[^/]+)\\/([-_0-9a-zA-Z]+)',
|
|
},
|
|
validation: [
|
|
{
|
|
type: 'regex',
|
|
properties: {
|
|
regex: 'https:\\/\\/([^/]+)\\/([-_0-9a-zA-Z]+)(?:.*)',
|
|
errorMessage: 'Not a valid Github URL',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
displayName: 'By Name',
|
|
name: 'name',
|
|
type: 'string',
|
|
placeholder: 'e.g. n8n-io',
|
|
validation: [
|
|
{
|
|
type: 'regex',
|
|
properties: {
|
|
regex: '[-_a-zA-Z0-9]+',
|
|
errorMessage: 'Not a valid Github Owner Name',
|
|
},
|
|
},
|
|
],
|
|
url: '=https://github.com/{{$value}}',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
displayName: 'Repository Name',
|
|
name: 'repository',
|
|
type: 'resourceLocator',
|
|
default: { mode: 'list', value: '' },
|
|
required: true,
|
|
modes: [
|
|
{
|
|
displayName: 'Repository Name',
|
|
name: 'list',
|
|
type: 'list',
|
|
placeholder: 'Select an Repository...',
|
|
typeOptions: {
|
|
searchListMethod: 'getRepositories',
|
|
searchable: true,
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Link',
|
|
name: 'url',
|
|
type: 'string',
|
|
placeholder: 'e.g. https://github.com/n8n-io/n8n',
|
|
extractValue: {
|
|
type: 'regex',
|
|
regex: 'https:\\/\\/(?:[^/]+)\\/(?:[-_0-9a-zA-Z]+)\\/([-_.0-9a-zA-Z]+)',
|
|
},
|
|
validation: [
|
|
{
|
|
type: 'regex',
|
|
properties: {
|
|
regex: 'https:\\/\\/([^/]+)\\/(?:[-_0-9a-zA-Z]+)\\/([-_.0-9a-zA-Z]+)(?:.*)',
|
|
errorMessage: 'Not a valid Github Repository URL',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
displayName: 'By Name',
|
|
name: 'name',
|
|
type: 'string',
|
|
placeholder: 'e.g. n8n',
|
|
validation: [
|
|
{
|
|
type: 'regex',
|
|
properties: {
|
|
regex: '[-_.0-9a-zA-Z]+',
|
|
errorMessage: 'Not a valid Github Repository Name',
|
|
},
|
|
},
|
|
],
|
|
url: '=https://github.com/{{$parameter["owner"]}}/{{$value}}',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
displayName: 'Events',
|
|
name: 'events',
|
|
type: 'multiOptions',
|
|
options: [
|
|
{
|
|
name: '*',
|
|
value: '*',
|
|
description: 'Any time any event is triggered (Wildcard Event)',
|
|
},
|
|
{
|
|
name: 'Check Run',
|
|
value: 'check_run',
|
|
description:
|
|
'Triggered when a check run is created, rerequested, completed, or has a requested_action',
|
|
},
|
|
{
|
|
name: 'Check Suite',
|
|
value: 'check_suite',
|
|
description: 'Triggered when a check suite is completed, requested, or rerequested',
|
|
},
|
|
{
|
|
name: 'Commit Comment',
|
|
value: 'commit_comment',
|
|
description: 'Triggered when a commit comment is created',
|
|
},
|
|
{
|
|
name: 'Create',
|
|
value: 'create',
|
|
description: 'Represents a created repository, branch, or tag',
|
|
},
|
|
{
|
|
name: 'Delete',
|
|
value: 'delete',
|
|
description: 'Represents a deleted branch or tag',
|
|
},
|
|
{
|
|
name: 'Deploy Key',
|
|
value: 'deploy_key',
|
|
description: 'Triggered when a deploy key is added or removed from a repository',
|
|
},
|
|
{
|
|
name: 'Deployment',
|
|
value: 'deployment',
|
|
description: 'Represents a deployment',
|
|
},
|
|
{
|
|
name: 'Deployment Status',
|
|
value: 'deployment_status',
|
|
description: 'Represents a deployment status',
|
|
},
|
|
{
|
|
name: 'Fork',
|
|
value: 'fork',
|
|
description: 'Triggered when a user forks a repository',
|
|
},
|
|
{
|
|
name: 'Github App Authorization',
|
|
value: 'github_app_authorization',
|
|
description: 'Triggered when someone revokes their authorization of a GitHub App',
|
|
},
|
|
{
|
|
name: 'Gollum',
|
|
value: 'gollum',
|
|
description: 'Triggered when a Wiki page is created or updated',
|
|
},
|
|
{
|
|
name: 'Installation',
|
|
value: 'installation',
|
|
description:
|
|
'Triggered when someone installs (created), uninstalls (deleted), or accepts new permissions (new_permissions_accepted) for a GitHub App. When a GitHub App owner requests new permissions, the person who installed the GitHub App must accept the new permissions request.',
|
|
},
|
|
{
|
|
name: 'Installation Repositories',
|
|
value: 'installation_repositories',
|
|
description: 'Triggered when a repository is added or removed from an installation',
|
|
},
|
|
{
|
|
name: 'Issue Comment',
|
|
value: 'issue_comment',
|
|
description: 'Triggered when an issue comment is created, edited, or deleted',
|
|
},
|
|
{
|
|
name: 'Issues',
|
|
value: 'issues',
|
|
description:
|
|
'Triggered when an issue is opened, edited, deleted, transferred, pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, locked, unlocked, milestoned, or demilestoned',
|
|
},
|
|
{
|
|
name: 'Label',
|
|
value: 'label',
|
|
description: "Triggered when a repository's label is created, edited, or deleted",
|
|
},
|
|
{
|
|
name: 'Marketplace Purchase',
|
|
value: 'marketplace_purchase',
|
|
description:
|
|
'Triggered when someone purchases a GitHub Marketplace plan, cancels their plan, upgrades their plan (effective immediately), downgrades a plan that remains pending until the end of the billing cycle, or cancels a pending plan change',
|
|
},
|
|
{
|
|
name: 'Member',
|
|
value: 'member',
|
|
description:
|
|
'Triggered when a user accepts an invitation or is removed as a collaborator to a repository, or has their permissions changed',
|
|
},
|
|
{
|
|
name: 'Membership',
|
|
value: 'membership',
|
|
description:
|
|
'Triggered when a user is added or removed from a team. Organization hooks only.',
|
|
},
|
|
{
|
|
name: 'Meta',
|
|
value: 'meta',
|
|
description: 'Triggered when the webhook that this event is configured on is deleted',
|
|
},
|
|
{
|
|
name: 'Milestone',
|
|
value: 'milestone',
|
|
description:
|
|
'Triggered when a milestone is created, closed, opened, edited, or deleted',
|
|
},
|
|
{
|
|
name: 'Org Block',
|
|
value: 'org_block',
|
|
description:
|
|
'Triggered when an organization blocks or unblocks a user. Organization hooks only.',
|
|
},
|
|
{
|
|
name: 'Organization',
|
|
value: 'organization',
|
|
description:
|
|
'Triggered when an organization is deleted and renamed, and when a user is added, removed, or invited to an organization. Organization hooks only.',
|
|
},
|
|
{
|
|
name: 'Page Build',
|
|
value: 'page_build',
|
|
description:
|
|
'Triggered on push to a GitHub Pages enabled branch (gh-pages for project pages, master for user and organization pages)',
|
|
},
|
|
{
|
|
name: 'Project',
|
|
value: 'project',
|
|
description:
|
|
'Triggered when a project is created, updated, closed, reopened, or deleted',
|
|
},
|
|
{
|
|
name: 'Project Card',
|
|
value: 'project_card',
|
|
description:
|
|
'Triggered when a project card is created, edited, moved, converted to an issue, or deleted',
|
|
},
|
|
{
|
|
name: 'Project Column',
|
|
value: 'project_column',
|
|
description: 'Triggered when a project column is created, updated, moved, or deleted',
|
|
},
|
|
{
|
|
name: 'Public',
|
|
value: 'public',
|
|
description: 'Triggered when a private repository is open sourced',
|
|
},
|
|
{
|
|
name: 'Pull Request',
|
|
value: 'pull_request',
|
|
description:
|
|
'Triggered when a pull request is assigned, unassigned, labeled, unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, locked, unlocked, a pull request review is requested, or a review request is removed',
|
|
},
|
|
{
|
|
name: 'Pull Request Review',
|
|
value: 'pull_request_review',
|
|
description:
|
|
'Triggered when a pull request review is submitted into a non-pending state, the body is edited, or the review is dismissed',
|
|
},
|
|
{
|
|
name: 'Pull Request Review Comment',
|
|
value: 'pull_request_review_comment',
|
|
description:
|
|
"Triggered when a comment on a pull request's unified diff is created, edited, or deleted (in the Files Changed tab)",
|
|
},
|
|
{
|
|
name: 'Push',
|
|
value: 'push',
|
|
description:
|
|
'Triggered on a push to a repository branch. Branch pushes and repository tag pushes also trigger webhook push events. This is the default event.',
|
|
},
|
|
{
|
|
name: 'Release',
|
|
value: 'release',
|
|
description:
|
|
'Triggered when a release is published, unpublished, created, edited, deleted, or prereleased',
|
|
},
|
|
{
|
|
name: 'Repository',
|
|
value: 'repository',
|
|
description:
|
|
'Triggered when a repository is created, archived, unarchived, renamed, edited, transferred, made public, or made private. Organization hooks are also triggered when a repository is deleted.',
|
|
},
|
|
{
|
|
name: 'Repository Import',
|
|
value: 'repository_import',
|
|
description:
|
|
'Triggered when a successful, cancelled, or failed repository import finishes for a GitHub organization or a personal repository',
|
|
},
|
|
{
|
|
name: 'Repository Vulnerability Alert',
|
|
value: 'repository_vulnerability_alert',
|
|
description: 'Triggered when a security alert is created, dismissed, or resolved',
|
|
},
|
|
{
|
|
name: 'Security Advisory',
|
|
value: 'security_advisory',
|
|
description:
|
|
'Triggered when a new security advisory is published, updated, or withdrawn',
|
|
},
|
|
{
|
|
name: 'Star',
|
|
value: 'star',
|
|
description: 'Triggered when a star is added or removed from a repository',
|
|
},
|
|
{
|
|
name: 'Status',
|
|
value: 'status',
|
|
description: 'Triggered when the status of a Git commit changes',
|
|
},
|
|
{
|
|
name: 'Team',
|
|
value: 'team',
|
|
description:
|
|
"Triggered when an organization's team is created, deleted, edited, added_to_repository, or removed_from_repository. Organization hooks only.",
|
|
},
|
|
{
|
|
name: 'Team Add',
|
|
value: 'team_add',
|
|
description: 'Triggered when a repository is added to a team',
|
|
},
|
|
{
|
|
name: 'Watch',
|
|
value: 'watch',
|
|
description: 'Triggered when someone stars a repository',
|
|
},
|
|
],
|
|
required: true,
|
|
default: [],
|
|
description: 'The events to listen to',
|
|
},
|
|
{
|
|
displayName: 'Options',
|
|
name: 'options',
|
|
type: 'collection',
|
|
placeholder: 'Add option',
|
|
default: {},
|
|
options: [
|
|
{
|
|
displayName: 'Insecure SSL',
|
|
name: 'insecureSSL',
|
|
type: 'boolean',
|
|
default: false,
|
|
description:
|
|
'Whether the SSL certificate of the n8n host be verified by GitHub when delivering payloads',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
methods = {
|
|
listSearch: {
|
|
getUsers,
|
|
getRepositories,
|
|
},
|
|
};
|
|
}
|