N
n8n Store
Workflow Market
Track n8n Workflow Changes Over Time with Compare Dataset & Google Sheets

Track n8n Workflow Changes Over Time with Compare Dataset & Google Sheets

by jimleuk0 views

説明

Categories

🔧 Engineering

Nodes Used

n8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.ifn8n-nodes-base.n8nn8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.set
Price無料
Views0
最終更新11/28/2025
workflow.json
{
  "meta": {
    "instanceId": "408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "f2bb0773-754c-4535-99c0-14617221f64b",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1100,
        100
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "828cb1c8-f92a-4129-a6eb-4597ea809953",
      "name": "Get Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -100,
        100
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.id }}",
              "lookupColumn": "id"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=drivesdk",
          "cachedResultName": "97. Workflow Template Changes"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "XHvC7jIRR8A2TlUl",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.6,
      "alwaysOutputData": true
    },
    {
      "id": "6511415e-afa9-439c-b417-944c69b2c691",
      "name": "Row Exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        80,
        100
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "45b02cff-5406-4158-bb14-31cadf88b062",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1791d64d-fbb1-4143-8925-f2d3dd15e645",
      "name": "Create New Entry",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        280,
        280
      ],
      "parameters": {
        "columns": {
          "value": {
            "id": "={{ $('Get Values').item.json.id }}",
            "name": "={{ $('Get Values').item.json.name }}",
            "nodes": "={{ $('Get Values').item.json.nodes.toJsonString() }}",
            "status": "={{ $('Get Values').item.json.status }}",
            "history": "={{$now.toISO() }} [info] Initiated",
            "connections": "={{ $('Get Values').item.json.connections.toJsonString() }}",
            "last_updated": "={{ $('Get Values').item.json.updatedAt }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_updated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_updated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "history",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "history",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nodes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "nodes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "connections",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "connections",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": true
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=drivesdk",
          "cachedResultName": "97. Workflow Template Changes"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "XHvC7jIRR8A2TlUl",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "56eacb4e-8c1d-454e-926b-3e91efc23639",
      "name": "Compare Datasets",
      "type": "n8n-nodes-base.compareDatasets",
      "position": [
        -280,
        780
      ],
      "parameters": {
        "options": {},
        "mergeByFields": {
          "values": [
            {
              "field1": "type",
              "field2": "type"
            },
            {
              "field1": "name",
              "field2": "name"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "1357e5ee-e456-4e71-8a84-1fbe22e879bf",
      "name": "Current State",
      "type": "n8n-nodes-base.set",
      "position": [
        780,
        -20
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a0306005-1c90-4e03-999c-0178663ff406",
              "name": "name",
              "type": "string",
              "value": "={{ $('Get Values').item.json.name }}"
            },
            {
              "id": "847207dd-96a1-4d32-b854-d2965e34a44f",
              "name": "nodes",
              "type": "array",
              "value": "={{ $('Get Values').item.json.nodes }}"
            },
            {
              "id": "e44844d9-b224-43c6-90f0-4e740b0da7fb",
              "name": "connections",
              "type": "array",
              "value": "={{ $('Get Values').item.json.connections }}"
            },
            {
              "id": "e230a396-d27c-4604-b682-39217a40581a",
              "name": "status",
              "type": "string",
              "value": "={{ $('Get Values').item.json.active ? 'active' : 'inactive' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6f97fba9-82d1-43b4-a51d-3bf9955a8d60",
      "name": "Previous State",
      "type": "n8n-nodes-base.set",
      "position": [
        600,
        -20
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "98e1e832-ea3c-4bf9-862f-eb6f0c7892a3",
              "name": "name",
              "type": "string",
              "value": "={{ $json.name }}"
            },
            {
              "id": "7594680d-0552-464d-9b2c-4ded8fdc3455",
              "name": "nodes",
              "type": "array",
              "value": "={{ $json.nodes.parseJson() }}"
            },
            {
              "id": "5de5aab3-3236-4d47-88cb-701168aca8b8",
              "name": "connections",
              "type": "array",
              "value": "={{ $json.connections.parseJson() }}"
            },
            {
              "id": "07c50e91-42ba-4fbb-be86-5b999c267541",
              "name": "status",
              "type": "string",
              "value": "={{ $json.status }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d50929da-1948-4283-a19d-4973d9c74acd",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -500,
        100
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "2ec9bffd-4da4-41e5-9bb1-f2e1ace7db17",
      "name": "Added Nodes",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        580
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "added"
      },
      "typeVersion": 1
    },
    {
      "id": "2f07ae8b-fea4-4e01-bfae-0b9a689662bf",
      "name": "Same Nodes",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        720
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "unchanged"
      },
      "typeVersion": 1
    },
    {
      "id": "53e3083c-cf50-4361-bb70-bb6f1498c5b4",
      "name": "Different Nodes",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        880
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "changed"
      },
      "typeVersion": 1
    },
    {
      "id": "e28eb560-0fae-43a4-9e1f-1c8346d18ac0",
      "name": "Removed Nodes",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        1020
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "removed"
      },
      "typeVersion": 1
    },
    {
      "id": "c08719a3-b81a-4ee2-a6b8-d0463f70ccfe",
      "name": "Report Nodes",
      "type": "n8n-nodes-base.set",
      "position": [
        420,
        1000
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{\n{\n  \"nodes\": {\n    \"added_total\": $json.added?.length ?? 0,\n    \"added_names\": $json.added?.map(node =>\n      `${node.name} (${node.type.split('.').last()})`) ?? [],\n    \"removed_total\": $json.removed?.length ?? 0,\n    \"removed_names\": $json.removed?.map(node => `${node.name} (${node.type.split('.').last()})`) ?? []\n  }\n}\n}}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "900b67e3-465e-4e1d-8003-bdb312307569",
      "name": "Compare Datasets1",
      "type": "n8n-nodes-base.compareDatasets",
      "position": [
        -280,
        1420
      ],
      "parameters": {
        "options": {},
        "mergeByFields": {
          "values": [
            {
              "field1": "key",
              "field2": "key"
            },
            {
              "field1": "node",
              "field2": "node"
            },
            {
              "field1": "index",
              "field2": "index"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "63e56c07-510e-4d28-a799-889cf94ef927",
      "name": "Added Connections",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        1220
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "added"
      },
      "typeVersion": 1
    },
    {
      "id": "42e3117e-2539-4667-bc99-263d46526fb4",
      "name": "Same Connections",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        1360
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "unchanged"
      },
      "typeVersion": 1
    },
    {
      "id": "cc09e996-b3af-4436-8eb2-8849745f3f76",
      "name": "Different Connections",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        1520
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "changed"
      },
      "typeVersion": 1
    },
    {
      "id": "658b2c72-8ff7-41c2-b4f9-a09109a408d9",
      "name": "Removed Connections",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -20,
        1660
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "removed"
      },
      "typeVersion": 1
    },
    {
      "id": "ca385cad-e275-4c5a-a880-9ac2ae0f1cf1",
      "name": "Report Connections",
      "type": "n8n-nodes-base.set",
      "position": [
        420,
        1220
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{\n{\n  \"connections\": {\n    \"added_total\": $json.added?.length ?? 0,\n    \"added_names\": $json.added?.map(node => `${node.key} [to] ${node.node}`) ?? [],\n    \"removed_total\": $json.removed?.length ?? 0,\n    \"removed_names\": $json.removed?.map(node => `${node.key} [to] ${node.node}`) ?? [],\n    \n  }\n}\n}}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "331d7764-752d-4b18-9b41-5c5f98997e13",
      "name": "Merge Nodes Diff",
      "type": "n8n-nodes-base.merge",
      "position": [
        200,
        780
      ],
      "parameters": {
        "mode": "combine",
        "options": {
          "includeUnpaired": true
        },
        "combineBy": "combineByPosition",
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "97a3ce94-acbb-40bd-b360-5891c62fbdfa",
      "name": "Merge Connections Diff",
      "type": "n8n-nodes-base.merge",
      "position": [
        200,
        1420
      ],
      "parameters": {
        "mode": "combine",
        "options": {
          "includeUnpaired": true
        },
        "combineBy": "combineByPosition",
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "ffe4301e-ad39-40e0-ae5b-c3ce3ed1cc32",
      "name": "Merge Reports",
      "type": "n8n-nodes-base.merge",
      "position": [
        640,
        1120
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "0999ab7d-8227-4e6e-a08f-9821d806bd8e",
      "name": "Has UpdatedAt Changed?",
      "type": "n8n-nodes-base.if",
      "position": [
        280,
        100
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e91f9db3-228c-47e4-a982-df0f73ebad26",
              "operator": {
                "type": "dateTime",
                "operation": "notEquals"
              },
              "leftValue": "={{ $('Get All Workflows').item.json.updatedAt }}",
              "rightValue": "={{ $json.last_updated }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f37d8fd6-cad6-4504-ae67-7172732b95ad",
      "name": "When Executed by Another Workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -1060,
        1120
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "jobType"
            },
            {
              "name": "data",
              "type": "object"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "c9930943-9348-469c-a500-2e06973b96b1",
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        -860,
        1120
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "95d54b19-77f5-4559-b5a2-8cb3d6a608f5",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.jobType }}",
                    "rightValue": "diff"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "ec179774-ef5c-4e37-8476-ddfa7a32ed8b",
      "name": "Split Conn Previous",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -500,
        1400
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data.previous.connections"
      },
      "typeVersion": 1
    },
    {
      "id": "85ca03c4-8eb1-4477-8249-5f1d2235230f",
      "name": "Split Conn Current",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -500,
        1220
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data.current.connections"
      },
      "typeVersion": 1
    },
    {
      "id": "7d54b755-8402-40b6-8410-2f4010dc0c1a",
      "name": "Split Nodes Current",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -500,
        860
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data.current.nodes"
      },
      "typeVersion": 1
    },
    {
      "id": "2b7f1d6c-04ae-4e96-8004-2b91d94aa7fb",
      "name": "Split Nodes Previous",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -500,
        1020
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data.previous.nodes"
      },
      "typeVersion": 1
    },
    {
      "id": "7885842f-23b4-4963-85b3-ab24a536a645",
      "name": "Calculate Template Diffs",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        960,
        -20
      ],
      "parameters": {
        "mode": "each",
        "options": {
          "waitForSubWorkflow": true
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}"
        },
        "workflowInputs": {
          "value": {
            "data": "={{\n{\n  \"current\": $('Current State').item.json,\n  \"previous\": $('Previous State').item.json,\n}\n}}",
            "jobType": "diff"
          },
          "schema": [
            {
              "id": "jobType",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "jobType",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "data",
              "type": "object",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "data",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "155f0a4f-627a-43b8-824c-929d521dd2b8",
      "name": "Update Entry",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1580,
        -20
      ],
      "parameters": {
        "columns": {
          "value": {
            "id": "={{ $('Get Values').item.json.id }}",
            "name": "={{ $('Get Values').item.json.name }}",
            "nodes": "={{ $('Get Values').item.json.nodes.toJsonString() }}",
            "status": "={{ $('Get Values').item.json.status }}",
            "history": "={{\n$('Current State').item.json.status !== $('Previous State').item.json.status\n  ? `{$now.toISO()} [status] ` + (\n    $('Current State').item.json.status === 'active'\n    ? 'Workflow was activated'\n    : 'Workflow was deactivated'\n  )\n  : ''\n}}\n{{$now.toISO() }} [connections] {{ $json.connections.added_total }} added, {{ $json.connections.removed_total }} removed\n{{$now.toISO() }} [nodes] {{ $json.nodes.added_total }} added, {{ $json.nodes.removed_total }} removed\n{{ $('Has UpdatedAt Changed?').item.json.history }}",
            "summary": "={{\n$('Current State').item.json.status !== $('Previous State').item.json.status\n  ? (\n    $('Current State').item.json.status === 'active'\n    ? 'Workflow was activated'\n    : 'Workflow was deactivated'\n  )\n  : ''\n}}\n{{\n$json.nodes.added_total > 0\n  ? [\n    `The nodes added (${$json.nodes.added_total}) were:`,\n    $json.nodes.added_names.join(', ')\n  ].join(' ')\n  : ''\n}}.\n{{\n$json.nodes.removed_total > 0\n  ? [\n    `The nodes removed (${$json.nodes.removed_total}) were:`,\n    $json.nodes.removed_names.join(', ')\n  ].join(' ')\n  : ''\n}}.\n{{\n$json.connections.added_total > 0\n  ? [\n    `The connections added (${$json.connections.added_total}) were:`,\n    $json.connections.added_names.join(', ')\n  ].join(' ')\n  : ''\n}}\n{{\n$json.connections.removed_total > 0\n  ? [\n    `The connections removed (${$json.connections.removed_total}) were:`,\n    $json.connections.removed_names.join(', ')\n  ].join(' ')\n  : ''\n}}",
            "connections": "={{ $('Get Values').item.json.connections.toJsonString() }}",
            "last_updated": "={{ $('Get Values').item.json.updatedAt }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_updated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_updated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "history",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "history",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nodes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "nodes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "connections",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "connections",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": true
        },
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=drivesdk",
          "cachedResultName": "97. Workflow Template Changes"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "XHvC7jIRR8A2TlUl",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "e16b0e69-5eee-4b51-9a5e-a653833a5d26",
      "name": "Get Values",
      "type": "n8n-nodes-base.set",
      "position": [
        -280,
        100
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0bd0d75d-3a1b-4e50-b496-6d33edebda8b",
              "name": "id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "07f2d234-c5d6-41ab-9198-80b139e898ae",
              "name": "name",
              "type": "string",
              "value": "={{ $json.name }}"
            },
            {
              "id": "2596e1bd-a2d6-4c51-9797-b029ceb57d07",
              "name": "nodes",
              "type": "array",
              "value": "={{ $json.nodes.map(node => ({ name: node.name, type: node.type })) }}"
            },
            {
              "id": "4182dc9c-8d40-438a-b8bb-db2f86632110",
              "name": "connections",
              "type": "array",
              "value": "={{\n(function(connections){\n  return connections\n    .keys()\n    .flatMap(key =>\n      connections[key].keys().map(subkey =>\n        connections[key][subkey].flatMap(node =>\n          node.map(item =>\n            ({ key, node: item.node, index: item.index })\n          )\n        )\n      )\n    )\n})($json.connections)\n}}"
            },
            {
              "id": "82e3cb86-123a-4ae8-9dbe-0f613785feb6",
              "name": "updatedAt",
              "type": "string",
              "value": "={{ $json.updatedAt }}"
            },
            {
              "id": "e98aaa3e-174d-456b-8289-c1d2025b986d",
              "name": "status",
              "type": "string",
              "value": "={{ $json.active ? 'active' : 'inactive' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f98f2311-879c-4cfa-8498-dbd5d063f7a4",
      "name": "set non-update response",
      "type": "n8n-nodes-base.set",
      "position": [
        1600,
        280
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "809ff45c-ff14-4195-b132-353e5cc49803",
              "name": "id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "77252bda-65ce-4e2b-852c-4c9dc7ce457e",
              "name": "is_updated",
              "type": "boolean",
              "value": false
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b02b7552-68d4-40fc-a237-5a5d101a8d37",
      "name": "Set Response",
      "type": "n8n-nodes-base.set",
      "position": [
        1820,
        280
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "99dccb72-bc38-47e9-9607-f7ef2d146293",
              "name": "id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "384725e9-bdc2-405b-8c1c-ab68b7a656f0",
              "name": "is_updated",
              "type": "boolean",
              "value": "={{ $json.is_updated ?? true }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ff36d209-0b29-443f-9dc8-33024ed9fa81",
      "name": "Has Node or Connection Updates?",
      "type": "n8n-nodes-base.if",
      "position": [
        1340,
        -20
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "81db3948-7061-4ef1-a883-498dc03a2ab4",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.nodes.added_total }}",
              "rightValue": 0
            },
            {
              "id": "4aad2fa6-dac1-430e-9f41-1c315cc9aa1c",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.nodes.removed_total }}",
              "rightValue": 0
            },
            {
              "id": "b8f0889d-9b6a-4de6-b82e-e17e7135508d",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.connections.added_total }}",
              "rightValue": 0
            },
            {
              "id": "c6a5ba18-6e40-4ae5-b703-6f985fd49b66",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.connections.removed_total }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "89fbe71d-dd20-4b07-a203-c7ffb77750a7",
      "name": "GSheets Rate Limit",
      "type": "n8n-nodes-base.wait",
      "position": [
        2020,
        280
      ],
      "webhookId": "efe9a371-126f-4d73-9128-04b272222a9b",
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "9994e65f-2825-4ad8-9ce7-bcc9745c6346",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -100
      ],
      "parameters": {
        "color": 7,
        "width": 520,
        "height": 400,
        "content": "## 1. Get Workflows To Track\n[Learn more about the n8n node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.n8n/)\n\nTo start, we'll need the json templates of the workflows that exist in the n8n instance. We can easily get these by using the n8n node. You may want to further filter down workflow depending on which ones you want to track. "
      },
      "typeVersion": 1
    },
    {
      "id": "47202dc8-880d-48e4-b58a-a681d7dc56a2",
      "name": "Get All Workflows",
      "type": "n8n-nodes-base.n8n",
      "position": [
        -880,
        100
      ],
      "parameters": {
        "limit": 25,
        "filters": {
          "activeWorkflows": false
        },
        "returnAll": false,
        "requestOptions": {}
      },
      "credentials": {
        "n8nApi": {
          "id": "5vELmsVPmK4Bkqkg",
          "name": "n8n account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d1c2137f-2ac9-47a9-998d-6e17c8492793",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -620,
        -100
      ],
      "parameters": {
        "color": 7,
        "width": 1080,
        "height": 620,
        "content": "## 2. Create GSheet Entry If Workflow is New\n[Read more about the loop node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches)\n\nNext, we'll need to determine which workflows are currently new vs already being tracked. This is important as we can only compare workflow versions if we have a previous copy of it. If a workflow doesn't have an entry in our sheet then we can presume it's new and no comparison is necessary as of yet."
      },
      "typeVersion": 1
    },
    {
      "id": "d4fa75b8-f1be-4dfd-994e-7458ef945016",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        500,
        -200
      ],
      "parameters": {
        "color": 7,
        "width": 680,
        "height": 380,
        "content": "## 3. Calculate Changes Since Last Update\n[Read more about the Execute Workflow node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow/)\n\nIf a previous version exists, we'll can compare it with the current versions to workout what exactly has changed. Here, I'll pass both versions of the workflow's json to a subworkflow which can compare the two."
      },
      "typeVersion": 1
    },
    {
      "id": "c0044b95-e9ed-40ba-b602-ef7822637773",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1220,
        -200
      ],
      "parameters": {
        "color": 7,
        "width": 580,
        "height": 380,
        "content": "## 5. Update GSheet Entry with Changes\n[Read more about the Google Sheets node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googlesheets)\n\nThe resulting list of changes of the workflow are updated in the Google sheet for review. From here, it's possible to connect messaging and/or notification platforms to alert on changes which may break the business processes or worse!"
      },
      "typeVersion": 1
    },
    {
      "id": "7a83901c-3ed0-41c2-8f81-55d1508d0f94",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        840
      ],
      "parameters": {
        "color": 7,
        "width": 600,
        "height": 220,
        "content": "## 4. Calculate Differences in Nodes & Connections\n[Learn more about the Compare Datasets node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.comparedatasets)\n\nOur comparison focuses on changes between nodes and connections. It does this by running both the previous and current versions of the workflow json through the \"Compare dataset\" node to find the differences. Using this node, we're able to determine how many nodes and/or connections were added or removed."
      },
      "typeVersion": 1
    },
    {
      "id": "49553752-1bba-44d1-ab92-4a4130dfa388",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1660,
        -280
      ],
      "parameters": {
        "width": 420,
        "height": 960,
        "content": "## Try It Out!\n### This n8n template runs daily to track and report on any changes to available workflows on an n8n instance.\n\nUseful if a team is working within a single instance and you want to be notified of what workflows have changed since you last visited them. Another use-case might be monitoring your managed instances for clients and being alerted when changes are made without your knowledge.\n\nSee a sample Gsheet here: [https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=sharing](https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=sharing)\n\n### How it works\n* A scheduled trigger is set to run once a day to review all available workflows.\n* An n8n node imports the workflows as json.\n* The workflows are brought into a loop where each is first checked to see if it exists in the designated google sheet.\n* If not, a new entry is created and skipped.\n* If the workflow has been captured before, then the comparison subworkflow can be executed using the previous and current versions of the workflow json data.\n* The subworkflow uses the compare dataset tool to calculate the changes to nodes and connections for the given workflow.\n* The results are then recorded back to the google sheet for review.\n\n### How to use\n* Start with the n8n node and try to filter by the workflows you're interested in tracking.\n* Set the scheduled trigger interval to match the frequency to suit how often your workflows are being edited.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Switch": {
      "main": [
        [
          {
            "node": "Split Nodes Current",
            "type": "main",
            "index": 0
          },
          {
            "node": "Split Nodes Previous",
            "type": "main",
            "index": 0
          },
          {
            "node": "Split Conn Current",
            "type": "main",
            "index": 0
          },
          {
            "node": "Split Conn Previous",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Row": {
      "main": [
        [
          {
            "node": "Row Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Values": {
      "main": [
        [
          {
            "node": "Get Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Same Nodes": {
      "main": [
        [
          {
            "node": "Merge Nodes Diff",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Added Nodes": {
      "main": [
        [
          {
            "node": "Merge Nodes Diff",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Row Exists?": {
      "main": [
        [
          {
            "node": "Has UpdatedAt Changed?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create New Entry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Report Nodes": {
      "main": [
        [
          {
            "node": "Merge Reports",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Response": {
      "main": [
        [
          {
            "node": "GSheets Rate Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Entry": {
      "main": [
        [
          {
            "node": "Set Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Current State": {
      "main": [
        [
          {
            "node": "Calculate Template Diffs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Removed Nodes": {
      "main": [
        [
          {
            "node": "Merge Nodes Diff",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Previous State": {
      "main": [
        [
          {
            "node": "Current State",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Different Nodes": {
      "main": [
        [
          {
            "node": "Merge Nodes Diff",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Get Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Datasets": {
      "main": [
        [
          {
            "node": "Added Nodes",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Same Nodes",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Different Nodes",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Removed Nodes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create New Entry": {
      "main": [
        [
          {
            "node": "set non-update response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Nodes Diff": {
      "main": [
        [
          {
            "node": "Report Nodes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Same Connections": {
      "main": [
        [
          {
            "node": "Merge Connections Diff",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get All Workflows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Added Connections": {
      "main": [
        [
          {
            "node": "Merge Connections Diff",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Datasets1": {
      "main": [
        [
          {
            "node": "Added Connections",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Same Connections",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Different Connections",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Removed Connections",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get All Workflows": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GSheets Rate Limit": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Report Connections": {
      "main": [
        [
          {
            "node": "Merge Reports",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Split Conn Current": {
      "main": [
        [
          {
            "node": "Compare Datasets1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Removed Connections": {
      "main": [
        [
          {
            "node": "Merge Connections Diff",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Split Conn Previous": {
      "main": [
        [
          {
            "node": "Compare Datasets1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Split Nodes Current": {
      "main": [
        [
          {
            "node": "Compare Datasets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Nodes Previous": {
      "main": [
        [
          {
            "node": "Compare Datasets",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Different Connections": {
      "main": [
        [
          {
            "node": "Merge Connections Diff",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Has UpdatedAt Changed?": {
      "main": [
        [
          {
            "node": "Previous State",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "set non-update response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Connections Diff": {
      "main": [
        [
          {
            "node": "Report Connections",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "set non-update response": {
      "main": [
        [
          {
            "node": "Set Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Template Diffs": {
      "main": [
        [
          {
            "node": "Has Node or Connection Updates?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Node or Connection Updates?": {
      "main": [
        [
          {
            "node": "Update Entry",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "set non-update response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

相关工作流