Asistente de sincronización de la configuración del entorno iOS: .env a Xcode

Intermedio

Este es unDevOpsflujo de automatización del dominio deautomatización que contiene 12 nodos.Utiliza principalmente nodos como Set, Code, Gmail, HttpRequest, GithubTrigger. Automatización de la sincronización de configuración de iOS: .env a Xcode con PR de GitHub y notificaciones por correo

Requisitos previos
  • Cuenta de Google y credenciales de API de Gmail
  • Pueden requerirse credenciales de autenticación para la API de destino
  • Personal Access Token de GitHub

Categoría

Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "zNx6ArX0ZtTTcfqp",
  "meta": {
    "instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
    "templateCredsSetupCompleted": true
  },
  "name": "iOS Environment Config Sync Wizard: .env to Xcode",
  "tags": [],
  "nodes": [
    {
      "id": "252bad23-e84c-4e8b-bb4d-81aba9315782",
      "name": "Verificar Archivos Modificados",
      "type": "n8n-nodes-base.code",
      "position": [
        420,
        280
      ],
      "parameters": {
        "jsCode": "const webhookData = $input.first().json.body;\n\n// Log the entire webhookData for debugging\nconsole.log(webhookData);\n\n//const envFilePath = $node[\"SetConfiguration\"].json[\"envFilePath\"];\n\nconst envFilePath = \n$input.first().json.envFilePath\n// Ensure commits array exists and is not empty\nconst commits = webhookData.commits || [];\nconst changedFiles = commits.flatMap(commit => commit.added.concat(commit.modified, commit.removed));\n\n// Check if the repository exists before accessing full_name\nconst repositoryName = webhookData.repository ? webhookData.repository.full_name : 'Repository not found';\n\n// Check if the .env.staging file was changed\nconst envFileChanged = changedFiles.some(file => file.includes(envFilePath));\n\nreturn [\n  {\n    json: {\n      repository: repositoryName,\n      ref: webhookData.ref,\n      after: webhookData.after,\n      envFileChanged,\n      changedFiles\n    }\n  }\n];\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7cb9824a-13ca-4ffc-9626-cbcf5983ddc4",
      "name": "Realizar Diff de Configuración",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        280
      ],
      "parameters": {
        "jsCode": "// Only proceed if .env.staging was changed\nif (!$input.first().json.envFileChanged) {\n  return [];\n}\n\n// Get configuration values\nconst configFiles = JSON.parse($node[\"SetConfiguration\"].json[\"configFiles\"]);\nconst targetBranch = $node[\"SetConfiguration\"].json[\"targetBranch\"];\nconst cacheInvalidationKeys = JSON.parse($node[\"SetConfiguration\"].json[\"cacheInvalidationKeys\"]);\nconst repository = $input.first().json.repository;\nconst commitSha = $input.first().json.after;\n\n// Simulate diff logic for iOS\nconst envChanges = {\n  \"API_KEY\": \"new-api-key-value\",\n  \"BUNDLE_VERSION\": \"2.0.0\",\n  \"DEBUG_MODE\": \"true\"\n};\n\n// Determine which config files need updates\nconst configUpdates = [];\n\n// Check if cache invalidation is needed\nconst cacheInvalidationNeeded = cacheInvalidationKeys.some(key => envChanges.hasOwnProperty(key));\n\n// For each config file, determine what needs to be updated\nconfigFiles.forEach(file => {\n  if (file === \"Info.plist\") {\n    configUpdates.push({\n      file,\n      changes: [\n        {\n          key: \"CFBundleShortVersionString\",\n          oldValue: \"1.0.0\",\n          newValue: \"2.0.0\"\n        },\n        {\n          key: \"API_KEY\",\n          oldValue: \"old-api-key-value\",\n          newValue: \"new-api-key-value\"\n        }\n      ]\n    });\n  } else if (file === \"Config.xcconfig\") {\n    configUpdates.push({\n      file,\n      changes: [\n        {\n          key: \"API_KEY\",\n          oldValue: \"old-api-key-value\",\n          newValue: \"new-api-key-value\"\n        },\n        {\n          key: \"BUNDLE_VERSION\",\n          oldValue: \"1.0.0\",\n          newValue: \"2.0.0\"\n        }\n      ]\n    });\n  }\n});\n\nreturn [\n  {\n    json: {\n      repository,\n      commitSha,\n      targetBranch,\n      envChanges,\n      configUpdates,\n      cacheInvalidationNeeded,\n      cacheInvalidationKeys\n    }\n  }\n];"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "71c6a15a-acc5-487e-a28f-5ab7d6a06f65",
      "name": "Crear Nombre de Rama",
      "type": "n8n-nodes-base.code",
      "position": [
        860,
        280
      ],
      "parameters": {
        "jsCode": "// Create a unique branch name for the config sync\nconst data = $input.first().json;\nconst timestamp = new Date().toISOString().replace(/[:.]/g, '-');\nconst branchName = `ios-config-sync/${timestamp}`;\n\nreturn [\n  {\n    json: {\n      ...data,\n      branchName\n    }\n  }\n];"
      },
      "typeVersion": 1
    },
    {
      "id": "021ea454-007c-4e35-9396-749be82a454c",
      "name": "Invalidar Caché",
      "type": "n8n-nodes-base.code",
      "position": [
        1740,
        280
      ],
      "parameters": {
        "jsCode": "// Check if cache invalidation is needed\nconst data = $input.first().json;\n\nif (!data.cacheInvalidationNeeded) {\n  return [{ json: { ...data, cacheInvalidated: false } }];\n}\n\n// In a real implementation, you would invalidate the Xcode cache here\n// For iOS, this might involve cleaning derived data or triggering a cache cleanup\n\nreturn [\n  {\n    json: {\n      ...data,\n      cacheInvalidated: true,\n      cacheInvalidationMessage: \"Xcode cache invalidation triggered for keys: \" + data.cacheInvalidationKeys.join(\", \")\n    }\n  }\n];"
      },
      "typeVersion": 1
    },
    {
      "id": "db3f0bf4-59cf-41ff-baed-8dd994a4a9e1",
      "name": "Establecer Configuración",
      "type": "n8n-nodes-base.set",
      "position": [
        200,
        280
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "envFilePath",
              "value": ".env.staging"
            },
            {
              "name": "configFiles",
              "value": "[\"Info.plist\", \"Config.xcconfig\"]"
            },
            {
              "name": "targetBranch",
              "value": "main"
            },
            {
              "name": "cacheInvalidationKeys",
              "value": "[\"API_KEY\", \"BUNDLE_VERSION\", \"ENVIRONMENT\"]"
            },
            {
              "name": "prLabels",
              "value": "[\"config-sync\", \"automated\", \"ios\"]"
            },
            {
              "name": "emailTo",
              "value": "ios-team@example.com"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "8b34ddf0-c670-40c1-b699-b30da3fcc6af",
      "name": "Preparar Archivo y Resultado de Fusión",
      "type": "n8n-nodes-base.code",
      "position": [
        1300,
        280
      ],
      "parameters": {
        "jsCode": "// Prepare file updates for each iOS config file\nconst data = $input.first().json;\n\n// Extract repository name from the URL\n// Check if the URL exists\nconst url = data?.url;\nlet repoName = '';\nlet user = '';\nlet repoFullName = '';\nlet newBranch = '';\n// If the URL exists, extract the repository name and user\nif (url) {\n  const urlParts = url.split(\"/repos/\")[1]?.split(\"/\");\n  \n  if (urlParts && urlParts.length > 1) {\n    user = urlParts[0]; // Get the user (e.g., username)\n    repoName = urlParts[1]; // Get the repository name (e.g., repo_app)\n    repoFullName = `${user}/${repoName}`; // Full repository name (e.g., username/repo_app)\n  }\n}\n\nconst targetBranch = $node[\"SetConfiguration\"].json[\"targetBranch\"];\n\n// Extract the new branch name from the `ref` field\nconst ref = data?.ref;\nif (ref) {\n  // Remove \"refs/heads/\" to get just the branch name\n  newBranch = ref.replace(\"refs/heads/\", \"\");\n}\n\nreturn [\n  {\n    json: {\n      ...data,\n      user,\n      repoName,\n      repoFullName,\n      targetBranch,\n      newBranch\n    }\n  }\n];\n"
      },
      "typeVersion": 1
    },
    {
      "id": "52d9141f-0b0e-45d8-8930-3d535f99d834",
      "name": "Enviar Notificación por Correo",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1960,
        280
      ],
      "webhookId": "7b33ec82-a94f-428d-8be6-31100c30f97f",
      "parameters": {
        "sendTo": "={{ $node[\"SetConfiguration\"].json[\"emailTo\"] }}",
        "message": "=Environment Configuration Sync Completed \\nRepository: {{ $json.head.repo.full_name }}\\nBranch: {{ $('Prepare File and Merge Result').item.json.newBranch }}\\nPR: #{{ $json.number }}\\n\\nSummary:\\n- {{ $json.changed_files }} iOS config files updated\\n- {{ $json.cacheInvalidated ? 'Xcode cache invalidation triggered' : 'No cache invalidation needed' }}\\n\\nChanges Made:\\n{{ $json.configUpdates.map(u => `\\n${u.file}:\\n${u.changes.map(c => `  - ${c.key}: ${c.oldValue} → ${c.newValue}`).join('\\n')}`).join('\\n') }}\\n\\nView PR: https://github.com/{{ $json.head.repo.full_name }}/pull/{{ $json.number }}\\n\\n---\\nThis email was automatically generated by the Environment Config Sync for iOS workflow.",
        "options": {
          "appendAttribution": false
        },
        "subject": "=iOS Config Sync Completed - {{ $json.head.repo.full_name }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "sLXWQuAMcImXHmqA",
          "name": "Gmail account 8"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "b218d17f-8fd4-437e-bf17-418fcd5edda6",
      "name": "Crear PR",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        1520,
        280
      ],
      "parameters": {
        "url": "=https://api.github.com/repos/{{ $json.repoFullName }}/pulls",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"title\": \"Sync iOS Configurations\",\n  \"body\": \"This PR syncs iOS configuration changes.\",\n  \"head\": \"{{ $json.newBranch }}\",\n  \"base\": \"{{ $json.targetBranch }}\",\n  \"maintainer_can_modify\": true\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer ${token}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "githubApi"
      },
      "credentials": {
        "githubApi": {
          "id": "vcwkEYebN1BqWFLe",
          "name": "GitHub account 6"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "a4946753-c20a-49cb-8414-ebb2786b16e1",
      "name": "Crear Rama",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        1080,
        280
      ],
      "parameters": {
        "url": "=https://api.github.com/repos/{{ $json.repository }}/git/refs",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"ref\": \"refs/heads/{{ $json[\"branchName\"] }}\",\n  \"sha\": \"{{ $json[\"commitSha\"] }}\"\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer ${token}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "githubApi"
      },
      "credentials": {
        "githubApi": {
          "id": "vcwkEYebN1BqWFLe",
          "name": "GitHub account 6"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "e36828b0-5520-4840-9864-633cb755511a",
      "name": "Github Push Trigger",
      "type": "n8n-nodes-base.githubTrigger",
      "position": [
        -20,
        280
      ],
      "webhookId": "18e18df2-708c-4497-966c-48181fdb800b",
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "username"
        },
        "events": [
          "push"
        ],
        "options": {
          "insecureSSL": false
        },
        "repository": {
          "__rl": true,
          "mode": "list",
          "value": "repo_app",
          "cachedResultUrl": "",
          "cachedResultName": "repo_app"
        }
      },
      "credentials": {
        "githubApi": {
          "id": "vcwkEYebN1BqWFLe",
          "name": "GitHub account 6"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7079fb26-5b6a-448e-8815-ab39231a2f8e",
      "name": "Nota Adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        660
      ],
      "parameters": {
        "width": 2400,
        "height": 2120,
        "content": "## Description\n\n### 1. Github Push Trigger\n- Purpose: Watches for push events on the username/repo repository.\n- What it does: When a commit is pushed, it captures details such as repository name, branch (ref), commit SHA (after), and changed files.\n- Key Output: Provides raw push payload data that other nodes consume for further processing.\n\n---\n\n### 2. SetConfiguration and Customisation\n- Purpose: Defines configurable parameters for the workflow.\n- What it does:\n- Specifies the environment file to monitor (.env.staging).\n- Lists config files to update (Info.plist, Config.xcconfig).\n- Sets the target branch (main).\n- Declares cache invalidation keys (API_KEY, BUNDLE_VERSION, ENVIRONMENT).\n- Adds PR labels (config-sync, automated, ios).\n- Configures email notification recipient (eg: ios-team@example.com).\n- Key Output: Passes configuration values downstream for diffing and PR creation.\n\n---\n\n### 3. Check Changed Files\n- Purpose: Detects if .env.staging was modified in the latest push.\n- What it does:\n- Parses commit payload.\n- Flattens all added/modified/removed files.\n- Checks whether .env.staging exists in the changed files.\n- Key Output: Returns envFileChanged = true/false plus the repository and commit details.\n\n---\n\n### 4. Perform Config Diff\n- Purpose: Analyzes differences between .env.staging and iOS configuration files.\n- What it does:\n- Extracts simulated environment changes (e.g., API_KEY, BUNDLE_VERSION).\n- Prepares configUpdates array describing old → new values for each file.\n- Determines if cache invalidation is required (based on keys).\n- Key Output: Provides structured diff results and flags whether cache invalidation is needed.\n\n---\n\n### 5. Create Branch Name\n- Purpose: Generates a unique branch name for the configuration changes.\n- What it does: Appends a timestamp to ios-config-sync/ (e.g., ios-config-sync/2025-09-01T12-00-00).\n- Key Output: New branch name (branchName) to be created in GitHub.\n\n---\n\n### 6. Create Branch\n- Purpose: Creates a new branch in the repository.\n- What it does: Calls GitHub API to create a reference (refs/heads/branchName) from the latest commit SHA.\n- Key Output: Confirmation of branch creation for downstream file updates.\n\n---\n\n### 7. Prepare File and Merge Result\n- Purpose: Prepares repository details for file updates and PR creation.\n- What it does:\n- Extracts user, repoName, and repoFullName from the repository URL.\n- Determines newBranch name from ref.\n- Prepares a merged JSON object with config updates and metadata.\n- Key Output: Supplies enriched repository details for PR step.\n\n---\n\n### 8. Create PR\n- Purpose: Opens a pull request in GitHub with the config changes.\n- What it does:\n- Uses GitHub API to create PR with title “Sync iOS Configurations”.\n- Sets head = newBranch, base = main.\n- Attaches PR labels.\n- Key Output: Returns PR number (prNumber) and metadata for notifications.\n\n---\n\n### 9. Invalidate Cache\n- Purpose: Triggers Xcode build cache invalidation if required.\n- What it does:\n- Checks cacheInvalidationNeeded.\n- If true, marks cache as invalidated and logs message (e.g., “Xcode cache invalidation triggered for keys: API_KEY, BUNDLE_VERSION”).\n- Key Output: Adds cacheInvalidated status and message to workflow data.\n\n---\n\n### 10. Send Email Notification\n- Purpose: Notifies stakeholders of completed config sync.\n- What it does:\n- Sends Gmail notification to the configured recipient.\n- Includes repository name, branch, PR number, number of updated config files, cache invalidation status, and detailed change log.\n- Adds GitHub PR link for quick access.\n- Key Output: Final communication to confirm sync completion.\n\n---"
      },
      "typeVersion": 1
    },
    {
      "id": "d8620a5d-87e5-4174-978e-bbd37bce0a50",
      "name": "Nota Adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        120
      ],
      "parameters": {
        "width": 2400,
        "height": 440,
        "content": "## iOS Environment Config Sync Wizard: .env to Xcode"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {
    "Github Push Trigger": [
      {
        "json": {
          "body": {
            "ref": "refs/heads/develop",
            "after": "e592287f68b64ddd754dd0f64aedd84f37a270ba",
            "before": "0000000000000000000000000000000000000000",
            "forced": false,
            "pusher": {
              "name": "username",
              "email": "151736888+username@users.noreply.github.com"
            },
            "sender": {
              "id": 151736888,
              "url": "https://api.github.com/users/username",
              "type": "User",
              "login": "username",
              "node_id": "U_kgDOCQtSOA",
              "html_url": "https://github.com/username",
              "gists_url": "https://api.github.com/users/username/gists{/gist_id}",
              "repos_url": "https://api.github.com/users/username/repos",
              "avatar_url": "https://avatars.githubusercontent.com/u/151736888?v=4",
              "events_url": "https://api.github.com/users/username/events{/privacy}",
              "site_admin": false,
              "gravatar_id": "",
              "starred_url": "https://api.github.com/users/username/starred{/owner}{/repo}",
              "followers_url": "https://api.github.com/users/username/followers",
              "following_url": "https://api.github.com/users/username/following{/other_user}",
              "user_view_type": "public",
              "organizations_url": "https://api.github.com/users/username/orgs",
              "subscriptions_url": "https://api.github.com/users/username/subscriptions",
              "received_events_url": "https://api.github.com/users/username/received_events"
            },
            "commits": [
              {
                "id": "e592287f68b64ddd754dd0f64aedd84f37a270ba",
                "url": "",
                "added": [],
                "author": {
                  "name": "username",
                  "email": "username@example.com",
                  "username": "username"
                },
                "message": "change3",
                "removed": [],
                "tree_id": "6e0f7c23e352216f6eac41c17d4f87c76d55dcd5",
                "distinct": true,
                "modified": [
                  "",
                  "n8n_flow_app/.env.staging"
                ],
                "committer": {
                  "name": "username",
                  "email": "username@example.com",
                  "username": "username"
                },
                "timestamp": "2025-08-30T19:58:10+05:30"
              }
            ],
            "compare": "",
            "created": true,
            "deleted": false,
            "base_ref": null,
            "repository": {
              "id": 1040155358,
              "url": "https://api.github.com/repos/username/repo_app",
              "fork": false,
              "name": "repo_app",
              "size": 31,
              "forks": 0,
              "owner": {
                "id": 151736888,
                "url": "https://api.github.com/users/username",
                "name": "username",
                "type": "User",
                "email": "151736888+username@users.noreply.github.com",
                "login": "username",
                "node_id": "U_kgDOCQtSOA",
                "html_url": "https://github.com/username",
                "gists_url": "https://api.github.com/users/username/gists{/gist_id}",
                "repos_url": "https://api.github.com/users/username/repos",
                "avatar_url": "https://avatars.githubusercontent.com/u/151736888?v=4",
                "events_url": "https://api.github.com/users/username/events{/privacy}",
                "site_admin": false,
                "gravatar_id": "",
                "starred_url": "https://api.github.com/users/username/starred{/owner}{/repo}",
                "followers_url": "https://api.github.com/users/username/followers",
                "following_url": "https://api.github.com/users/username/following{/other_user}",
                "user_view_type": "public",
                "organizations_url": "https://api.github.com/users/username/orgs",
                "subscriptions_url": "https://api.github.com/users/username/subscriptions",
                "received_events_url": "https://api.github.com/users/username/received_events"
              },
              "topics": [],
              "git_url": "git://github.com/username/repo_app.git",
              "license": null,
              "node_id": "R_kgDOPf-C3g",
              "private": false,
              "ssh_url": "git@github.com:username/repo_app.git",
              "svn_url": "https://github.com/username/repo_app",
              "archived": false,
              "disabled": false,
              "has_wiki": true,
              "homepage": null,
              "html_url": "https://github.com/username/repo_app",
              "keys_url": "https://api.github.com/repos/username/repo_app/keys{/key_id}",
              "language": "Swift",
              "tags_url": "https://api.github.com/repos/username/repo_app/tags",
              "watchers": 0,
              "blobs_url": "https://api.github.com/repos/username/repo_app/git/blobs{/sha}",
              "clone_url": "https://github.com/username/repo_app.git",
              "forks_url": "https://api.github.com/repos/username/repo_app/forks",
              "full_name": "username/repo_app",
              "has_pages": false,
              "hooks_url": "https://api.github.com/repos/username/repo_app/hooks",
              "pulls_url": "https://api.github.com/repos/username/repo_app/pulls{/number}",
              "pushed_at": 1756564260,
              "teams_url": "https://api.github.com/repos/username/repo_app/teams",
              "trees_url": "https://api.github.com/repos/username/repo_app/git/trees{/sha}",
              "created_at": 1755527836,
              "events_url": "https://api.github.com/repos/username/repo_app/events",
              "has_issues": true,
              "issues_url": "https://api.github.com/repos/username/repo_app/issues{/number}",
              "labels_url": "https://api.github.com/repos/username/repo_app/labels{/name}",
              "merges_url": "https://api.github.com/repos/username/repo_app/merges",
              "mirror_url": null,
              "stargazers": 0,
              "updated_at": "2025-08-30T10:36:42Z",
              "visibility": "public",
              "archive_url": "https://api.github.com/repos/username/repo_app/{archive_format}{/ref}",
              "commits_url": "https://api.github.com/repos/username/repo_app/commits{/sha}",
              "compare_url": "https://api.github.com/repos/username/repo_app/compare/{base}...{head}",
              "description": "n8n work flow ",
              "forks_count": 0,
              "is_template": false,
              "open_issues": 0,
              "branches_url": "https://api.github.com/repos/username/repo_app/branches{/branch}",
              "comments_url": "https://api.github.com/repos/username/repo_app/comments{/number}",
              "contents_url": "https://api.github.com/repos/username/repo_app/contents/{+path}",
              "git_refs_url": "https://api.github.com/repos/username/repo_app/git/refs{/sha}",
              "git_tags_url": "https://api.github.com/repos/username/repo_app/git/tags{/sha}",
              "has_projects": true,
              "releases_url": "https://api.github.com/repos/username/repo_app/releases{/id}",
              "statuses_url": "https://api.github.com/repos/username/repo_app/statuses/{sha}",
              "allow_forking": true,
              "assignees_url": "https://api.github.com/repos/username/repo_app/assignees{/user}",
              "downloads_url": "https://api.github.com/repos/username/repo_app/downloads",
              "has_downloads": true,
              "languages_url": "https://api.github.com/repos/username/repo_app/languages",
              "master_branch": "main",
              "default_branch": "main",
              "milestones_url": "https://api.github.com/repos/username/repo_app/milestones{/number}",
              "stargazers_url": "https://api.github.com/repos/username/repo_app/stargazers",
              "watchers_count": 0,
              "deployments_url": "https://api.github.com/repos/username/repo_app/deployments",
              "git_commits_url": "https://api.github.com/repos/username/repo_app/git/commits{/sha}",
              "has_discussions": false,
              "subscribers_url": "https://api.github.com/repos/username/repo_app/subscribers",
              "contributors_url": "https://api.github.com/repos/username/repo_app/contributors",
              "issue_events_url": "https://api.github.com/repos/username/repo_app/issues/events{/number}",
              "stargazers_count": 0,
              "subscription_url": "https://api.github.com/repos/username/repo_app/subscription",
              "collaborators_url": "https://api.github.com/repos/username/repo_app/collaborators{/collaborator}",
              "issue_comment_url": "https://api.github.com/repos/username/repo_app/issues/comments{/number}",
              "notifications_url": "https://api.github.com/repos/username/repo_app/notifications{?since,all,participating}",
              "open_issues_count": 0,
              "web_commit_signoff_required": false
            },
            "head_commit": {
              "id": "e592287f68b64ddd754dd0f64aedd84f37a270ba",
              "url": "",
              "added": [],
              "author": {
                "name": "username",
                "email": "username@example.com",
                "username": "username"
              },
              "message": "change3",
              "removed": [],
              "tree_id": "6e0f7c23e352216f6eac41c17d4f87c76d55dcd5",
              "distinct": true,
              "modified": [
                "",
                "n8n_flow_app/.env.staging"
              ],
              "committer": {
                "name": "username",
                "email": "username@example.com",
                "username": "username"
              },
              "timestamp": "2025-08-30T19:58:10+05:30"
            }
          },
          "query": {},
          "headers": {
            "host": "domain.app.n8n.cloud",
            "accept": "*/*",
            "cf-ray": "9774fd47659dd6f7-IAD",
            "cdn-loop": "cloudflare; loops=1; subreqs=1",
            "cf-ew-via": "15",
            "cf-worker": "n8n.cloud",
            "x-real-ip": "140.82.115.102",
            "cf-visitor": "{\"scheme\":\"https\"}",
            "user-agent": "GitHub-Hookshot/bebe1c7",
            "cf-ipcountry": "US",
            "content-type": "application/json",
            "x-is-trusted": "yes",
            "content-length": "7278",
            "x-github-event": "push",
            "accept-encoding": "gzip, br",
            "x-forwarded-for": "140.82.115.102, 172.71.194.43",
            "cf-connecting-ip": "140.82.115.102",
            "x-forwarded-host": "domain.app.n8n.cloud",
            "x-forwarded-port": "443",
            "x-github-hook-id": "566851828",
            "x-forwarded-proto": "https",
            "x-github-delivery": "f3435bd4-85ad-11f0-824f-61363511cd42",
            "x-forwarded-server": "traefik-prod-users-gwc-84-57fcbd49bc-g4r2w",
            "x-github-hook-installation-target-id": "1040155358",
            "x-github-hook-installation-target-type": "repository"
          }
        }
      }
    ]
  },
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f44fd78d-b44c-4689-adf7-f576535c6db5",
  "connections": {
    "b218d17f-8fd4-437e-bf17-418fcd5edda6": {
      "main": [
        [
          {
            "node": "021ea454-007c-4e35-9396-749be82a454c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a4946753-c20a-49cb-8414-ebb2786b16e1": {
      "main": [
        [
          {
            "node": "8b34ddf0-c670-40c1-b699-b30da3fcc6af",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "021ea454-007c-4e35-9396-749be82a454c": {
      "main": [
        [
          {
            "node": "52d9141f-0b0e-45d8-8930-3d535f99d834",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "db3f0bf4-59cf-41ff-baed-8dd994a4a9e1": {
      "main": [
        [
          {
            "node": "252bad23-e84c-4e8b-bb4d-81aba9315782",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "71c6a15a-acc5-487e-a28f-5ab7d6a06f65": {
      "main": [
        [
          {
            "node": "a4946753-c20a-49cb-8414-ebb2786b16e1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "252bad23-e84c-4e8b-bb4d-81aba9315782": {
      "main": [
        [
          {
            "node": "7cb9824a-13ca-4ffc-9626-cbcf5983ddc4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e36828b0-5520-4840-9864-633cb755511a": {
      "main": [
        [
          {
            "node": "db3f0bf4-59cf-41ff-baed-8dd994a4a9e1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7cb9824a-13ca-4ffc-9626-cbcf5983ddc4": {
      "main": [
        [
          {
            "node": "71c6a15a-acc5-487e-a28f-5ab7d6a06f65",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8b34ddf0-c670-40c1-b699-b30da3fcc6af": {
      "main": [
        [
          {
            "node": "b218d17f-8fd4-437e-bf17-418fcd5edda6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Intermedio - DevOps

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Intermedio
Número de nodos12
Categoría1
Tipos de nodos6
Descripción de la dificultad

Adecuado para usuarios con experiencia intermedia, flujos de trabajo de complejidad media con 6-15 nodos

Autor
WeblineIndia

WeblineIndia

@weblineindia

A Leading Software Engineering, Consulting & Outsourcing Services Company in USA & India serving Clients Globally since 1999.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34