Automatische Erstellung von Veröffentlichungshinweisen

Fortgeschritten

Dies ist ein DevOps-Bereich Automatisierungsworkflow mit 10 Nodes. Hauptsächlich werden Set, Code, FormTrigger, HttpRequest und andere Nodes verwendet. Automatisiertes Erstellen von GitHub-Release-Notes mit Benachrichtigung über Slack

Voraussetzungen
  • Möglicherweise sind Ziel-API-Anmeldedaten erforderlich

Kategorie

Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
  "id": "CK1X6HPPuntaDwNl",
  "meta": {
    "instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
    "templateCredsSetupCompleted": true
  },
  "name": "Auto‑Generate Release Notes",
  "tags": [],
  "nodes": [
    {
      "id": "74c1115a-e28b-478e-b4d5-d3c7e890b39c",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "position": [
        200,
        40
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8b87d9c7-3a18-42a9-9ec1-8568fea2908a",
              "name": "repoOwner",
              "type": "string",
              "value": "={{ $json['Repository Owner'] }}"
            },
            {
              "id": "5cac0fee-0aa9-4a4f-a610-8fc3b8682039",
              "name": "repoName",
              "type": "string",
              "value": "={{ $json['Repository Name'] }}"
            },
            {
              "id": "ce2d2b21-55c8-4913-863f-c686e0a51610",
              "name": "defaultBranch",
              "type": "string",
              "value": "={{ $json['Branch Name'] }}"
            },
            {
              "id": "3445fa18-848c-4df5-b5d0-458f978d7cf1",
              "name": "=labelMap",
              "type": "string",
              "value": "{ \"Feature\": \"🚀 Features\", \"bug\": \"🐞 Bug Fixes\", \"performance\": \"⚡ Performance\", \"sdk\": \"📦 SDK / Dependency\" }"
            },
            {
              "id": "29753009-bf1f-40d0-adb9-2ae8135c2eed",
              "name": "=qaChecklist",
              "type": "string",
              "value": "[ \"[ ] App boots successfully\", \"[ ] No crash on startup\", \"[ ] All features tested\", \"[ ] No broken UI on devices\" ]"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "dc575c60-f1ad-439f-8176-0729c109f631",
      "name": "Letzten Git-Tag abrufen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        420,
        40
      ],
      "parameters": {
        "url": "=https://api.github.com/repos/{{$json[\"repoOwner\"]}}/{{$json[\"repoName\"]}}/tags",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "githubApi"
      },
      "credentials": {
        "githubApi": {
          "id": "sWK5QVSgNgKCkpaF",
          "name": "GitHub account"
        },
        "httpHeaderAuth": {
          "id": "Q6oCLdEppyzR0Uga",
          "name": "Header Auth account 3"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a45ac6c8-8f50-49c8-97cd-24e57d3b9c24",
      "name": "Commit-Datum des letzten Tags abrufen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        640,
        40
      ],
      "parameters": {
        "url": "={{$json[\"commit\"][\"url\"]}}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "51399899-3a7b-44d3-9067-64e474d0a00a",
      "name": "Alle gemergten PRs seit dem letzten Tag abholen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        860,
        40
      ],
      "parameters": {
        "url": "=https://api.github.com/search/issues?q=is:pr+is:merged+repo:{{ $('Config').first().json.repoOwner }}/{{ $('Config').first().json.repoName }}+base:{{ $('Config').first().json.defaultBranch }}+merged:>={{ $json.commit.author.date }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "ed1609f1-f1c0-4c15-adb5-b116af6e0a44",
      "name": "Angepasst: PRs gruppieren & Release Notizs generieren",
      "type": "n8n-nodes-base.code",
      "position": [
        1080,
        40
      ],
      "parameters": {
        "jsCode": "// SAFELY access config node data\nconst configNode = $('Config').first();\nif (!configNode) {\n  throw new Error(\"Missing 'Config' node or it's not accessible.\");\n}\n\nconst labelMap =  configNode.labelMap|| {};\nconst qaChecklist = configNode.qaChecklist || [];\n\nconsole.log(\"Your message\", labelMap);\nconsole.log(\"Your message\", qaChecklist);\n\n// Access PR list from previous node\nconst prNode = $('Fetch All Merged PRs Since Last Tag').first(); // <-- Replace with your actual PR-fetch node name\nif (!prNode || !prNode.json || !Array.isArray(prNode.json.items)) {\n  throw new Error(\"Pull request data not found or improperly formatted.\");\n}\n\nconst prItems = prNode.json.items;\n\n/** @type {Record<string, string[]>} */\nconst grouped = {};\n\n// Loop through each PR\nfor (const pr of prItems) {\n  const labels = pr.labels?.map(l => l.name) || [];\n  const matchedKey = labels.find(l => labelMap[l]);\n  const groupTitle = matchedKey ? labelMap[matchedKey] : \"📋 Others\";\n\n  if (!grouped[groupTitle]) {\n    grouped[groupTitle] = [];\n  }\n\n  grouped[groupTitle].push(`- ${pr.title} (#${pr.number})`);\n}\n\n// Build Markdown content\nlet markdown = `## 📝 Release Notes\\n`;\n\nfor (const group in grouped) {\n  markdown += `\\n### ${group}\\n`;\n  markdown += grouped[group].join(\"\\n\") + \"\\n\";\n}\n\nmarkdown += `\\n## ✅ QA Checklist\\n`;\nmarkdown += qaChecklist.map(item => `[ ] ${item}`).join(\"\\n\");\n\nreturn [\n  {\n    json: {\n      release_notes: markdown,\n    },\n  },\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "589e2cf2-e5f5-4411-a0ba-a4f705d242f9",
      "name": "Github Pre Release",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1300,
        40
      ],
      "parameters": {
        "url": "=https://api.github.com/repos/{{ $('Config').first().json.repoOwner }}/{{ $('Config').first().json.repoName }}/releases",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "tag_name",
              "value": "={{ $('Get Latest Git Tag').first().json.name }}"
            },
            {
              "name": "name",
              "value": "={{ $('Get Latest Git Tag').first().json.name }}"
            },
            {
              "name": "body",
              "value": "={{ $json.release_notes }}"
            },
            {
              "name": "draft",
              "value": "={{ true }}"
            },
            {
              "name": "prerelease",
              "value": "={{ false }}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "Q6oCLdEppyzR0Uga",
          "name": "Header Auth account 3"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2190c525-95c9-49e8-84de-e13df0d826e5",
      "name": "Nachricht senden an slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1520,
        40
      ],
      "parameters": {
        "url": "",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "text",
              "value": "={{ $('Adjusted: Group PRs & Generate Release Notes').item.json.release_notes }} {{ $json.html_url }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "6c385b76-cc8e-4cbd-b086-0e2c7e9f42bc",
      "name": "GitHub Release Input Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -20,
        40
      ],
      "webhookId": "80253212-d5c6-4542-9dba-b9ec3f7cc48d",
      "parameters": {
        "options": {},
        "formTitle": "GitHub Release Input Form",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Repository Name",
              "placeholder": "Enter name of the repository",
              "requiredField": true
            },
            {
              "fieldLabel": "Repository Owner",
              "placeholder": "Enter username of github",
              "requiredField": true
            },
            {
              "fieldLabel": "Branch Name",
              "placeholder": "Enter branch name ",
              "requiredField": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "bd0ad833-757e-4619-b31a-7abfef910fe7",
      "name": "Haftnotiz",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        -60
      ],
      "parameters": {
        "width": 1860,
        "height": 360,
        "content": "## Auto‑Generate Release Notes for Any GitHub Repo → Slack"
      },
      "typeVersion": 1
    },
    {
      "id": "fa9609ed-9ef4-43b7-b1e5-1b2245cdc657",
      "name": "Haftnotiz1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        320
      ],
      "parameters": {
        "width": 1880,
        "height": 1260,
        "content": "#🚀 GitHub Automated Release Workflow (n8n)\n\nThis workflow auto-generates release notes from merged pull requests and creates a draft GitHub release, notifying via Slack. Below are the descriptions for each node involved:\n\n⸻\n\n🧩 1. GitHub Release Input Form\n\t•\tPurpose: Collects user input for:\n\t•\towner: GitHub username/org\n\t•\trepo: Repository name\n\t•\tbranch: Target base branch\n\n⸻\n\n⚙️ 2. Config\n\t•\tPurpose:\n\t•\tExtracts user input from the form node.\n\t•\tDefines the label grouping map to classify PRs under sections like feature, bug, performance, etc.\n\n⸻\n\n🔖 3. Get Latest Git Tag\n\t•\tPurpose: Fetches the most recent semantic Git tag from the selected repository.\n\t•\tWhy: Used to determine what PRs were merged after the last release.\n\n⸻\n\n🕒 4. Get Commit Date of Latest Tag\n\t•\tPurpose: Retrieves the commit timestamp for the latest tag.\n\t•\tWhy: This timestamp is used to filter only the PRs merged after the last release.\n\n⸻\n\n📥 5. Fetch All Merged PRs Since Last Tag\n\t•\tPurpose: Queries GitHub’s Search API for pull requests:\n\t•\tThat are merged.\n\t•\tMerged after the latest tag’s commit date.\n\t•\tOn the selected base branch.\n\t•\tWhy: Ensures only new, relevant PRs are included in the release.\n\n⸻\n\n🧠 6. Adjusted: Group PRs & Generate Release Note\n\t•\tPurpose:\n\t•\tGroups the filtered PRs by label (using Config map).\n\t•\tFormats them into a clean Markdown release note.\n\t•\tAdds a ✅ QA Checklist section at the end.\n\n⸻\n\n🪄 7. GitHub Pre Release\n\t•\tPurpose:\n\t•\tCreates a draft GitHub release.\n\t•\tUses the latest tag and generated notes.\n\t•\tSets:\n\t•\t\"draft\": true\n\t•\t\"prerelease\": false\n\n⸻\n\n💬 8. Send Message to Slack\n\t•\tPurpose: Posts the release summary to a designated Slack channel.\n\t•\tIncludes: Tag name, categorized release notes, and optionally a link to the GitHub release."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "e0e3b36d-59a8-4ec1-a1e5-5a19fb5063ed",
  "connections": {
    "74c1115a-e28b-478e-b4d5-d3c7e890b39c": {
      "main": [
        [
          {
            "node": "dc575c60-f1ad-439f-8176-0729c109f631",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "dc575c60-f1ad-439f-8176-0729c109f631": {
      "main": [
        [
          {
            "node": "a45ac6c8-8f50-49c8-97cd-24e57d3b9c24",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "589e2cf2-e5f5-4411-a0ba-a4f705d242f9": {
      "main": [
        [
          {
            "node": "2190c525-95c9-49e8-84de-e13df0d826e5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6c385b76-cc8e-4cbd-b086-0e2c7e9f42bc": {
      "main": [
        [
          {
            "node": "74c1115a-e28b-478e-b4d5-d3c7e890b39c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a45ac6c8-8f50-49c8-97cd-24e57d3b9c24": {
      "main": [
        [
          {
            "node": "51399899-3a7b-44d3-9067-64e474d0a00a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "51399899-3a7b-44d3-9067-64e474d0a00a": {
      "main": [
        [
          {
            "node": "Angepasst: PRs gruppieren & Release Notes generieren",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Angepasst: PRs gruppieren & Release Notes generieren": {
      "main": [
        [
          {
            "node": "589e2cf2-e5f5-4411-a0ba-a4f705d242f9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Häufig gestellte Fragen

Wie verwende ich diesen Workflow?

Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.

Für welche Szenarien ist dieser Workflow geeignet?

Fortgeschritten - DevOps

Ist es kostenpflichtig?

Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.

Workflow-Informationen
Schwierigkeitsgrad
Fortgeschritten
Anzahl der Nodes10
Kategorie1
Node-Typen5
Schwierigkeitsbeschreibung

Für erfahrene Benutzer, mittelkomplexe Workflows mit 6-15 Nodes

Autor
WeblineIndia

WeblineIndia

@weblineindia

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

Externe Links
Auf n8n.io ansehen

Diesen Workflow teilen

Kategorien

Kategorien: 34