{
  "id": "NSMCG1Y1qcaShFm8",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automated Workflow Deployment & Git Version Control",
  "tags": [],
  "nodes": [
    {
      "id": "7f391c1b-ad8e-4295-9ca6-f74707073ac2",
      "name": "Update GitHub File",
      "type": "n8n-nodes-base.github",
      "position": [
        -1264,
        -64
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Build File Context').first().json.repoOwner }}"
        },
        "filePath": "={{ $('Build File Context').first().json.filePath }}",
        "resource": "file",
        "operation": "edit",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Build File Context').first().json.repoName }}"
        },
        "fileContent": "={{ $('Build File Context').first().json.workflowJson }}",
        "commitMessage": "={{ $('Build File Context').first().json.commitMessage }}",
        "authentication": "oAuth2",
        "additionalParameters": {
          "branch": {
            "branch": "={{ $('Repo Config').item.json.branch }}"
          }
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "2aed3fe3-c022-4949-98fa-3d70c0ace88c",
      "name": "Get GitHub File SHA",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        -2464,
        64
      ],
      "parameters": {
        "url": "={{ `https://api.github.com/repos/${$('Build File Context').first().json.repoOwner}/${$('Build File Context').first().json.repoName}/contents/${$('Build File Context').first().json.filePath}?ref=${$('Build File Context').first().json.branch}` }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.github+json"
            },
            {
              "name": "X-GitHub-Api-Version",
              "value": "2022-11-28"
            }
          ]
        },
        "nodeCredentialType": "githubOAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "8218134c-724b-4b96-9a49-0f117988e9f5",
      "name": "No Changes Detected",
      "type": "n8n-nodes-base.set",
      "position": [
        -1776,
        160
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "nc1",
              "name": "success",
              "type": "boolean",
              "value": true
            },
            {
              "id": "nc2",
              "name": "message",
              "type": "string",
              "value": "No changes detected. GitHub commit skipped."
            },
            {
              "id": "nc3",
              "name": "workflow_name",
              "type": "string",
              "value": "={{ $('Build File Context').first().json.workflowName }}"
            },
            {
              "id": "nc4",
              "name": "github_path",
              "type": "string",
              "value": "={{ $('Build File Context').first().json.filePath }}"
            },
            {
              "id": "nc5",
              "name": "checked_at",
              "type": "string",
              "value": "={{ new Date().toISOString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7a12968d-610e-42d5-af35-1778525d8c0e",
      "name": "Content Changed?",
      "type": "n8n-nodes-base.if",
      "position": [
        -2016,
        48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-skip",
              "operator": {
                "type": "boolean",
                "operation": "false"
              },
              "leftValue": "={{ $json.skipCommit }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "ccb0eeb6-7d2e-45eb-b727-c85992ac8c02",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        -2240,
        48
      ],
      "parameters": {
        "jsCode": "const currentSha = $('Get GitHub File SHA').first().json.sha;\nconst currentContent = $('Get GitHub File SHA').first().json.content;\nconst incomingContent = Buffer.from(\n  $('Build File Context').first().json.workflowJson\n).toString('base64').replace(/\\n/g, '');\n\nconst isDuplicate = currentSha && \n  currentContent?.replace(/\\n/g, '') === incomingContent;\n\nreturn [{\n  json: {\n    ...$('Get GitHub File SHA').first().json,\n    isDuplicate,\n    skipCommit: isDuplicate\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "eee5cb60-e9cd-4b0a-8136-60fbab5c0d29",
      "name": "DevOps Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -3360,
        64
      ],
      "parameters": {
        "path": "3cef4035-d3af-4cdc-989b-f42eb4a99d63",
        "options": {},
        "formTitle": "\ud83d\ude80 DevOps Control Center",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Workflow ID",
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Environment Action",
              "fieldOptions": {
                "values": [
                  {
                    "option": "\ud83d\udee0\ufe0f Backup to Sandbox Folder"
                  },
                  {
                    "option": "\ud83d\ude80 Promote to Production Folder & Deploy"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Commit Message",
              "requiredField": true
            }
          ]
        },
        "formDescription": "Push workflows to GitHub and deploy to servers."
      },
      "typeVersion": 2
    },
    {
      "id": "392a99da-2c51-405e-b0c6-930cce92820e",
      "name": "Build File Context",
      "type": "n8n-nodes-base.code",
      "position": [
        -2688,
        64
      ],
      "parameters": {
        "jsCode": "const formData = $('DevOps Form').first().json;\nconst workflow = $('Fetch Local Workflow').first().json;\nconst repoConfig = $('Repo Config').first().json;\n\nconst envMap = {\n  '\ud83d\udee0\ufe0f Backup to Sandbox Folder': 'sandbox',\n  '\ud83d\ude80 Promote to Production Folder & Deploy': 'production',\n  'sandbox': 'sandbox',\n  'production': 'production'\n};\n\nconst rawEnv = formData['Environment Action'];\nconst envAction = envMap[rawEnv];\n\nif (!envAction) {\n  throw new Error(`Unrecognised environment: '${rawEnv}'`);\n}\n\nconst safeName = workflow.name\n  .toLowerCase()\n  .replace(/[^a-z0-9_-]/g, '-')\n  .replace(/-+/g, '-')\n  .replace(/^-+|-+$/g, '');\n\nconst filePath = `github-workflow/${safeName}/${envAction}/${safeName}.json`;\n\nconst cleanWorkflow = {\n  name: workflow.name,\n  nodes: workflow.nodes,\n  connections: workflow.connections,\n  settings: workflow.settings,\n  staticData: workflow.staticData ?? null\n};\n\nreturn [{\n  json: {\n    workflow,\n    workflowJson: JSON.stringify(cleanWorkflow, null, 2),\n    workflowName: workflow.name,\n    envAction,\n    filePath,\n    commitMessage: formData['Commit Message'],\n    isProduction: envAction === 'production',\n    repoOwner: repoConfig.repoOwner,\n    repoName: repoConfig.repoName,\n    branch: repoConfig.branch\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "64a33d29-036d-443d-abe7-02139fc4273e",
      "name": "Repo Config",
      "type": "n8n-nodes-base.set",
      "position": [
        -2912,
        64
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "rc1",
              "name": "repoOwner",
              "type": "string",
              "value": "YOUR_GITHUB_USERNAME"
            },
            {
              "id": "rc2",
              "name": "repoName",
              "type": "string",
              "value": "YOUR_REPO_NAME"
            },
            {
              "id": "rc3",
              "name": "branch",
              "type": "string",
              "value": "main"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b07d37d5-1aed-4cc7-819a-26561a710938",
      "name": "Fetch Local Workflow",
      "type": "n8n-nodes-base.n8n",
      "position": [
        -3136,
        64
      ],
      "parameters": {
        "operation": "get",
        "workflowId": "={{ $json['Workflow ID'] }}",
        "requestOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "dbeb988d-f237-4cdb-9a28-384da55a7e86",
      "name": "Is Production Deploy?",
      "type": "n8n-nodes-base.if",
      "position": [
        -816,
        48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-is-prod",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $('Build File Context').first().json.isProduction }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "39395092-b036-4f3e-8ac4-d21decb0999b",
      "name": "GitHub File Exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1488,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-status",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "404"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b1acce8b-6c41-4fd5-adb3-06fac549bb0e",
      "name": "Build Error Response",
      "type": "n8n-nodes-base.set",
      "position": [
        -3104,
        576
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e1",
              "name": "success",
              "type": "boolean",
              "value": false
            },
            {
              "id": "e2",
              "name": "error",
              "type": "string",
              "value": "={{ $json.execution.error.message }}"
            },
            {
              "id": "e3",
              "name": "failed_node",
              "type": "string",
              "value": "={{ $json.execution.lastNodeExecuted }}"
            },
            {
              "id": "e4",
              "name": "execution_id",
              "type": "string",
              "value": "={{ $json.execution.id }}"
            },
            {
              "id": "e5",
              "name": "failed_at",
              "type": "string",
              "value": "={{ new Date().toISOString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "43bc1e49-5096-44b3-83ca-c7f3267008bc",
      "name": "Workflow Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -3328,
        576
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "953d3148-bccb-434e-9c1e-2c4d56bf89c2",
      "name": "Build Success Response",
      "type": "n8n-nodes-base.set",
      "position": [
        912,
        32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "success",
              "type": "boolean",
              "value": true
            },
            {
              "id": "a2",
              "name": "environment",
              "type": "string",
              "value": "={{ $('Build File Context').first().json.envAction }}"
            },
            {
              "id": "a3",
              "name": "workflow_name",
              "type": "string",
              "value": "={{ $('Build File Context').first().json.workflowName }}"
            },
            {
              "id": "a4",
              "name": "github_path",
              "type": "string",
              "value": "={{ $('Build File Context').first().json.filePath }}"
            },
            {
              "id": "a5",
              "name": "prod_workflow_id",
              "type": "string",
              "value": "={{ $json.id ?? $('Resolve Prod Workflow ID').first().json.prodWorkflowId }}"
            },
            {
              "id": "a6",
              "name": "deployed_at",
              "type": "string",
              "value": "={{ new Date().toISOString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8fb73bff-fc02-4891-99f4-dc3d2a35f5a6",
      "name": "Activate on Production",
      "type": "n8n-nodes-base.n8n",
      "position": [
        688,
        32
      ],
      "parameters": {
        "operation": "activate",
        "workflowId": "={{ $json.id }}",
        "requestOptions": {},
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "7d2c0bf2-0a2a-4728-b4b6-1fc003e6a657",
      "name": "Create on Prod Server",
      "type": "n8n-nodes-base.n8n",
      "position": [
        464,
        128
      ],
      "parameters": {
        "operation": "create",
        "requestOptions": {},
        "workflowObject": "={{ JSON.stringify($json.workflowPayload) }}"
      },
      "typeVersion": 1
    },
    {
      "id": "23501075-7ae8-4280-ac4f-36f9f21733ba",
      "name": "Update on Prod Server",
      "type": "n8n-nodes-base.n8n",
      "position": [
        464,
        -64
      ],
      "parameters": {
        "operation": "update",
        "workflowId": "={{ $json.prodWorkflowId }}",
        "requestOptions": {},
        "workflowObject": "={{ JSON.stringify($json.workflowPayload) }}"
      },
      "typeVersion": 1
    },
    {
      "id": "19a7e57a-9db2-4600-b680-facf56791591",
      "name": "Workflow Exists on Prod?",
      "type": "n8n-nodes-base.if",
      "position": [
        240,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-prod-exists",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.exists }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "7b4a23c6-15fe-4c32-8d5e-b50e82153a07",
      "name": "Resolve Prod Workflow ID",
      "type": "n8n-nodes-base.code",
      "position": [
        16,
        32
      ],
      "parameters": {
        "jsCode": "const targetName = $('Build File Context').first().json.workflowName;\nconst workflows = $input.all().map(i => i.json);\nconst existing = workflows.find(w => w.name === targetName);\n\nconst rawPayload = $('Build File Context').first().json.workflow;\n\nconst workflowPayload = {\n  name: rawPayload.name,\n  nodes: rawPayload.nodes,\n  connections: rawPayload.connections,\n  settings: {\n    executionOrder: rawPayload.settings?.executionOrder ?? 'v1'\n  },\n  staticData: rawPayload.staticData ?? null\n};\n\nreturn [{\n  json: {\n    prodWorkflowId: existing ? existing.id : null,\n    exists: !!existing,\n    workflowPayload\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "9d8098e0-5511-4620-b453-c5eb6c189072",
      "name": "Find Workflow on Prod",
      "type": "n8n-nodes-base.n8n",
      "position": [
        -208,
        32
      ],
      "parameters": {
        "filters": {},
        "requestOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "8968ec79-91d0-4a17-9726-4850d19538be",
      "name": "Sandbox Backup Complete",
      "type": "n8n-nodes-base.set",
      "position": [
        -544,
        160
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b1",
              "name": "success",
              "type": "boolean",
              "value": true
            },
            {
              "id": "b2",
              "name": "environment",
              "type": "string",
              "value": "sandbox"
            },
            {
              "id": "b3",
              "name": "workflow_name",
              "type": "string",
              "value": "={{ $('Build File Context').first().json.workflowName }}"
            },
            {
              "id": "b4",
              "name": "github_path",
              "type": "string",
              "value": "={{ $('Build File Context').first().json.filePath }}"
            },
            {
              "id": "b5",
              "name": "message",
              "type": "string",
              "value": "Backed up to sandbox. No prod deploy triggered."
            },
            {
              "id": "b6",
              "name": "backed_up_at",
              "type": "string",
              "value": "={{ new Date().toISOString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a6054eea-38af-4cc8-84c9-168cdcb4d01d",
      "name": "Create GitHub File",
      "type": "n8n-nodes-base.github",
      "position": [
        -1264,
        128
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Repo Config').item.json.repoOwner }}"
        },
        "filePath": "={{ $('Build File Context').first().json.filePath }}",
        "resource": "file",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Repo Config').item.json.repoName }}"
        },
        "fileContent": "={{ $('Build File Context').first().json.workflowJson }}",
        "commitMessage": "={{ $('Build File Context').first().json.commitMessage }}",
        "authentication": "oAuth2",
        "additionalParameters": {
          "branch": {
            "branch": "={{ $('Build File Context').first().json.branch }}"
          }
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "41ef022d-2ac7-4c9f-9594-3e65c954314e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4224,
        -192
      ],
      "parameters": {
        "width": 688,
        "height": 1008,
        "content": "## Automated Workflow Deployment & Git Version Control\n\n### Form-Triggered Workflow Backup & Production Deployment\n\n### How it works\nThis workflow acts as a centralized CI/CD pipeline for your n8n environment, allowing you to back up or deploy workflows directly from a custom form interface:\n\n**The Deployment Pipeline**\n1. Triggered manually via a custom Form that requests the local **Workflow ID**, the desired **Environment Action** (Sandbox or Production), and a **Commit Message**.\n2. Fetches the local workflow definition and cleans the JSON payload (stripping out instance-specific metadata while keeping nodes, connections, and settings).\n3. Checks the target GitHub repository to verify if the file already exists and compares the SHA/content to prevent duplicate or empty commits.\n4. Creates or updates the `[workflow-name].json` file in the GitHub repository under the respective environment folder (`/sandbox/` or `/production/`).\n5. **If Sandboxed:** Safely ends the workflow with a success response after backing up the code.\n6. **If Promoted to Production:** Connects to the designated Production n8n environment, checks if a workflow with the same name already exists, and either creates or updates it.\n7. Automatically activates the promoted workflow on the Production server.\n8. A built-in Error Trigger captures any failures, formats the error details (failed node, execution ID), and builds a standardized error response.\n\n### Setup steps\n- [ ] Connect your GitHub OAuth2 or Personal Access Token credential to the GitHub and HTTP Request nodes.\n- [ ] Connect your n8n API credentials (one for the local environment to fetch workflows, and one for the target Production environment).\n- [ ] Open the **Repo Config** node and set `YOUR_GITHUB_USERNAME` for the `repoOwner` value.\n- [ ] Set `YOUR_REPO_NAME` in the **Repo Config** node.\n- [ ] Set the target `branch` in the **Repo Config** node (defaults to `main`).\n- [ ] Ensure the **Find/Create/Update on Prod Server** nodes are pointing to your actual Production instance if using a multi-server setup.\n\n### Required credentials\n- **GitHub OAuth2 API** (or equivalent Personal Access Token)\n- **n8n API** (Local instance read access)\n- **n8n API** (Production instance write/deploy access)\n\n### Required GitHub API permissions\n`repo` (or fine-grained repository permissions for **Contents** Read & Write access)"
      },
      "typeVersion": 1
    },
    {
      "id": "0816f4a0-66bc-4bc7-9784-f090a7553c80",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3472,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 912,
        "height": 544,
        "content": "### Input & Payload Prep\nCaptures the user request from the form, fetches the local workflow JSON, and builds the deployment configuration."
      },
      "typeVersion": 1
    },
    {
      "id": "4f5643e5-be90-4ad7-8165-94e7cf7b633e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2512,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 928,
        "height": 544,
        "content": "###  GitHub Version Check\nFetches the existing file SHA and compares the content to prevent duplicate or empty commits to the repository."
      },
      "typeVersion": 1
    },
    {
      "id": "010656da-b603-42f4-945e-1d282d0b7c9a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 544,
        "content": "### Production Deploy & Activate\nChecks the target Production server for an existing workflow, updates or creates it, and automatically activates it."
      },
      "typeVersion": 1
    },
    {
      "id": "a30b2e3b-8057-47b3-aaed-b9637a77e42f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1536,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 544,
        "content": "### GitHub Version Control\nCreates or updates the `[workflow-name].json` file in the correct repository folder (`/sandbox` or `/production`)."
      },
      "typeVersion": 1
    },
    {
      "id": "15067849-2af0-4766-b723-05172be245ad",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3472,
        400
      ],
      "parameters": {
        "color": 7,
        "width": 704,
        "height": 416,
        "content": "### Error Handling\nGlobal error catcher that intercepts any node failures and builds a structured, clean error response."
      },
      "typeVersion": 1
    },
    {
      "id": "7afd628b-3b56-430b-8d09-3908fdba1040",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -288,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 1408,
        "height": 544,
        "content": "### Production Deploy & Activate\nChecks the target Production server for an existing workflow, updates or creates it, and automatically activates it."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "3c43ee01-d268-4d97-94f5-06bb6e4468da",
  "connections": {
    "DevOps Form": {
      "main": [
        [
          {
            "node": "Fetch Local Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Repo Config": {
      "main": [
        [
          {
            "node": "Build File Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Content Changed?": {
      "main": [
        [
          {
            "node": "GitHub File Exists?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Changes Detected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build File Context": {
      "main": [
        [
          {
            "node": "Get GitHub File SHA",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Content Changed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create GitHub File": {
      "main": [
        [
          {
            "node": "Is Production Deploy?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update GitHub File": {
      "main": [
        [
          {
            "node": "Is Production Deploy?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get GitHub File SHA": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub File Exists?": {
      "main": [
        [
          {
            "node": "Update GitHub File",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create GitHub File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Local Workflow": {
      "main": [
        [
          {
            "node": "Repo Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create on Prod Server": {
      "main": [
        [
          {
            "node": "Activate on Production",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Workflow on Prod": {
      "main": [
        [
          {
            "node": "Resolve Prod Workflow ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Production Deploy?": {
      "main": [
        [
          {
            "node": "Find Workflow on Prod",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Sandbox Backup Complete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update on Prod Server": {
      "main": [
        [
          {
            "node": "Activate on Production",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Activate on Production": {
      "main": [
        [
          {
            "node": "Build Success Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Error Trigger": {
      "main": [
        [
          {
            "node": "Build Error Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resolve Prod Workflow ID": {
      "main": [
        [
          {
            "node": "Workflow Exists on Prod?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Exists on Prod?": {
      "main": [
        [
          {
            "node": "Update on Prod Server",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create on Prod Server",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}