first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,101 @@
import { snakeCase } from 'change-case';
import type {
JsonObject,
IDataObject,
IExecuteFunctions,
ILoadOptionsFunctions,
IHookFunctions,
IWebhookFunctions,
IHttpRequestMethods,
IRequestOptions,
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
export async function pagerDutyApiRequest(
this: IExecuteFunctions | IWebhookFunctions | IHookFunctions | ILoadOptionsFunctions,
method: IHttpRequestMethods,
resource: string,
body: any = {},
query: IDataObject = {},
uri?: string,
headers: IDataObject = {},
): Promise<any> {
const authenticationMethod = this.getNodeParameter('authentication', 0);
const options: IRequestOptions = {
headers: {
Accept: 'application/vnd.pagerduty+json;version=2',
},
method,
body,
qs: query,
uri: uri || `https://api.pagerduty.com${resource}`,
json: true,
qsStringifyOptions: {
arrayFormat: 'brackets',
},
};
if (!Object.keys(body as IDataObject).length) {
delete options.form;
}
if (!Object.keys(query).length) {
delete options.qs;
}
options.headers = Object.assign({}, options.headers, headers);
try {
if (authenticationMethod === 'apiToken') {
const credentials = await this.getCredentials('pagerDutyApi');
options.headers.Authorization = `Token token=${credentials.apiToken}`;
return await this.helpers.request(options);
} else {
return await this.helpers.requestOAuth2.call(this, 'pagerDutyOAuth2Api', options);
}
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
}
export async function pagerDutyApiRequestAllItems(
this: IExecuteFunctions | ILoadOptionsFunctions,
propertyName: string,
method: IHttpRequestMethods,
endpoint: string,
body: any = {},
query: IDataObject = {},
): Promise<any> {
const returnData: IDataObject[] = [];
let responseData;
query.limit = 100;
query.offset = 0;
do {
responseData = await pagerDutyApiRequest.call(this, method, endpoint, body, query);
query.offset++;
returnData.push.apply(returnData, responseData[propertyName] as IDataObject[]);
} while (responseData.more);
return returnData;
}
export function keysToSnakeCase(elements: IDataObject[] | IDataObject): IDataObject[] {
if (!Array.isArray(elements)) {
elements = [elements];
}
for (const element of elements) {
for (const key of Object.keys(element)) {
if (key !== snakeCase(key)) {
element[snakeCase(key)] = element[key];
delete element[key];
}
}
}
return elements;
}
@@ -0,0 +1,606 @@
import type { INodeProperties } from 'n8n-workflow';
export const incidentOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['incident'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create an incident',
action: 'Create an incident',
},
{
name: 'Get',
value: 'get',
description: 'Get an incident',
action: 'Get an incident',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many incidents',
action: 'Get many incidents',
},
{
name: 'Update',
value: 'update',
description: 'Update an incident',
action: 'Update an incident',
},
],
default: 'create',
},
];
export const incidentFields: INodeProperties[] = [
/* -------------------------------------------------------------------------- */
/* incident:create */
/* -------------------------------------------------------------------------- */
{
displayName: 'Title',
name: 'title',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incident'],
operation: ['create'],
},
},
description: 'A succinct description of the nature, symptoms, cause, or effect of the incident',
},
{
displayName: 'Service Name or ID',
name: 'serviceId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getServices',
},
required: true,
default: '',
displayOptions: {
show: {
resource: ['incident'],
operation: ['create'],
},
},
description:
'The incident will be created on this service. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
placeholder: 'name@email.com',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incident'],
operation: ['create'],
},
},
description: 'The email address of a valid user associated with the account making the request',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
resource: ['incident'],
operation: ['create'],
},
},
default: {},
options: [
{
displayName: 'Escalation Policy Name or ID',
name: 'escalationPolicyId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getEscalationPolicies',
},
default: '',
description:
'Delegate this incident to the specified escalation policy. Cannot be specified if an assignee is given. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Incident Details',
name: 'details',
type: 'string',
default: '',
description: 'Additional details about the incident which will go in the body',
},
{
displayName: 'Incident Key',
name: 'incidentKey',
type: 'string',
default: '',
description:
'Sending subsequent requests referencing the same service and with the same incident_key will result in those requests being rejected if an open incident matches that incident_key',
},
{
displayName: 'Priority Name or ID',
name: 'priorityId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getPriorities',
},
default: '',
description:
'The incident will be created on this service. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Urgency',
name: 'urgency',
type: 'options',
options: [
{
name: 'Hight',
value: 'high',
},
{
name: 'Low',
value: 'low',
},
],
default: '',
description: 'The urgency of the incident',
},
],
},
{
displayName: 'Conference Bridge',
name: 'conferenceBridgeUi',
type: 'fixedCollection',
typeOptions: {
multipleValues: false,
},
placeholder: 'Add Conference Bridge',
displayOptions: {
show: {
resource: ['incident'],
operation: ['create'],
},
},
default: {},
options: [
{
displayName: 'Conference Bridge',
name: 'conferenceBridgeValues',
values: [
{
displayName: 'Conference Number',
name: 'conferenceNumber',
type: 'string',
default: '',
description:
'Phone numbers should be formatted like +1 415-555-1212,,,,1234#, where a comma (,) represents a one-second wait and pound (#) completes access code input',
},
{
displayName: 'Conference URL',
name: 'conferenceUrl',
type: 'string',
default: '',
description:
'An URL for the conference bridge. This could be a link to a web conference or Slack channel.',
},
],
},
],
},
/* -------------------------------------------------------------------------- */
/* incident:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Incident ID',
name: 'incidentId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incident'],
operation: ['get'],
},
},
description: 'Unique identifier for the incident',
},
/* -------------------------------------------------------------------------- */
/* incident:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['incident'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['incident'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'Max number of results to return',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['incident'],
operation: ['getAll'],
},
},
options: [
{
displayName: 'Date Range',
name: 'dateRange',
type: 'options',
options: [
{
name: 'All',
value: 'all',
},
],
default: '',
description: 'When set to all, the since and until parameters and defaults are ignored',
},
{
displayName: 'Incident Key',
name: 'incidentKey',
type: 'string',
default: '',
description:
'Incident de-duplication key. Incidents with child alerts do not have an incident key; querying by incident key will return incidents whose alerts have alert_key matching the given incident key.',
},
{
displayName: 'Include',
name: 'include',
type: 'multiOptions',
options: [
{
name: 'Acknowledgers',
value: 'acknowledgers',
},
{
name: 'Assignees',
value: 'assignees',
},
{
name: 'Conference Bridge',
value: 'conferenceBridge',
},
{
name: 'Escalation Policies',
value: 'escalationPolicies',
},
{
name: 'First Trigger Log Entries',
value: 'firstTriggerLogEntries',
},
{
name: 'Priorities',
value: 'priorities',
},
{
name: 'Services',
value: 'services',
},
{
name: 'Teams',
value: 'teams',
},
{
name: 'Users',
value: 'users',
},
],
default: [],
description: 'Additional details to include',
},
{
displayName: 'Service Names or IDs',
name: 'serviceIds',
type: 'multiOptions',
typeOptions: {
loadOptionsMethod: 'getServices',
},
default: [],
description:
'Returns only the incidents associated with the passed service(s). Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Since',
name: 'since',
type: 'dateTime',
default: '',
description:
'The start of the date range over which you want to search. (the limit on date ranges is 6 months).',
},
{
displayName: 'Sort By',
name: 'sortBy',
type: 'string',
default: '',
placeholder: 'created_at:asc,resolved_at:desc',
description:
'Used to specify both the field you wish to sort the results on (incident_number/created_at/resolved_at/urgency), as well as the direction (asc/desc) of the results. The sort_by field and direction should be separated by a colon. A maximum of two fields can be included, separated by a comma.',
},
{
displayName: 'Statuses',
name: 'statuses',
type: 'multiOptions',
options: [
{
name: 'Acknowledged',
value: 'acknowledged',
},
{
name: 'Resolved',
value: 'resolved',
},
{
name: 'Triggered',
value: 'triggered',
},
],
default: [],
description: 'Returns only the incidents associated with the passed service(s)',
},
{
displayName: 'Team IDs',
name: 'teamIds',
type: 'string',
default: '',
description:
'Team IDs. Only results related to these teams will be returned. Account must have the teams ability to use this parameter. (multiples IDs can be added separated by comma)',
},
{
displayName: 'Timezone Name or ID',
name: 'timeZone',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getTimezones',
},
default: '',
description:
'Time zone in which dates in the result will be rendered. If not set dates will return UTC. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Until',
name: 'until',
type: 'dateTime',
default: '',
description:
'The end of the date range over which you want to search. (the limit on date ranges is 6 months).',
},
{
displayName: 'Urgencies',
name: 'urgencies',
type: 'multiOptions',
options: [
{
name: 'High',
value: 'high',
},
{
name: 'Low',
value: 'low',
},
],
default: [],
description:
'Urgencies of the incidents to be returned. Defaults to all urgencies. Account must have the urgencies ability to do this',
},
{
displayName: 'User IDs',
name: 'userIds',
type: 'string',
default: '',
description:
'Returns only the incidents currently assigned to the passed user(s). This expects one or more user IDs (multiple IDs can be added separated by comma).',
},
],
},
/* -------------------------------------------------------------------------- */
/* incident:update */
/* -------------------------------------------------------------------------- */
{
displayName: 'Incident ID',
name: 'incidentId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incident'],
operation: ['update'],
},
},
description: 'Unique identifier for the incident',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
placeholder: 'name@email.com',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incident'],
operation: ['update'],
},
},
description: 'The email address of a valid user associated with the account making the request',
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
resource: ['incident'],
operation: ['update'],
},
},
default: {},
options: [
{
displayName: 'Escalation Level',
name: 'escalationLevel',
type: 'number',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Escalate the incident to this level in the escalation policy',
},
{
displayName: 'Escalation Policy Name or ID',
name: 'escalationPolicyId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getEscalationPolicies',
},
default: '',
description:
'Delegate this incident to the specified escalation policy. Cannot be specified if an assignee is given. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Priority Name or ID',
name: 'priorityId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getPriorities',
},
default: '',
description:
'The incident will be created on this service. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Resolution',
name: 'resolution',
type: 'string',
default: '',
description: 'The resolution for this incident if status is set to resolved',
},
{
displayName: 'Status',
name: 'status',
type: 'options',
options: [
{
name: 'Acknowledged',
value: 'acknowledged',
},
{
name: 'Resolved',
value: 'resolved',
},
],
default: '',
description: 'The new status of the incident',
},
{
displayName: 'Title',
name: 'title',
type: 'string',
default: '',
description:
'A succinct description of the nature, symptoms, cause, or effect of the incident',
},
{
displayName: 'Urgency',
name: 'urgency',
type: 'options',
options: [
{
name: 'High',
value: 'high',
},
{
name: 'Low',
value: 'low',
},
],
default: '',
description: 'The urgency of the incident',
},
],
},
{
displayName: 'Conference Bridge',
name: 'conferenceBridgeUi',
type: 'fixedCollection',
typeOptions: {
multipleValues: false,
},
placeholder: 'Add Conference Bridge',
displayOptions: {
show: {
resource: ['incident'],
operation: ['update'],
},
},
default: {},
options: [
{
displayName: 'Conference Bridge',
name: 'conferenceBridgeValues',
values: [
{
displayName: 'Conference Number',
name: 'conferenceNumber',
type: 'string',
default: '',
description:
'Phone numbers should be formatted like +1 415-555-1212,,,,1234#, where a comma (,) represents a one-second wait and pound (#) completes access code input',
},
{
displayName: 'Conference URL',
name: 'conferenceUrl',
type: 'string',
default: '',
description:
'An URL for the conference bridge. This could be a link to a web conference or Slack channel.',
},
],
},
],
},
];
@@ -0,0 +1,17 @@
import type { IDataObject } from 'n8n-workflow';
export interface IIncident {
assignments?: IDataObject[];
body?: IDataObject;
conference_bridge?: IDataObject;
escalation_level?: number;
escalation_policy?: IDataObject;
incident_key?: string;
priority?: IDataObject;
resolution?: string;
status?: string;
service?: IDataObject;
title?: string;
type?: string;
urgency?: string;
}
@@ -0,0 +1,127 @@
import type { INodeProperties } from 'n8n-workflow';
export const incidentNoteOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['incidentNote'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a incident note',
action: 'Create an incident note',
},
{
name: 'Get Many',
value: 'getAll',
description: "Get many incident's notes",
action: 'Get many incident notes',
},
],
default: 'create',
},
];
export const incidentNoteFields: INodeProperties[] = [
/* -------------------------------------------------------------------------- */
/* incidentNote:create */
/* -------------------------------------------------------------------------- */
{
displayName: 'Incident ID',
name: 'incidentId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incidentNote'],
operation: ['create'],
},
},
description: 'Unique identifier for the incident',
},
{
displayName: 'Content',
name: 'content',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incidentNote'],
operation: ['create'],
},
},
description: 'The note content',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
placeholder: 'name@email.com',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incidentNote'],
operation: ['create'],
},
},
description: 'The email address of a valid user associated with the account making the request',
},
/* -------------------------------------------------------------------------- */
/* incidentNote:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Incident ID',
name: 'incidentId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['incidentNote'],
operation: ['getAll'],
},
},
description: 'Unique identifier for the incident',
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['incidentNote'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['incidentNote'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'Max number of results to return',
},
];
@@ -0,0 +1,159 @@
import type { INodeProperties } from 'n8n-workflow';
export const logEntryOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['logEntry'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get a log entry',
action: 'Get a log entry',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many log entries',
action: 'Get many log entries',
},
],
default: 'get',
},
];
export const logEntryFields: INodeProperties[] = [
/* -------------------------------------------------------------------------- */
/* logEntry:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Log Entry ID',
name: 'logEntryId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['logEntry'],
operation: ['get'],
},
},
description: 'Unique identifier for the log entry',
},
/* -------------------------------------------------------------------------- */
/* logEntry:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['logEntry'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['logEntry'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'Max number of results to return',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['logEntry'],
operation: ['getAll'],
},
},
options: [
{
displayName: 'Include',
name: 'include',
type: 'multiOptions',
options: [
{
name: 'Channels',
value: 'channels',
},
{
name: 'Incidents',
value: 'incidents',
},
{
name: 'Services',
value: 'services',
},
{
name: 'Teams',
value: 'teams',
},
],
default: [],
description: 'Additional details to include',
},
{
displayName: 'Is Overview',
name: 'isOverview',
type: 'boolean',
default: false,
description:
'Whether to return a subset of log entries that show only the most important changes to the incident',
},
{
displayName: 'Since',
name: 'since',
type: 'dateTime',
default: '',
description:
'The start of the date range over which you want to search. (the limit on date ranges is 6 months).',
},
{
displayName: 'Timezone Name or ID',
name: 'timeZone',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getTimezones',
},
default: '',
description:
'Time zone in which dates in the result will be rendered. If not set dates will return UTC. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
},
{
displayName: 'Until',
name: 'until',
type: 'dateTime',
default: '',
description:
'The end of the date range over which you want to search. (the limit on date ranges is 6 months).',
},
],
},
];
@@ -0,0 +1,29 @@
{
"node": "n8n-nodes-base.pagerDuty",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Communication", "Development"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/pagerduty/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.pagerduty/"
}
],
"generic": [
{
"label": "Learn to Automate Your Factory's Incident Reporting: A Step by Step Guide",
"icon": "🏭",
"url": "https://n8n.io/blog/learn-to-automate-your-factorys-incident-reporting-a-step-by-step-guide/"
},
{
"label": "How to automate every step of an incident response workflow",
"url": "https://n8n.io/blog/creating-custom-incident-response-workflows-with-n8n/"
}
]
}
}
@@ -0,0 +1,472 @@
import { snakeCase } from 'change-case';
import moment from 'moment-timezone';
import type {
IExecuteFunctions,
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
INodePropertyOptions,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
import {
keysToSnakeCase,
pagerDutyApiRequest,
pagerDutyApiRequestAllItems,
} from './GenericFunctions';
import { incidentFields, incidentOperations } from './IncidentDescription';
import type { IIncident } from './IncidentInterface';
import { incidentNoteFields, incidentNoteOperations } from './IncidentNoteDescription';
import { logEntryFields, logEntryOperations } from './LogEntryDescription';
import { userFields, userOperations } from './UserDescription';
export class PagerDuty implements INodeType {
description: INodeTypeDescription = {
displayName: 'PagerDuty',
name: 'pagerDuty',
icon: 'file:pagerDuty.svg',
group: ['output'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume PagerDuty API',
defaults: {
name: 'PagerDuty',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'pagerDutyApi',
required: true,
displayOptions: {
show: {
authentication: ['apiToken'],
},
},
},
{
name: 'pagerDutyOAuth2Api',
required: true,
displayOptions: {
show: {
authentication: ['oAuth2'],
},
},
},
],
properties: [
{
displayName: 'Authentication',
name: 'authentication',
type: 'options',
options: [
{
name: 'API Token',
value: 'apiToken',
},
{
name: 'OAuth2',
value: 'oAuth2',
},
],
default: 'apiToken',
},
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Incident',
value: 'incident',
},
{
name: 'Incident Note',
value: 'incidentNote',
},
{
name: 'Log Entry',
value: 'logEntry',
},
{
name: 'User',
value: 'user',
},
],
default: 'incident',
},
// INCIDENT
...incidentOperations,
...incidentFields,
// INCIDENT NOTE
...incidentNoteOperations,
...incidentNoteFields,
// LOG ENTRY
...logEntryOperations,
...logEntryFields,
// USER
...userOperations,
...userFields,
],
};
methods = {
loadOptions: {
// Get all the available escalation policies to display them to user so that they can
// select them easily
async getEscalationPolicies(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const escalationPolicies = await pagerDutyApiRequestAllItems.call(
this,
'escalation_policies',
'GET',
'/escalation_policies',
);
for (const escalationPolicy of escalationPolicies) {
const escalationPolicyName = escalationPolicy.name;
const escalationPolicyId = escalationPolicy.id;
returnData.push({
name: escalationPolicyName,
value: escalationPolicyId,
});
}
return returnData;
},
// Get all the available priorities to display them to user so that they can
// select them easily
async getPriorities(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const priorities = await pagerDutyApiRequestAllItems.call(
this,
'priorities',
'GET',
'/priorities',
);
for (const priority of priorities) {
const priorityName = priority.name;
const priorityId = priority.id;
const priorityDescription = priority.description;
returnData.push({
name: priorityName,
value: priorityId,
description: priorityDescription,
});
}
return returnData;
},
// Get all the available services to display them to user so that they can
// select them easily
async getServices(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const services = await pagerDutyApiRequestAllItems.call(
this,
'services',
'GET',
'/services',
);
for (const service of services) {
const serviceName = service.name;
const serviceId = service.id;
returnData.push({
name: serviceName,
value: serviceId,
});
}
return returnData;
},
// Get all the timezones to display them to user so that they can
// select them easily
async getTimezones(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
for (const timezone of moment.tz.names()) {
const timezoneName = timezone;
const timezoneId = timezone;
returnData.push({
name: timezoneName,
value: timezoneId,
});
}
return returnData;
},
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: INodeExecutionData[] = [];
const length = items.length;
let responseData;
const qs: IDataObject = {};
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < length; i++) {
try {
if (resource === 'incident') {
//https://api-reference.pagerduty.com/#!/Incidents/post_incidents
if (operation === 'create') {
const title = this.getNodeParameter('title', i) as string;
const serviceId = this.getNodeParameter('serviceId', i) as string;
const email = this.getNodeParameter('email', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
const conferenceBridge = (this.getNodeParameter('conferenceBridgeUi', i) as IDataObject)
.conferenceBridgeValues as IDataObject;
const body: IIncident = {
type: 'incident',
title,
service: {
id: serviceId,
type: 'service_reference',
},
};
if (additionalFields.details) {
body.body = {
type: 'incident_body',
details: additionalFields.details,
};
}
if (additionalFields.priorityId) {
body.priority = {
id: additionalFields.priorityId,
type: 'priority_reference',
};
}
if (additionalFields.escalationPolicyId) {
body.escalation_policy = {
id: additionalFields.escalationPolicyId,
type: 'escalation_policy_reference',
};
}
if (additionalFields.urgency) {
body.urgency = additionalFields.urgency as string;
}
if (additionalFields.incidentKey) {
body.incident_key = additionalFields.incidentKey as string;
}
if (conferenceBridge) {
body.conference_bridge = {
conference_number: conferenceBridge.conferenceNumber,
conference_url: conferenceBridge.conferenceUrl,
};
}
responseData = await pagerDutyApiRequest.call(
this,
'POST',
'/incidents',
{ incident: body },
{},
undefined,
{ from: email },
);
responseData = responseData.incident;
}
//https://api-reference.pagerduty.com/#!/Incidents/get_incidents_id
if (operation === 'get') {
const incidentId = this.getNodeParameter('incidentId', i) as string;
responseData = await pagerDutyApiRequest.call(this, 'GET', `/incidents/${incidentId}`);
responseData = responseData.incident;
}
//https://api-reference.pagerduty.com/#!/Incidents/get_incidents
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', 0);
const options = this.getNodeParameter('options', 0);
if (options.userIds) {
options.userIds = (options.userIds as string).split(',');
}
if (options.teamIds) {
options.teamIds = (options.teamIds as string).split(',');
}
if (options.include) {
options.include = (options.include as string[]).map((e) => snakeCase(e));
}
if (options.sortBy) {
options.sortBy = options.sortBy as string;
}
Object.assign(qs, keysToSnakeCase(options)[0]);
if (returnAll) {
responseData = await pagerDutyApiRequestAllItems.call(
this,
'incidents',
'GET',
'/incidents',
{},
qs,
);
} else {
qs.limit = this.getNodeParameter('limit', 0);
responseData = await pagerDutyApiRequest.call(this, 'GET', '/incidents', {}, qs);
responseData = responseData.incidents;
}
}
//https://api-reference.pagerduty.com/#!/Incidents/put_incidents_id
if (operation === 'update') {
const incidentId = this.getNodeParameter('incidentId', i) as string;
const email = this.getNodeParameter('email', i) as string;
const conferenceBridge = (this.getNodeParameter('conferenceBridgeUi', i) as IDataObject)
.conferenceBridgeValues as IDataObject;
const updateFields = this.getNodeParameter('updateFields', i);
const body: IIncident = {
type: 'incident',
};
if (updateFields.title) {
body.title = updateFields.title as string;
}
if (updateFields.escalationLevel) {
body.escalation_level = updateFields.escalationLevel as number;
}
if (updateFields.details) {
body.body = {
type: 'incident_body',
details: updateFields.details,
};
}
if (updateFields.priorityId) {
body.priority = {
id: updateFields.priorityId,
type: 'priority_reference',
};
}
if (updateFields.escalationPolicyId) {
body.escalation_policy = {
id: updateFields.escalationPolicyId,
type: 'escalation_policy_reference',
};
}
if (updateFields.urgency) {
body.urgency = updateFields.urgency as string;
}
if (updateFields.resolution) {
body.resolution = updateFields.resolution as string;
}
if (updateFields.status) {
body.status = updateFields.status as string;
}
if (conferenceBridge) {
body.conference_bridge = {
conference_number: conferenceBridge.conferenceNumber,
conference_url: conferenceBridge.conferenceUrl,
};
}
responseData = await pagerDutyApiRequest.call(
this,
'PUT',
`/incidents/${incidentId}`,
{ incident: body },
{},
undefined,
{ from: email },
);
responseData = responseData.incident;
}
}
if (resource === 'incidentNote') {
//https://api-reference.pagerduty.com/#!/Incidents/post_incidents_id_notes
if (operation === 'create') {
const incidentId = this.getNodeParameter('incidentId', i) as string;
const content = this.getNodeParameter('content', i) as string;
const email = this.getNodeParameter('email', i) as string;
const body: IDataObject = {
content,
};
responseData = await pagerDutyApiRequest.call(
this,
'POST',
`/incidents/${incidentId}/notes`,
{ note: body },
{},
undefined,
{ from: email },
);
}
//https://api-reference.pagerduty.com/#!/Incidents/get_incidents_id_notes
if (operation === 'getAll') {
const incidentId = this.getNodeParameter('incidentId', i) as string;
const returnAll = this.getNodeParameter('returnAll', 0);
if (returnAll) {
responseData = await pagerDutyApiRequestAllItems.call(
this,
'notes',
'GET',
`/incidents/${incidentId}/notes`,
{},
qs,
);
} else {
qs.limit = this.getNodeParameter('limit', 0);
responseData = await pagerDutyApiRequest.call(
this,
'GET',
`/incidents/${incidentId}/notes`,
{},
qs,
);
responseData = responseData.notes;
}
}
}
if (resource === 'logEntry') {
//https://api-reference.pagerduty.com/#!/Log_Entries/get_log_entries_id
if (operation === 'get') {
const logEntryId = this.getNodeParameter('logEntryId', i) as string;
responseData = await pagerDutyApiRequest.call(
this,
'GET',
`/log_entries/${logEntryId}`,
);
responseData = responseData.log_entry;
}
//https://api-reference.pagerduty.com/#!/Log_Entries/get_log_entries
if (operation === 'getAll') {
const options = this.getNodeParameter('options', i);
Object.assign(qs, options);
keysToSnakeCase(qs);
const returnAll = this.getNodeParameter('returnAll', 0);
if (returnAll) {
responseData = await pagerDutyApiRequestAllItems.call(
this,
'log_entries',
'GET',
'/log_entries',
{},
qs,
);
} else {
qs.limit = this.getNodeParameter('limit', 0);
responseData = await pagerDutyApiRequest.call(this, 'GET', '/log_entries', {}, qs);
responseData = responseData.log_entries;
}
}
}
if (resource === 'user') {
//https://developer.pagerduty.com/api-reference/reference/REST/openapiv3.json/paths/~1users~1%7Bid%7D/get
if (operation === 'get') {
const userId = this.getNodeParameter('userId', i) as string;
responseData = await pagerDutyApiRequest.call(this, 'GET', `/users/${userId}`);
responseData = responseData.user;
}
}
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData: { item: i } },
);
returnData.push(...executionData);
} catch (error) {
if (this.continueOnFail()) {
const executionErrorData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData: { item: i } },
);
returnData.push(...executionErrorData);
continue;
}
throw error;
}
}
return [returnData];
}
}
@@ -0,0 +1,44 @@
import type { INodeProperties } from 'n8n-workflow';
export const userOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['user'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get a user',
action: 'Get a user',
},
],
default: 'get',
},
];
export const userFields: INodeProperties[] = [
/* -------------------------------------------------------------------------- */
/* user:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'User ID',
name: 'userId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['user'],
operation: ['get'],
},
},
description: 'Unique identifier for the user',
},
];
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 66 56"><use xlink:href="#a" x=".5" y=".5"/><symbol id="a" overflow="visible"><path fill="#25c151" fill-rule="nonzero" stroke="none" d="M6.704 54.434H0v-33.65c0-3.455 1.418-5.544 2.604-6.704 2.63-2.58 6.2-2.656 6.782-2.656h10.546c3.765 0 5.93 1.52 7.117 2.8 2.346 2.553 2.372 5.853 2.32 6.73v12.687c0 3.662-1.496 5.828-2.733 6.988-2.553 2.398-5.93 2.45-6.73 2.424H6.704zm13.46-18.102c.36 0 1.367-.103 1.908-.62.413-.387.62-1.083.62-2.1v-13.02c0-.36-.077-1.315-.593-1.857-.5-.516-1.444-.62-2.166-.62h-10.6c-2.63 0-2.63 1.985-2.63 2.656v15.55zM57.296 0H64v33.677c0 3.455-1.418 5.544-2.604 6.704-2.63 2.58-6.2 2.656-6.782 2.656H44.068c-3.765 0-5.93-1.52-7.117-2.8-2.346-2.553-2.372-5.853-2.32-6.73v-12.67c0-3.662 1.496-5.828 2.733-6.988 2.553-2.398 5.93-2.45 6.73-2.424h13.202zm-13.46 18.117c-.36 0-1.367.103-1.908.62-.413.387-.62 1.083-.62 2.1v13.02c0 .36.077 1.315.593 1.857.5.516 1.444.62 2.166.62h10.598c2.656-.026 2.656-2 2.656-2.682V18.117z"/></symbol></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB