Sauvegarde des identifiants sur GitHub

Avancé

Ceci est unDevOpsworkflow d'automatisation du domainecontenant 18 nœuds.Utilise principalement des nœuds comme Set, Code, Cron, Merge, Github. Sauvegarde des identifiants vers GitHub

Prérequis
  • Personal Access Token GitHub

Catégorie

Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "meta": {
    "instanceId": "d6b502dfa4d9dd072cdc5c2bb763558661053f651289291352a84403e01b3d1b",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "4377c764-07f3-4304-8105-d3f009925917",
      "name": "Au clic sur 'exécuter'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        1780,
        520
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "10f6ea70-c2cb-4463-972c-e2fdef3e837a",
      "name": "Note autocollante",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1339.5461279763795,
        900
      ],
      "parameters": {
        "color": 6,
        "width": 2086.845881354743,
        "height": 750.8363163824032,
        "content": "## Subworkflow"
      },
      "typeVersion": 1
    },
    {
      "id": "d22236c2-578c-400b-b3e5-354498620c39",
      "name": "Retour",
      "type": "n8n-nodes-base.set",
      "position": [
        3220,
        1100
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8d513345-6484-431f-afb7-7cf045c90f4f",
              "name": "Done",
              "type": "boolean",
              "value": true
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "943eed85-d4cd-4ec5-b278-d143b0f6bd15",
      "name": "Obtenir le fichier",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2320,
        980
      ],
      "parameters": {
        "url": "={{ $json.download_url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "124ebdd7-c2c1-4fec-89d3-596f034e0fe7",
      "name": "Si fichier trop volumineux",
      "type": "n8n-nodes-base.if",
      "position": [
        2120,
        1000
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "45ce825e-9fa6-430c-8931-9aaf22c42585",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.content }}",
              "rightValue": ""
            },
            {
              "id": "9619a55f-7fb1-4f24-b1a7-7aeb82365806",
              "operator": {
                "type": "string",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $json.error }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "751621b4-4f99-4178-a691-40fc7488874b",
      "name": "Fusionner les éléments",
      "type": "n8n-nodes-base.merge",
      "position": [
        2120,
        1260
      ],
      "parameters": {},
      "typeVersion": 2
    },
    {
      "id": "8892eb02-0e8e-4617-85e6-e6f188361f95",
      "name": "isDiffOrNew",
      "type": "n8n-nodes-base.code",
      "position": [
        2320,
        1260
      ],
      "parameters": {
        "jsCode": "const orderJsonKeys = (jsonObj) => {\n  const ordered = {};\n  Object.keys(jsonObj).sort().forEach(key => {\n    ordered[key] = jsonObj[key];\n  });\n  return ordered;\n}\n\n// Check if file returned with content\nif (Object.keys($input.all()[0].json).includes(\"content\")) {\n  // Decode base64 content and parse JSON\n  const origWorkflow = JSON.parse(Buffer.from($input.all()[0].json.content, 'base64').toString());\n  const n8nWorkflow = $input.all()[1].json;\n  \n  // Order JSON objects\n  const orderedOriginal = orderJsonKeys(origWorkflow);\n  const orderedActual = orderJsonKeys(n8nWorkflow);\n\n  // Determine difference\n  if (JSON.stringify(orderedOriginal) === JSON.stringify(orderedActual)) {\n    $input.all()[0].json.github_status = \"same\";\n  } else {\n    $input.all()[0].json.github_status = \"different\";\n    $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n  }\n  $input.all()[0].json.content_decoded = orderedOriginal;\n// No file returned / new workflow\n} else if (Object.keys($input.all()[0].json).includes(\"data\")) {\n  const origWorkflow = JSON.parse($input.all()[0].json.data);\n  const n8nWorkflow = $input.all()[1].json;\n  \n  // Order JSON objects\n  const orderedOriginal = orderJsonKeys(origWorkflow);\n  const orderedActual = orderJsonKeys(n8nWorkflow);\n\n  // Determine difference\n  if (JSON.stringify(orderedOriginal) === JSON.stringify(orderedActual)) {\n    $input.all()[0].json.github_status = \"same\";\n  } else {\n    $input.all()[0].json.github_status = \"different\";\n    $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n  }\n  $input.all()[0].json.content_decoded = orderedOriginal;\n\n} else {\n  // Order JSON object\n  const n8nWorkflow = $input.all()[1].json;\n  const orderedActual = orderJsonKeys(n8nWorkflow);\n  \n  // Proper formatting\n  $input.all()[0].json.github_status = \"new\";\n  $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n}\n\n// Return items\nreturn $input.all();"
      },
      "typeVersion": 1
    },
    {
      "id": "bfddb2a2-c149-4710-bd77-b368d641114d",
      "name": "Vérifier l'état",
      "type": "n8n-nodes-base.switch",
      "position": [
        2540,
        1260
      ],
      "parameters": {
        "rules": {
          "rules": [
            {
              "value2": "same"
            },
            {
              "output": 1,
              "value2": "different"
            },
            {
              "output": 2,
              "value2": "new"
            }
          ]
        },
        "value1": "={{$json.github_status}}",
        "dataType": "string"
      },
      "typeVersion": 1
    },
    {
      "id": "681e54af-b916-416d-9801-ac38a5882bcf",
      "name": "Fichier identique - Ne rien faire",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2760,
        1100
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "38b2041d-1d56-436f-aa04-79d7241dcc74",
      "name": "Le fichier est différent",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2760,
        1260
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "ae33280d-10d5-4882-be9b-7972394357e1",
      "name": "Le fichier est nouveau",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2760,
        1420
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "bea3995f-9f34-4119-a6cf-20281e70d685",
      "name": "Créer un nouveau fichier",
      "type": "n8n-nodes-base.github",
      "position": [
        2980,
        1420
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.owner }}"
        },
        "filePath": "={{ $('Globals').item.json.repo.path }}{{$('Execute Workflow Trigger').first().json.id}}.json",
        "resource": "file",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.name }}"
        },
        "fileContent": "={{$('isDiffOrNew').item.json[\"n8n_data_stringy\"]}}",
        "commitMessage": "={{$('Execute Workflow Trigger').first().json.name}} ({{$json.github_status}})"
      },
      "credentials": {
        "githubApi": {
          "id": "3mfzXcMjoqNHsujs",
          "name": "GitHub account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d9172af3-55f8-4b99-b462-3e6e718b5a77",
      "name": "Modifier le fichier existant",
      "type": "n8n-nodes-base.github",
      "position": [
        2980,
        1240
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.owner }}"
        },
        "filePath": "={{ $('Globals').item.json.repo.path }}{{$('Execute Workflow Trigger').first().json.id}}.json",
        "resource": "file",
        "operation": "edit",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.name }}"
        },
        "fileContent": "={{$('isDiffOrNew').item.json[\"n8n_data_stringy\"]}}",
        "commitMessage": "={{$('Execute Workflow Trigger').first().json.name}} ({{$json.github_status}})"
      },
      "credentials": {
        "githubApi": {
          "id": "3mfzXcMjoqNHsujs",
          "name": "GitHub account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d9589e32-ed20-46e7-9427-1680c6222406",
      "name": "Boucler sur les éléments",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2380,
        620
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "e1530650-aa76-4ab3-b5bb-cd6b805ea656",
      "name": "Déclencheur planifié",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1780,
        720
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 2
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "79910589-f40f-46fa-a704-eaa65157a17a",
      "name": "Note autocollante 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1340,
        278.28654385738866
      ],
      "parameters": {
        "color": 4,
        "width": 365.19481715599653,
        "height": 596.4810912485963,
        "content": "## Backup to GitHub \nThis workflow will backup all instance credentials to GitHub.\n\nThe files are saved `ID.json` for the filename.\n\n### Setup\nOpen `Globals` node and update the values below 👇\n\n- **repo.owner:** your Github username\n- **repo.name:** the name of your repository\n- **repo.path:** the folder to use within the repository. If it doesn't exist it will be created.\n\n\nIf your username was `john-doe` and your repository was called `n8n-backups` and you wanted the credentials to go into a `credentials` folder you would set:\n\n- repo.owner - john-doe\n- repo.name - n8n-backups\n- repo.path - credentials/\n\n\nThe workflow calls itself using a subworkflow, to help reduce memory usage."
      },
      "typeVersion": 1
    },
    {
      "id": "e16c9874-1a35-41c4-8410-0c42efe17770",
      "name": "Note autocollante 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1740,
        440
      ],
      "parameters": {
        "color": 7,
        "width": 1028.7522287279464,
        "height": 434.88564057365943,
        "content": "## Main workflow loop"
      },
      "typeVersion": 1
    },
    {
      "id": "a1464b91-516a-4fd9-9235-20de50e74cb2",
      "name": "Obtenir les données du fichier",
      "type": "n8n-nodes-base.github",
      "position": [
        1920,
        1000
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.repo.owner }}"
        },
        "filePath": "={{ $json.repo.path }}{{ $('Execute Workflow Trigger').item.json.id }}.json",
        "resource": "file",
        "operation": "get",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.repo.name }}"
        },
        "asBinaryProperty": false,
        "additionalParameters": {}
      },
      "credentials": {
        "githubApi": {
          "id": "3mfzXcMjoqNHsujs",
          "name": "GitHub account"
        }
      },
      "typeVersion": 1,
      "continueOnFail": true,
      "alwaysOutputData": true
    },
    {
      "id": "eb2fe87f-f3af-4215-ac1f-7c2b45e8aff6",
      "name": "Variables globales",
      "type": "n8n-nodes-base.set",
      "position": [
        1720,
        1160
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "6cf546c5-5737-4dbd-851b-17d68e0a3780",
              "name": "repo.owner",
              "type": "string",
              "value": "john-doe"
            },
            {
              "id": "452efa28-2dc6-4ea3-a7a2-c35d100d0382",
              "name": "repo.name",
              "type": "string",
              "value": "n8n-backup"
            },
            {
              "id": "81c4dc54-86bf-4432-a23f-22c7ea831e74",
              "name": "repo.path",
              "type": "string",
              "value": "credentials/"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f4498ab4-1760-4849-9fe1-ecfcd7baa9f3",
      "name": "Exécuter la commande",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        2000,
        620
      ],
      "parameters": {
        "command": "npx n8n export:credentials --all --decrypted"
      },
      "typeVersion": 1
    },
    {
      "id": "d453a000-40ef-43f5-b108-5eb30422d1a3",
      "name": "Formatage JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        2180,
        620
      ],
      "parameters": {
        "jsCode": "// Function to beautify JSON\nfunction beautifyJson(jsonString) {\n  try {\n    // Parse the JSON string\n    const jsonObject = JSON.parse(jsonString);\n\n    // Format the JSON with indentation\n    return jsonObject; // Return the parsed object directly\n  } catch (error) {\n    // Return the error message if JSON is invalid\n    return `Invalid JSON: ${error.message}`;\n  }\n}\n\n// Retrieve the JSON object from the input data\nconst input = $input.all()[0].json;\n\n// Extract the JSON string from the stdout field\nconst jsonString = input.stdout.match(/\\[{.*}\\]/s);\n\n// Check if a valid JSON string is found\nif (!jsonString) {\n  return {\n    json: {\n      error: \"No valid JSON string found in stdout.\"\n    }\n  };\n}\n\n// Beautify the JSON\nconst beautifiedJson = beautifyJson(jsonString[0]);\n\n// Output the beautified JSON, ensuring each entry is in an object with a 'json' key\nconst output = beautifiedJson.map(entry => ({ json: entry }));\n\n// Return the output\nreturn output;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "49dbf875-7345-4241-a7fc-f42e53aef64e",
      "name": "Note autocollante 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1680,
        1060
      ],
      "parameters": {
        "color": 4,
        "width": 150,
        "height": 80,
        "content": "## Edit this node 👇"
      },
      "typeVersion": 1
    },
    {
      "id": "98158f3e-7aca-456b-994c-4c795d31c18c",
      "name": "Exécuter le flux de travail",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        2600,
        620
      ],
      "parameters": {
        "mode": "each",
        "options": {},
        "workflowId": "={{ $workflow.id }}"
      },
      "typeVersion": 1
    },
    {
      "id": "d8c52eb7-bcb0-49e7-bb32-7499b1ca22cd",
      "name": "Déclencheur d'exécution du flux de travail",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        1440,
        1280
      ],
      "parameters": {
        "inputSource": "passthrough"
      },
      "typeVersion": 1.1
    }
  ],
  "pinData": {},
  "connections": {
    "eb2fe87f-f3af-4215-ac1f-7c2b45e8aff6": {
      "main": [
        [
          {
            "node": "a1464b91-516a-4fd9-9235-20de50e74cb2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "943eed85-d4cd-4ec5-b278-d143b0f6bd15": {
      "main": [
        [
          {
            "node": "751621b4-4f99-4178-a691-40fc7488874b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ae33280d-10d5-4882-be9b-7972394357e1": {
      "main": [
        [
          {
            "node": "bea3995f-9f34-4119-a6cf-20281e70d685",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "751621b4-4f99-4178-a691-40fc7488874b": {
      "main": [
        [
          {
            "node": "8892eb02-0e8e-4617-85e6-e6f188361f95",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8892eb02-0e8e-4617-85e6-e6f188361f95": {
      "main": [
        [
          {
            "node": "bfddb2a2-c149-4710-bd77-b368d641114d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "bfddb2a2-c149-4710-bd77-b368d641114d": {
      "main": [
        [
          {
            "node": "681e54af-b916-416d-9801-ac38a5882bcf",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "38b2041d-1d56-436f-aa04-79d7241dcc74",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ae33280d-10d5-4882-be9b-7972394357e1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a1464b91-516a-4fd9-9235-20de50e74cb2": {
      "main": [
        [
          {
            "node": "124ebdd7-c2c1-4fec-89d3-596f034e0fe7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "bea3995f-9f34-4119-a6cf-20281e70d685": {
      "main": [
        [
          {
            "node": "d22236c2-578c-400b-b3e5-354498620c39",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f4498ab4-1760-4849-9fe1-ecfcd7baa9f3": {
      "main": [
        [
          {
            "node": "d453a000-40ef-43f5-b108-5eb30422d1a3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d453a000-40ef-43f5-b108-5eb30422d1a3": {
      "main": [
        [
          {
            "node": "d9589e32-ed20-46e7-9427-1680c6222406",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d9589e32-ed20-46e7-9427-1680c6222406": {
      "main": [
        [],
        [
          {
            "node": "98158f3e-7aca-456b-994c-4c795d31c18c",
            "type": "main",
            "index": 0
          },
          {
            "node": "98158f3e-7aca-456b-994c-4c795d31c18c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "98158f3e-7aca-456b-994c-4c795d31c18c": {
      "main": [
        [
          {
            "node": "d9589e32-ed20-46e7-9427-1680c6222406",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e1530650-aa76-4ab3-b5bb-cd6b805ea656": {
      "main": [
        [
          {
            "node": "f4498ab4-1760-4849-9fe1-ecfcd7baa9f3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "38b2041d-1d56-436f-aa04-79d7241dcc74": {
      "main": [
        [
          {
            "node": "d9172af3-55f8-4b99-b462-3e6e718b5a77",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "124ebdd7-c2c1-4fec-89d3-596f034e0fe7": {
      "main": [
        [
          {
            "node": "943eed85-d4cd-4ec5-b278-d143b0f6bd15",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "751621b4-4f99-4178-a691-40fc7488874b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d9172af3-55f8-4b99-b462-3e6e718b5a77": {
      "main": [
        [
          {
            "node": "d22236c2-578c-400b-b3e5-354498620c39",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4377c764-07f3-4304-8105-d3f009925917": {
      "main": [
        [
          {
            "node": "f4498ab4-1760-4849-9fe1-ecfcd7baa9f3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "681e54af-b916-416d-9801-ac38a5882bcf": {
      "main": [
        [
          {
            "node": "d22236c2-578c-400b-b3e5-354498620c39",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d8c52eb7-bcb0-49e7-bb32-7499b1ca22cd": {
      "main": [
        [
          {
            "node": "eb2fe87f-f3af-4215-ac1f-7c2b45e8aff6",
            "type": "main",
            "index": 0
          },
          {
            "node": "751621b4-4f99-4178-a691-40fc7488874b",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé - DevOps

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds18
Catégorie1
Types de nœuds11
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Auteur
Solomon

Solomon

@solomon

Freelance consultant from Brazil, specializing in automations and data analysis. I work with select clients, addressing their toughest projects. For business inquiries, email me at automations.solomon@gmail.com or message me on Telegram for a faster response.

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34