AutomationFlowsData & Sheets › Track Sdk Documentation Drift with Github, Notion, Google Sheets, and Slack

Track Sdk Documentation Drift with Github, Notion, Google Sheets, and Slack

ByRahul Joshi @rahul08 on n8n.io

Automatically track SDK releases from GitHub, compare documentation freshness in Notion, and send Slack alerts when docs lag behind. This workflow ensures documentation stays in sync with releases, improves visibility, and reduces version drift across teams. 🚀📚💬 Step 1: Listens…

Event trigger★★★★☆ complexity21 nodesGithub TriggerGitHubGoogle SheetsNotionSlack
Data & Sheets Trigger: Event Nodes: 21 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #10337 — we link there as the canonical source.

This workflow follows the Google Sheets → Notion recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "L9nRhIlKBOKLFzmr",
  "meta": {
    "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": "## \ud83c\udfaf 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": "## \ud83d\udccc 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\u26a0\ufe0f **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": "## \ud83d\udce5 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": "## \ud83d\udd04 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": "## \ud83d\udcca 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\u26a0\ufe0f **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": "## \ud83d\udcda 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\u26a0\ufe0f **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": "## \ud83d\udd00 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": "## \ud83e\uddee 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": "## \ud83d\udcbe 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": "## \ud83d\udea6 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": "## \ud83d\udd14 Slack Alert\n\n### Purpose\nNotifies team about overdue documentation via Slack.\n\n### Message Format\n\ud83d\udea8 SDK Version Drift Alert\n\n**SDK Name** \u2192 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
      ],
      "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
      ],
      "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
      ],
      "parameters": {
        "text": "=\ud83d\udea8 SDK Version Drift Alert\n\n*{{ $json['SDK Name'] }}* \u2192 {{ $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,
  "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
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Automatically track SDK releases from GitHub, compare documentation freshness in Notion, and send Slack alerts when docs lag behind. This workflow ensures documentation stays in sync with releases, improves visibility, and reduces version drift across teams. 🚀📚💬 Step 1: Listens…

Source: https://n8n.io/workflows/10337/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

This workflow triggers when a HubSpot deal stage changes to Closed Won and automatically generates an invoice. It collects deal and contact data, builds a styled invoice, converts it into a PDF, and s

HubSpot Trigger, HTTP Request, Google Sheets +4
Data & Sheets

Generate market research reports from news and competitor sites to Notion and Slack. Uses errorTrigger, httpRequest, notion, googleSheets. Event-driven trigger; 19 nodes.

Error Trigger, HTTP Request, Notion +2
Data & Sheets

Xmind Sales Email v2. Uses gmailTrigger, notion, googleSheets, googleSheetsTrigger. Event-driven trigger; 37 nodes.

Gmail Trigger, Notion, Google Sheets +6
Data & Sheets

This workflow automates end-to-end AI-driven inventory intelligence, transforming Airtable stock data into optimized reorder recommendations, daily operational summaries, and instant Slack alerts. It

Lm Chat Azure Open Ai, Airtable, Google Sheets +6
Data & Sheets

This workflow automatically classifies new Stack Overflow questions by topic, generates structured FAQ content using GPT-4o-mini, logs each entry in Google Sheets, saves formatted FAQs in Notion, and

OpenAI, Error Trigger, Slack +3