N
n8n Store
Workflow Market
Automate SDK Version Drift Detection with GitHub, Notion, and Slack

Automate SDK Version Drift Detection with GitHub, Notion, and Slack

by rahul08โ€ข0 views

Description

Categories

๐Ÿ”ง Engineering

Nodes Used

n8n-nodes-base.ifn8n-nodes-base.setn8n-nodes-base.coden8n-nodes-base.mergen8n-nodes-base.slackn8n-nodes-base.githubn8n-nodes-base.notionn8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNote
PriceKostenlos
Views0
Last Updated11/28/2025
workflow.json
{
  "id": "L9nRhIlKBOKLFzmr",
  "meta": {
    "instanceId": "8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177",
    "templateCredsSetupCompleted": true
  },
  "name": "Automate SDK Version Drift Detection with GitHub, Notion, and Slack",
  "tags": [],
  "nodes": [
    {
      "id": "00c0c0f6-a22d-40e4-bb1a-aec22dc4b1ac",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1712,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 426,
        "height": 544,
        "content": "## ๐ŸŽฏ SDK Release Tracker Workflow\n\n### Purpose\nAutomatically tracks SDK releases from GitHub and monitors if documentation (FAQs) in Notion are kept up-to-date. Sends Slack alerts when documentation is >30 days behind.\n\n### Flow Overview\n1. **Trigger**: GitHub repository event\n2. **Fetch**: Get all releases from repository\n3. **Transform**: Extract release metadata\n4. **Log**: Save to Google Sheets\n5. **Compare**: Match with Notion FAQ updates\n6. **Calculate**: Compute drift (days since last update)\n7. **Alert**: Send Slack notification if overdue\n\n### Requirements\n- GitHub OAuth2 credentials\n- Google Sheets OAuth2 credentials\n- Notion API credentials\n- Slack API credentials\n\n### Setup Note\nReplace the following with your own:\n- Google Sheet ID (2 locations)\n- Notion Database ID\n- Slack Channel ID"
      },
      "typeVersion": 1
    },
    {
      "id": "67181deb-538a-4dc1-bf0b-b7230615b6eb",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1264,
        -112
      ],
      "parameters": {
        "color": 5,
        "width": 311,
        "height": 288,
        "content": "## ๐Ÿ“Œ GitHub Trigger Setup\n\n### Configuration\n- **Event**: Repository events\n- **Monitors**: Any changes to the repository\n- **Triggers on**: Releases, tags, and repository updates\n\n### Setup Steps\n1. Connect your GitHub OAuth2 account\n2. Select target repository\n3. Choose \"repository\" event type\n\nโš ๏ธ **Replace** repository with your own SDK repository"
      },
      "typeVersion": 1
    },
    {
      "id": "61146141-fa2e-46a4-b265-26c83668ea74",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        336
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 335,
        "content": "## ๐Ÿ“ฅ Fetch All Releases\n\n### What It Does\nRetrieves all published releases from the GitHub repository to process latest version information.\n\n### Configuration\n- **Resource**: Release\n- **Operation**: Get All\n- **Return All**: Yes (fetches complete release history)\n\n### Output\nRelease data including tag, name, date, and URL"
      },
      "typeVersion": 1
    },
    {
      "id": "c44c2b70-75d1-4a22-bb38-8466dff09b3d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -752,
        -240
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 392,
        "content": "## ๐Ÿ”„ Transform Release Data\n\n### Purpose\nStructures raw GitHub release data into a clean format for logging and analysis.\n\n### Fields Extracted\n- SDK Name (from repository)\n- Release Tag (version number)\n- Release Title\n- Release Date (ISO format)\n- Release URL\n- Days Since Release (calculated)"
      },
      "typeVersion": 1
    },
    {
      "id": "9200c97d-f9de-4385-a4a9-8b5bfbc7ee41",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        -320
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 374,
        "content": "## ๐Ÿ“Š Log to Google Sheets\n\n### Purpose\nCreates a persistent record of all SDK releases for tracking and reporting.\n\n### Configuration\n- **Operation**: Append (adds new rows)\n- **Mapping**: Auto-map input data\n\nโš ๏ธ **Replace** Sheet ID with your own tracking spreadsheet\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "37807e22-b3e5-4a44-9ef6-8708b0ac0dd2",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        400
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 346,
        "content": "## ๐Ÿ“š Fetch FAQ Data\n\n### Purpose\nRetrieves all FAQ/documentation pages from Notion to compare update dates with releases.\n\n### Configuration\n- **Resource**: Database Page\n- **Operation**: Get All\n- **Return All**: Yes\n\nโš ๏ธ **Replace** Database ID with your Notion FAQ database\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4b8d2255-a740-48df-bd11-301d12b5ea50",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -144,
        304
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 304,
        "content": "## ๐Ÿ”€ Merge Data Streams\n\n### Purpose\nCombines release data (from Sheets) with FAQ data (from Notion) for drift calculation.\n\n\n### Output\nCombined dataset ready for drift analysis"
      },
      "typeVersion": 1
    },
    {
      "id": "0bf5faa2-2f04-4287-b4b8-70e554d450ba",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        -208
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 376,
        "content": "## ๐Ÿงฎ Calculate Documentation Drift\n\n### Purpose\nComputes how many days documentation lags behind SDK releases.\n\n### Logic\n1. For each SDK release:\n   - Get release date\n   - Find corresponding FAQ update date\n   - Calculate days between them\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1bae2d99-fc88-4c53-af1a-5b51e54b2fb2",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        336
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 288,
        "content": "## ๐Ÿ’พ Update Drift Status\n\n### Purpose\nWrites calculated drift metrics back to Google Sheets for reporting.\n\n### Operation\nAppends drift analysis results as new rows\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b365f027-1e5e-4d8b-872a-582cbff5a808",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -128
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 264,
        "content": "## ๐Ÿšฆ Filter Overdue Items\n\n### Purpose\nIdentifies SDKs with documentation >30 days behind for alerting.\n\n### Condition\nOverdue Status = \"OVERDUE\"\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "16d3ce01-b42e-45ed-aa88-94c000fa539e",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        752,
        -160
      ],
      "parameters": {
        "color": 5,
        "width": 264,
        "height": 312,
        "content": "## ๐Ÿ”” Slack Alert\n\n### Purpose\nNotifies team about overdue documentation via Slack.\n\n### Message Format\n๐Ÿšจ SDK Version Drift Alert\n\n**SDK Name** โ†’ X days since FAQ update\nLatest Release: YYYY-MM-DD\n"
      },
      "typeVersion": 1
    },
    {
      "id": "061226de-b13c-4ec9-87bc-5da25a8f7100",
      "name": "Github Trigger",
      "type": "n8n-nodes-base.githubTrigger",
      "position": [
        -1072,
        160
      ],
      "webhookId": "a9cdfd9a-0bb8-4d7d-96b2-2fc9985f48c7",
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "https://github.com/YOUR_ORG"
        },
        "events": [
          "repository"
        ],
        "options": {},
        "repository": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_REPOSITORY_NAME",
          "cachedResultUrl": "https://github.com/YOUR_ORG/YOUR_REPOSITORY_NAME",
          "cachedResultName": "YOUR_REPOSITORY_NAME"
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 1
    },
    {
      "id": "be490392-9de4-49a9-95fb-0e18834e2d29",
      "name": "GitHub Fetch Releases",
      "type": "n8n-nodes-base.github",
      "position": [
        -848,
        160
      ],
      "webhookId": "e56158f5-aca5-4a82-9811-a60e31f265e6",
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.body.repository.owner.html_url }}"
        },
        "resource": "release",
        "operation": "getAll",
        "returnAll": true,
        "repository": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_REPOSITORY_NAME",
          "cachedResultUrl": "https://github.com/YOUR_ORG/YOUR_REPOSITORY_NAME",
          "cachedResultName": "YOUR_REPOSITORY_NAME"
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 1
    },
    {
      "id": "902bd84d-2495-4ff9-bf20-95f41e155a37",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        -624,
        160
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "faa9557a-0057-42e4-a4bb-5b1b93a04992",
              "name": "SDK Name",
              "type": "string",
              "value": "={{ $('Github Trigger').item.json.body.repository.name }}"
            },
            {
              "id": "ad5f6a08-f03f-4f72-b70c-0577eb7573ef",
              "name": "Release Tag",
              "type": "string",
              "value": "={{ $json.tag_name }}"
            },
            {
              "id": "c50e0186-739a-4670-b28e-69ef1dcdc9d3",
              "name": "Release Title",
              "type": "string",
              "value": "={{ $json.name }}"
            },
            {
              "id": "0599a0bc-d822-43dd-92ec-cce8e83c3146",
              "name": "Release Date",
              "type": "string",
              "value": "={{ $json.published_at }}"
            },
            {
              "id": "55a19cd6-460f-4f31-896f-396c18b350b9",
              "name": "Release Url",
              "type": "string",
              "value": "={{ $json.html_url }}"
            },
            {
              "id": "28bf7364-aeef-4c2a-8056-15fa7aad2793",
              "name": "Days Since Release",
              "type": "string",
              "value": "={{ Math.floor((new Date() - new Date($json[\"published_at\"])) / (1000 * 60 * 60 * 24)) }}"
            },
            {
              "id": "fcc21b19-4a8d-467d-ba6f-37df419d7044",
              "name": "Last FAQ Update(Notion)",
              "type": "string",
              "value": ""
            },
            {
              "id": "6a345e0a-bece-440e-bef6-dc3a00ba6a87",
              "name": "Days Since FAQ Update",
              "type": "string",
              "value": ""
            },
            {
              "id": "9789540d-70b8-4cac-9028-09bb9ffc2dc4",
              "name": "Overdue Status",
              "type": "string",
              "value": "Pending"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e8605efa-5f22-450a-a195-e0f119f01865",
      "name": "Google Sheets Log Release Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -400,
        64
      ],
      "parameters": {
        "columns": {
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SHEET_GID",
          "cachedResultName": "SDK Release Tracker"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "SDK Release Tracker"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "768fc3f6-59ba-4255-b500-8f7e47a22c62",
      "name": "Notion Fetch FAQ Data",
      "type": "n8n-nodes-base.notion",
      "position": [
        -400,
        256
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "returnAll": true,
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_NOTION_DATABASE_ID",
          "cachedResultName": "FAQ Database"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "3f79013e-63b0-4722-bb78-91e636d87afa",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        -176,
        160
      ],
      "parameters": {},
      "typeVersion": 3
    },
    {
      "id": "ec6e182c-0184-49ef-a2c9-8c99bc64162f",
      "name": "Function Compute Drift",
      "type": "n8n-nodes-base.code",
      "position": [
        64,
        160
      ],
      "parameters": {
        "jsCode": "// SDK Release Drift Calculator\n// Compares release dates with FAQ update dates to identify documentation lag\n\nconst items = [];\nconst allItems = $input.all();\n\nfor (let i = 0; i < allItems.length; i++) {\n  const item = allItems[i].json;\n  \n  // Process SDK release data from Google Sheets\n  if (item[\"SDK Name\"]) {\n    const sdkName = item[\"SDK Name\"];\n    const releaseDate = new Date(item[\"Release Date\"]);\n    const releaseTag = item[\"Release Tag\"];\n    const releaseUrl = item[\"Release Url\"];\n    const daysSinceRelease = parseInt(item[\"Days Since Release\"]);\n    \n    // Calculate FAQ update drift\n    let faqUpdateDate;\n    let daysSinceFaqUpdate;\n    \n    if (item[\"Last FAQ Update(Notion)\"] && item[\"Last FAQ Update(Notion)\"] !== \"\") {\n      // FAQ has been updated - use that date\n      faqUpdateDate = new Date(item[\"Last FAQ Update(Notion)\"]);\n      daysSinceFaqUpdate = Math.floor((new Date() - faqUpdateDate) / (1000 * 60 * 60 * 24));\n    } else {\n      // No FAQ update recorded - use release date as baseline\n      faqUpdateDate = releaseDate;\n      daysSinceFaqUpdate = daysSinceRelease;\n    }\n    \n    // Determine if documentation is overdue (>30 days)\n    const OVERDUE_THRESHOLD = 30;\n    const isOverdue = daysSinceFaqUpdate > OVERDUE_THRESHOLD;\n    \n    items.push({\n      json: {\n        sdkName: sdkName,\n        latestRelease: releaseTag,\n        releaseDate: item[\"Release Date\"],\n        releaseUrl: releaseUrl,\n        daysSinceRelease: daysSinceRelease,\n        lastFaqUpdate: faqUpdateDate.toISOString(),\n        daysSinceFaqUpdate: daysSinceFaqUpdate,\n        isOverdue: isOverdue,\n        overdueStatus: isOverdue ? \"OVERDUE\" : \"OK\"\n      }\n    });\n  }\n}\n\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "173af21d-e158-4a62-a463-9cf19f2207a7",
      "name": "Google Sheets Update Drift Status",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        288,
        160
      ],
      "parameters": {
        "columns": {
          "value": {
            "SDK Name": "={{ $json.sdkName }}",
            "Release Tag": "={{ $json.latestRelease }}",
            "Release Url": "={{ $json.releaseUrl }}",
            "Release Date": "={{ $json.releaseDate }}",
            "Overdue Status": "={{ $json.overdueStatus }}",
            "Days Since Release": "={{ $json.daysSinceRelease }}",
            "Days Since FAQ Update": "={{ $json.daysSinceFaqUpdate }}",
            "Last FAQ Update(Notion)": "={{ $json.lastFaqUpdate }}"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SHEET_GID",
          "cachedResultName": "SDK Release Tracker"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "SDK Release Tracker"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "f0631846-9832-4827-9469-7b19bab41931",
      "name": "Filter Overdue SDKs",
      "type": "n8n-nodes-base.if",
      "position": [
        512,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "107449cb-3d18-44d4-9eb0-dc12327ef42f",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json['Overdue Status'] }}",
              "rightValue": "OVERDUE"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "21d485f9-e81d-4999-bdbc-7a5bb05d8097",
      "name": "Slack Post Alerts",
      "type": "n8n-nodes-base.slack",
      "position": [
        736,
        160
      ],
      "webhookId": "394999a5-28f2-49e2-9c95-6f9032839311",
      "parameters": {
        "text": "=๐Ÿšจ SDK Version Drift Alert\n\n*{{ $json['SDK Name'] }}* โ†’ {{ $json['Days Since FAQ Update'] }} days since last FAQ update.\n\nLatest Release: {{ $json['Release Date'].split('T')[0] }}\nRelease URL: {{ $json['Release Url'] }}\n\n_Please update documentation in Notion._",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "sdk-alerts"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.2
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "52c620de-ecbf-40c2-a349-f3259a95ed88",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Function Compute Drift",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Google Sheets Log Release Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notion Fetch FAQ Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Github Trigger": {
      "main": [
        [
          {
            "node": "GitHub Fetch Releases",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Overdue SDKs": {
      "main": [
        [
          {
            "node": "Slack Post Alerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub Fetch Releases": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notion Fetch FAQ Data": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Function Compute Drift": {
      "main": [
        [
          {
            "node": "Google Sheets Update Drift Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets Log Release Data": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets Update Drift Status": {
      "main": [
        [
          {
            "node": "Filter Overdue SDKs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

็›ธๅ…ณๅทฅไฝœๆต