{ "kind": "open-flow-workflow", "version": 1, "name": "Create Pipedrive Leads for GitHub Forks", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_2426af938c42f661": { "name": "Receive fork events", "kind": "integration", "config": { "owner": { "kind": "value", "value": "your-github-owner" }, "repo": { "kind": "value", "value": "your-github-repo" }, "events": { "kind": "value", "value": [ "fork" ] }, "insecureSsl": { "kind": "value", "value": false } }, "definition": { "configInputs": [ { "jsonSchema": { "type": "array", "items": { "type": "string", "enum": [ "*", "branch_protection_configuration", "branch_protection_rule", "check_run", "check_suite", "code_scanning_alert", "commit_comment", "create", "custom_property_values", "delete", "dependabot_alert", "deploy_key", "deployment", "deployment_status", "discussion", "discussion_comment", "fork", "gollum", "issue_comment", "issue_dependencies", "issues", "label", "member", "meta", "milestone", "package", "page_build", "project", "project_card", "project_column", "public", "pull_request", "pull_request_review", "pull_request_review_comment", "pull_request_review_thread", "push", "registry_package", "release", "repository", "repository_advisory", "repository_import", "repository_ruleset", "repository_vulnerability_alert", "secret_scanning_alert", "secret_scanning_alert_location", "secret_scanning_scan", "security_and_analysis", "star", "status", "sub_issues", "team_add", "watch", "workflow_job", "workflow_run" ] }, "minItems": 1, "uniqueItems": true }, "nullable": false, "handle": "events" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "insecureSsl", "value": false }, { "jsonSchema": { "type": "string", "pattern": "^[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$" }, "nullable": false, "handle": "owner" }, { "jsonSchema": { "type": "string", "pattern": "^(?!\\.{1,2}$)[a-zA-Z0-9._-]{1,100}$" }, "nullable": false, "handle": "repo" } ], "definitionVersion": 2, "description": "Triggers when selected GitHub webhook events occur in a repository.", "displayName": "Repository Event", "key": "github.on_repo_event", "name": "on_repo_event", "outputs": [ { "jsonSchema": { "type": "object" }, "nullable": false, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "deliveryId" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "event" } ], "provider": "github", "type": "integration", "endpoint": { "body": { "allowArray": false, "allowEmpty": false, "formats": [ "json" ] }, "methods": [ "POST" ], "successStatus": 202 } } }, "n_00f4bb3d2bc1f208": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2426af938c42f661", "output": "body" } ] } }, "name": "Read the fork event", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "body" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "login" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "owner" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "repo" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "url" } ], "name": "Read the fork event", "moduleId": "n_eb021d964e359e5f", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_2d064d000e3e95b6": { "inputs": { "username": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00f4bb3d2bc1f208", "output": "login" } ] } }, "name": "Get the sender profile", "kind": "task", "task": { "inputs": [ { "description": "The username.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The username." }, "nullable": false, "handle": "username" } ], "outputs": [ { "description": "A GitHub user profile.", "jsonSchema": { "allOf": [ { "type": "object", "properties": { "id": { "type": "integer", "description": "The user ID." }, "login": { "type": "string", "description": "The username." }, "avatar_url": { "type": "string", "description": "The avatar URL." }, "html_url": { "type": "string", "description": "The profile URL." }, "type": { "type": "string", "description": "The account type." } }, "required": [ "id", "login" ], "additionalProperties": true, "description": "A GitHub user summary." }, { "type": "object", "properties": { "name": { "type": [ "string", "null" ], "description": "The display name." }, "email": { "type": [ "string", "null" ], "description": "The email address." }, "bio": { "type": [ "string", "null" ], "description": "The bio." }, "company": { "type": [ "string", "null" ], "description": "The company." }, "location": { "type": [ "string", "null" ], "description": "The location." }, "followers": { "type": "integer", "description": "The number of followers." }, "following": { "type": "integer", "description": "The number of users followed." }, "public_repos": { "type": "integer", "description": "The number of public repositories." } }, "additionalProperties": true, "description": "Additional object fields." } ], "description": "A GitHub user profile." }, "nullable": false, "handle": "output" } ], "name": "Get the sender profile", "executor": { "kind": "connector", "action": "github.get_user", "outputMode": "value" } } }, "n_4c3e1093f57228e0": { "inputs": { "user": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2d064d000e3e95b6", "output": "output" } ] } }, "name": "Check the public email", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "allOf": [ { "type": "object", "properties": { "id": { "type": "integer", "description": "The user ID." }, "login": { "type": "string", "description": "The username." }, "avatar_url": { "type": "string", "description": "The avatar URL." }, "html_url": { "type": "string", "description": "The profile URL." }, "type": { "type": "string", "description": "The account type." } }, "required": [ "id", "login" ], "additionalProperties": true, "description": "A GitHub user summary." }, { "type": "object", "properties": { "name": { "type": [ "string", "null" ], "description": "The display name." }, "email": { "type": [ "string", "null" ], "description": "The email address." }, "bio": { "type": [ "string", "null" ], "description": "The bio." }, "company": { "type": [ "string", "null" ], "description": "The company." }, "location": { "type": [ "string", "null" ], "description": "The location." }, "followers": { "type": "integer", "description": "The number of followers." }, "following": { "type": "integer", "description": "The number of users followed." }, "public_repos": { "type": "integer", "description": "The number of public repositories." } }, "additionalProperties": true, "description": "Additional object fields." } ], "description": "A GitHub user profile." }, "nullable": false, "handle": "user" } ], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "available" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "email" } ], "name": "Check the public email", "moduleId": "n_52a72eb9f802b47b", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_d8a81127b4236d0e": { "inputs": {}, "name": "Public email available", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_4c3e1093f57228e0", "output": "available" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_c50dcede50da3d49": { "inputs": { "term": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_4c3e1093f57228e0", "output": "email" } ] }, "fields": { "kind": "value", "value": [ "email" ] }, "exactMatch": { "kind": "value", "value": true }, "limit": { "kind": "value", "value": 100 } }, "name": "Search people by email", "kind": "task", "task": { "inputs": [ { "description": "Search term to send to Pipedrive. Use at least 2 characters unless exactMatch is true.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Search term to send to Pipedrive. Use at least 2 characters unless exactMatch is true." }, "nullable": false, "handle": "term" }, { "description": "Person fields to search through.", "jsonSchema": { "type": "array", "items": { "type": "string", "enum": [ "custom_fields", "email", "notes", "phone", "name" ], "description": "Person search field accepted by Pipedrive." }, "minItems": 1, "description": "Person fields to search through." }, "nullable": true, "handle": "fields", "value": null }, { "description": "Whether Pipedrive should only return case-insensitive exact matches.", "jsonSchema": { "type": "boolean", "description": "Whether Pipedrive should only return case-insensitive exact matches." }, "nullable": true, "handle": "exactMatch", "value": null }, { "description": "Organization ID filter.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "Organization ID filter." }, "nullable": true, "handle": "organizationId", "value": null }, { "description": "Optional fields to include in search results.", "jsonSchema": { "type": "array", "items": { "type": "string", "enum": [ "person.picture" ], "description": "Optional person search field accepted by Pipedrive." }, "minItems": 1, "description": "Optional fields to include in search results." }, "nullable": true, "handle": "includeFields", "value": null }, { "description": "Maximum number of search results to return in one Pipedrive page.", "jsonSchema": { "type": "integer", "minimum": 1, "maximum": 500, "description": "Maximum number of search results to return in one Pipedrive page." }, "nullable": true, "handle": "limit", "value": null }, { "description": "Opaque pagination cursor returned by a previous Pipedrive response.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Opaque pagination cursor returned by a previous Pipedrive response." }, "nullable": true, "handle": "cursor", "value": null } ], "outputs": [ { "description": "Search results returned by Pipedrive for person.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "result_score": { "type": "number", "description": "Search relevance score." }, "item": { "type": "object", "properties": { "id": { "type": "integer", "exclusiveMinimum": 0, "description": "Person ID." }, "type": { "type": "string", "description": "Search item type." }, "name": { "type": "string", "description": "Person name." }, "phones": { "type": "array", "items": { "type": "string", "description": "Matched phone number." }, "description": "Phone numbers included in the search hit." }, "emails": { "type": "array", "items": { "type": "string", "description": "Matched email address." }, "description": "Email addresses included in the search hit." }, "visible_to": { "type": "integer", "description": "Pipedrive visibility flag." }, "owner": { "type": "object", "properties": { "id": { "type": "integer", "exclusiveMinimum": 0, "description": "Owner user ID." } }, "required": [ "id" ], "additionalProperties": true, "description": "Owner reference." }, "organization": { "type": "object", "properties": { "id": { "type": "integer", "exclusiveMinimum": 0, "description": "Organization ID." }, "name": { "type": "string", "description": "Organization name." }, "address": { "type": [ "string", "null" ], "description": "Organization address." } }, "required": [ "id", "name" ], "additionalProperties": true, "description": "Related organization reference." }, "custom_fields": { "type": "array", "items": { "type": "string", "description": "Matched custom field value." }, "description": "Matched custom field values." }, "notes": { "type": "array", "items": { "type": "string", "description": "Matched note snippet." }, "description": "Matched notes." } }, "required": [ "id", "type", "name" ], "additionalProperties": true, "description": "Matched Pipedrive person." } }, "required": [ "result_score", "item" ], "additionalProperties": false, "description": "Pipedrive person search result." }, "description": "Search results returned by Pipedrive for person." }, "nullable": false, "handle": "items" }, { "description": "Cursor for the next page when Pipedrive has more search results.", "jsonSchema": { "type": [ "string", "null" ], "description": "Cursor for the next page when Pipedrive has more search results." }, "nullable": true, "handle": "nextCursor" } ], "name": "Search people by email", "executor": { "kind": "connector", "action": "pipedrive.search_persons" } } }, "n_ac1e078fa198b027": { "inputs": { "items": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c50dcede50da3d49", "output": "items" } ] }, "email": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_4c3e1093f57228e0", "output": "email" } ] }, "owner": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00f4bb3d2bc1f208", "output": "owner" } ] } }, "name": "Use or create people", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "items" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "email" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "owner" } ], "outputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "people" } ], "name": "Use or create people", "moduleId": "n_128647aa7f9dd6f9", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [ { "action": "pipedrive.create_person" } ] } ] } }, "n_71b3cd9fd89ff919": { "inputs": { "people": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ac1e078fa198b027", "output": "people" } ] }, "repo": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00f4bb3d2bc1f208", "output": "repo" } ] }, "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00f4bb3d2bc1f208", "output": "url" } ] }, "previous": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_71b3cd9fd89ff919", "output": "state" } ] } }, "name": "Prepare the next lead", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "people" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "repo" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previous" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "body" } ], "name": "Prepare the next lead", "moduleId": "n_ac9cef7e97f87a03", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_cab55f6f5dbf1cac": { "inputs": {}, "name": "Another person", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_71b3cd9fd89ff919", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_94549e0f844b2704": { "inputs": { "endpoint": { "kind": "value", "value": "/api/v1/leads" }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_71b3cd9fd89ff919", "output": "body" } ] } }, "name": "Create a Pipedrive lead", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "endpoint" }, { "jsonSchema": {}, "nullable": true, "handle": "body" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" }, { "jsonSchema": { "const": "base64" }, "nullable": true, "handle": "bodyEncoding" } ], "name": "Create a Pipedrive lead", "executor": { "providerId": "pipedrive", "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "json", "kind": "connector-proxy" } } }, "n_92bce80b34696c64": { "inputs": { "statusCode": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_94549e0f844b2704", "output": "statusCode" } ] }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_94549e0f844b2704", "output": "body" } ] }, "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00f4bb3d2bc1f208", "output": "url" } ] } }, "name": "Prepare the profile note", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "url" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "body" } ], "name": "Prepare the profile note", "moduleId": "n_eb1fbaec8c7546b6", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_b37d385f73ccc5fa": { "inputs": { "endpoint": { "kind": "value", "value": "/api/v1/notes" }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_92bce80b34696c64", "output": "body" } ] } }, "name": "Add the profile note", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "endpoint" }, { "jsonSchema": {}, "nullable": true, "handle": "body" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" }, { "jsonSchema": { "const": "base64" }, "nullable": true, "handle": "bodyEncoding" } ], "name": "Add the profile note", "executor": { "providerId": "pipedrive", "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "json", "kind": "connector-proxy" } } }, "n_832f4ce302e0c06b": { "inputs": { "statusCode": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b37d385f73ccc5fa", "output": "statusCode" } ] }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b37d385f73ccc5fa", "output": "body" } ] } }, "name": "Check the note result", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": {}, "nullable": true, "handle": "body" } ], "outputs": [], "name": "Check the note result", "moduleId": "n_b7ed1fec0790964b", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } } }, "edges": [ { "source": "n_2426af938c42f661", "target": "n_00f4bb3d2bc1f208" }, { "source": "n_00f4bb3d2bc1f208", "target": "n_2d064d000e3e95b6" }, { "source": "n_2d064d000e3e95b6", "target": "n_4c3e1093f57228e0" }, { "source": "n_4c3e1093f57228e0", "target": "n_d8a81127b4236d0e" }, { "source": "n_d8a81127b4236d0e", "target": "n_c50dcede50da3d49", "sourceHandle": "yes" }, { "source": "n_c50dcede50da3d49", "target": "n_ac1e078fa198b027" }, { "source": "n_ac1e078fa198b027", "target": "n_71b3cd9fd89ff919" }, { "source": "n_71b3cd9fd89ff919", "target": "n_cab55f6f5dbf1cac" }, { "source": "n_cab55f6f5dbf1cac", "target": "n_94549e0f844b2704", "sourceHandle": "yes" }, { "source": "n_94549e0f844b2704", "target": "n_92bce80b34696c64" }, { "source": "n_92bce80b34696c64", "target": "n_b37d385f73ccc5fa" }, { "source": "n_b37d385f73ccc5fa", "target": "n_832f4ce302e0c06b" }, { "source": "n_832f4ce302e0c06b", "target": "n_71b3cd9fd89ff919" } ] } }, "modules": { "n_eb021d964e359e5f": { "name": "Read the fork event", "imports": [], "source": "export default function event({body}) {\n const login=body?.sender?.login,owner=body?.forkee?.owner?.login,repo=body?.repository?.full_name,url=body?.sender?.html_url;\n if([login,owner,repo,url].some(x=>typeof x!=='string'||!x.trim()))throw Error('Fork event is missing sender, repository or profile');\n const parsed=new URL(url);if(parsed.protocol!=='https:'||parsed.hostname!=='github.com'||parsed.username||parsed.password)throw Error('Invalid GitHub profile URL');\n return {login,owner,repo,url};\n}\n" }, "n_52a72eb9f802b47b": { "name": "Check the public email", "imports": [], "source": "export default function email({user}) {\n const value=user?.email;\n if(value==null||value==='')return {available:false,email:'-' };\n if(typeof value!=='string'||!value.trim())throw Error('Invalid public email');\n return {available:true,email:value.trim()};\n}\n" }, "n_128647aa7f9dd6f9": { "name": "Use or create people", "imports": [], "source": "export default async function people({items,email,owner},context) {\n if(!Array.isArray(items))throw Error('Invalid Pipedrive search');\n if(items.length){const people=items.map(({item})=>{if(!Number.isSafeInteger(item?.id)||item.id<1||typeof item.name!=='string'||!item.name)throw Error('Invalid matching person');return {id:item.id,name:item.name};});return {people};}\n const {person}=await context.actions.call('pipedrive.create_person',{name:owner,emails:[{value:email}]});\n if(!Number.isSafeInteger(person?.id)||person.id<1||typeof person.name!=='string'||!person.name)throw Error('Person creation returned no usable person');return {people:[{id:person.id,name:person.name}]};\n}\n" }, "n_ac9cef7e97f87a03": { "name": "Prepare the next lead", "imports": [], "source": "export default function next({people,repo,url,previous}) {\n const index=previous?.index??0;if(index===people.length)return {state:{index},more:false,body:{}};\n const person=people[index];if(!Number.isSafeInteger(person?.id)||typeof person?.name!=='string')throw Error('Invalid person');\n return {state:{index:index+1},more:true,body:{title:`Repo '${repo}' forked by ${person.name}`,person_id:person.id}};\n}\n" }, "n_eb1fbaec8c7546b6": { "name": "Prepare the profile note", "imports": [], "source": "export default function result({statusCode,body,url}) {\n if(statusCode<200||statusCode>=300||body?.success!==true||typeof body?.data?.id!=='string'||!body.data.id)throw Error('Lead creation did not return a valid ID');\n const safe=url.replaceAll('&','&').replaceAll('<','<').replaceAll('>','>').replaceAll('\"','"').replaceAll(\"'\",''');return {body:{lead_id:body.data.id,content:'Github user url: '+safe}};\n}\n" }, "n_b7ed1fec0790964b": { "name": "Check the note result", "imports": [], "source": "export default function({statusCode,body}){if(statusCode<200||statusCode>=300||!body||body.success!==true)throw Error(\"Pipedrive note creation failed\");return {};}" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }