{ "nodes": [ { "id": "zendesk-ticket-to-github-issue-0", "name": "Get ticket", "type": "n8n-nodes-base.zendesk", "position": [ 380, 480 ], "parameters": { "id": "={{ $(\"Validate the ticket event\").first().json.ticketId }}", "operation": "get" }, "typeVersion": 1 }, { "id": "zendesk-ticket-to-github-issue-1", "name": "IF", "type": "n8n-nodes-base.if", "position": [ 780, 480 ], "parameters": { "conditions": { "string": [ { "value1": "={{ $json.existing ? \"yes\" : \"\" }}", "operation": "isNotEmpty" } ] } }, "typeVersion": 1 }, { "id": "zendesk-ticket-to-github-issue-2", "name": "Update ticket", "type": "n8n-nodes-base.zendesk", "notes": "Update the Zendesk ticket by adding the Jira issue key to the \"Jira Issue Key\" field.", "position": [ 1180, 580 ], "parameters": { "id": "={{ $(\"Validate the ticket event\").first().json.ticketId }}", "operation": "update", "updateFields": { "customFieldsUi": { "customFieldsValues": [ { "id": "={{ $(\"Validate the ticket event\").first().json.fieldId }}", "value": "={{ $json.number }}" } ] } } }, "notesInFlow": true, "typeVersion": 1 }, { "id": "zendesk-ticket-to-github-issue-3", "name": "Determine", "type": "n8n-nodes-base.code", "notes": "if issue was created already in Jira", "position": [ 580, 480 ], "parameters": { "mode": "runOnceForEachItem", "jsCode": "function route({ticket,ticketId,fieldId,comment}) {\n if(ticket?.id!==ticketId||!Array.isArray(ticket?.raw?.custom_fields))throw Error('Ticket ID or custom fields invalid');\n const matches=ticket.raw.custom_fields.filter(x=>x?.id===fieldId);if(matches.length!==1)throw Error('Configured GitHub issue field is absent or duplicated');\n const value=matches[0].value;if(value==null||value===''){if(typeof ticket.subject!=='string'||!ticket.subject.trim())throw Error('Ticket subject is missing');return {existing:false,issueNumber:1,title:ticket.subject,comment:'-'};}\n const text=String(value);if(!/^\\d+$/.test(text)||!Number.isSafeInteger(Number(text))||Number(text)<1)throw Error('Invalid stored GitHub issue number');\n if(!comment.trim())throw Error('A comment is required for an existing issue');return {existing:true,issueNumber:Number(text),title:ticket.subject||'-',comment};\n}\n\nconst r=$(\"Validate the ticket event\").first().json;return {json:route({ticket:{id:$json.id,subject:$json.subject,raw:$json},ticketId:r.ticketId,fieldId:r.fieldId,comment:r.comment})};" }, "notesInFlow": true, "typeVersion": 2 }, { "id": "zendesk-ticket-to-github-issue-4", "name": "Create issue", "type": "n8n-nodes-base.github", "position": [ 980, 580 ], "parameters": { "owner": "={{ $(\"Validate the ticket event\").first().json.owner }}", "title": "={{ $json.title }}", "labels": [], "assignees": [], "repository": "={{ $(\"Validate the ticket event\").first().json.repo }}", "body": "" }, "typeVersion": 1 }, { "id": "zendesk-ticket-to-github-issue-5", "name": "Create comment on existing issue", "type": "n8n-nodes-base.github", "position": [ 980, 380 ], "parameters": { "body": "={{ $(\"Validate the ticket event\").first().json.comment }}", "owner": "={{ $(\"Validate the ticket event\").first().json.owner }}", "operation": "createComment", "repository": "={{ $(\"Validate the ticket event\").first().json.repo }}", "issueNumber": "={{ $json.issueNumber }}" }, "typeVersion": 1 }, { "id": "zendesk-ticket-to-github-issue-6", "name": "On new Zendesk ticket", "type": "n8n-nodes-base.webhook", "position": [ 180, 480 ], "parameters": { "httpMethod": "POST", "path": "zendesk-ticket-to-github-issue", "responseMode": "onReceived", "options": { "responseData": "{}", "responseContentType": "application/json" } }, "typeVersion": 1 }, { "id": "zendesk-ticket-to-github-issue-request", "name": "Validate the ticket event", "type": "n8n-nodes-base.code", "typeVersion": 2, "parameters": { "mode": "runOnceForEachItem", "jsCode": "function request({body,secret,fieldId,owner,repo}) {\n if(typeof secret!=='string'||secret.length<24||body?.secret!==secret)throw Error('Invalid webhook secret');\n const rawId=body?.id;if(!((typeof rawId==='string'&&/^\\d+$/.test(rawId))||typeof rawId==='number'))throw Error('Invalid ticket ID');const ticketId=Number(rawId);if(!Number.isSafeInteger(ticketId)||ticketId<1)throw Error('Invalid ticket ID');\n if(!Number.isSafeInteger(fieldId)||fieldId<1||!owner||owner==='YOUR_GITHUB_OWNER'||!repo||repo==='YOUR_GITHUB_REPO')throw Error('Configure the custom field and GitHub repository');\n const comment=body?.comment;if(comment!=null&&typeof comment!=='string')throw Error('Invalid comment');return {ticketId,comment:comment??'',fieldId,owner,repo};\n}\n\nreturn {json:request({body:$json.body,secret:$env.ZENDESK_GITHUB_SECRET,fieldId:0,owner:\"YOUR_GITHUB_OWNER\",repo:\"YOUR_GITHUB_REPO\"})};" } } ], "connections": { "IF": { "main": [ [ { "node": "Create comment on existing issue", "type": "main", "index": 0 } ], [ { "node": "Create issue", "type": "main", "index": 0 } ] ] }, "Determine": { "main": [ [ { "node": "IF", "type": "main", "index": 0 } ] ] }, "Get ticket": { "main": [ [ { "node": "Determine", "type": "main", "index": 0 } ] ] }, "Create issue": { "main": [ [ { "node": "Update ticket", "type": "main", "index": 0 } ] ] }, "On new Zendesk ticket": { "main": [ [ { "node": "Validate the ticket event", "type": "main", "index": 0 } ] ] }, "Validate the ticket event": { "main": [ [ { "node": "Get ticket", "type": "main", "index": 0 } ] ] } }, "name": "Create or Comment on GitHub Issues from Zendesk", "active": false, "pinData": {} }