AutomationFlowsAI & RAG › Summarize Jenkins Test Runs with Gemini AI & Sheets

Summarize Jenkins Test Runs with Gemini AI & Sheets

Original n8n title: Summarize Daily Jenkins Test Runs with Google Sheets, Http and Gemini AI

ByRichard Nijsten @rnijsten on n8n.io

As a test automation engineer, staying on top of daily test runs in Jenkins is essential. This workflow automates that process: it pulls specific test details from a Google Sheet, retrieves data from your local Jenkins environment, and uses AI to generate a concise summary…

Cron / scheduled trigger★★★★☆ complexityAI-powered12 nodesGoogle Gemini ChatGoogle SheetsAgentGmailHTTP Request
AI & RAG Trigger: Cron / scheduled Nodes: 12 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #13808 — we link there as the canonical source.

This workflow follows the Agent → Gmail recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "qhsM9rmYFzfC28fo",
  "name": "Automate daily Jenkins test reports with AI and HTTP Requests",
  "tags": [],
  "nodes": [
    {
      "id": "dcee8db7-84ad-449c-ac90-5ebb30ff4288",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        2552,
        464
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "8f0e6821-e44a-47d6-b131-f8f8ece1f1bf",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 832,
        "height": 656,
        "content": "## Automate daily Jenkins test reports with AI and HTTP Requests\nAs a test automation engineer, staying on top of daily test runs in Jenkins is essential. This workflow automates that process: it pulls specific test details from a Google Sheet, retrieves data from your local Jenkins environment, and uses AI to generate a concise summary report to be sent via email.\n\n**Who's it for**\n* Test automation engineers using Jenkins.\n* QA teams looking to streamline daily reporting.\n\n**How it works** \n* Scheduled Trigger: The workflow runs automatically at a pre-defined time.\n* Dynamic Data Retrieval: It constructs an HTTP request based on the data in your Google Sheet to fetch specific Jenkins results.\n* AI Optimization: Only relevant data is extracted to minimize AI token usage and focus on the most important metrics.\n* Summarization: The AI groups the results and formats them into a clear, professional email.\n* Distribution: The report is sent to every recipient listed in the MailingList column.\n\n\n**How to set up** \n* In the Google Sheet, set the BaseUrl, Environment, FeatureClass and Feature in order to build up the Jenkins url in their corresponding columns, for example:\nBaseUrl\t   | Environment\t|  FeatureClass\t      |Feature |MailingList |\n<BaseUrl> |<environment>\t| <FeaturClassName> |<Featurename>  |\t<mail>     |\n* Define Recipients: In the MailingList column, add the email addresses of the people who need to receive the report. If there are multiple recipients, ensure they are separated by commas.\n\n\n**Requirements** \n* Access to your Jenkins server.\n* An AI API key (e.g., Gemini, OpenAI).\n* A Google Cloud project with the Google Sheets API enabled."
      },
      "typeVersion": 1
    },
    {
      "id": "52dadb42-ffe8-40fb-8b38-c51bfe7f2639",
      "name": "Retrieve Google Sheet data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1136,
        240
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 897459827,
          "cachedResultUrl": "",
          "cachedResultName": "DataRequest"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "1a0296af-cd8a-4b24-b0f8-62619f4e40cd",
      "name": "Aggregate the data for AI processing",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        2256,
        240
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "fa008380-afea-4fc9-8870-81f62109038f",
      "name": "Jenkins Report Analyzer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2480,
        240
      ],
      "parameters": {
        "text": "Use the provided data to create an overview of the failed (\"Gefaald\"), skipped (\"Overgeslagen\"), passed (\"Pass\") and total (\"Totaal\") tests for each feature.\nIf it has failed (\"Gefaald\") tests, list them by name.\n\nSummize them per environment and per feature and combine them in one email.",
        "options": {
          "systemMessage": "=You are a Jenkins Report analyzer, and your job is to get the results of each environment (develop = test, master = acceptance), and report back the results of each environment and which tests passed and/or failed.\nIf failed, show the specific failed test and the corresponding error.\nUse the data of {{ $json.data.map(item => {\n    const buildInfo = JSON.parse(item.build_Number);\n    const pkg = JSON.parse(item.test_data);\n    \n    const header = `### ENV: ${item.environment.toUpperCase()} | BUILD: ${buildInfo.build_number} ###\\n`;\n    \n    const body = `PACKAGE: ${pkg.name} (Pass: ${pkg.passCount}, Fail: ${pkg.failCount})\\n` + \n        pkg.child.map(story => \n            `  STORY: ${story.name}\\n` + \n            story.child.map(test => \n                `    [${test.status}] ${test.name}${test.status === 'FAILED' ? '\\n    ERROR: ' + (test.errorDetails ? test.errorDetails.trim() : 'No details available') : ''}`\n            ).join('\\n')\n        ).join('\\n');\n\n    return header + body;\n}).join('\\n\\n====================\\n\\n') }}\n\nBeautify the HTML using inline CSS styling for an email. Format it like a modern newsletter. Output only the results without any header elements.\nKeep the formatting and layout each mail the same.\nGenerate a professional HTML email report\nOutput ONLY the raw HTML code. \nDO NOT include introductory text (like 'Here is your report').\nDO NOT include markdown code blocks (no ```html).\nDO NOT include explanations, justifications, or Python code.\nStart your response with <html> and end it with </html>.\""
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "d4fed334-f0f9-4089-87c0-11e5673131bb",
      "name": "Send the test results based on the MailingList",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2832,
        240
      ],
      "parameters": {
        "sendTo": "={{ $('Retrieve Google Sheet data').first().json.MailingList }}",
        "message": "={{ $json.output }}",
        "options": {},
        "subject": "=Jenkins - Test Results Report - {{new Date().toLocaleDateString()}}"
      },
      "typeVersion": 2.2
    },
    {
      "id": "7a354845-5797-465d-9544-ac0b08fef0df",
      "name": "Perform HTTP Request to Jenkins Server for build numbers",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "The first request is needed to have the build numbers available.",
      "position": [
        1360,
        240
      ],
      "parameters": {
        "url": "={{ $node[\"Retrieve Google Sheet data\"].json.BaseUrl }}/{{ $node[\"Retrieve Google Sheet data\"].json.Environment }}/lastCompletedBuild/testReport/{{ $node[\"Retrieve Google Sheet data\"].json.FeatureClass }}.{{ $node[\"Retrieve Google Sheet data\"].json.Feature }}/",
        "options": {}
      },
      "typeVersion": 4.4
    },
    {
      "id": "ef12a5f6-cfa9-4885-b769-f5e27213529d",
      "name": "Extract the build number",
      "type": "n8n-nodes-base.html",
      "position": [
        1584,
        240
      ],
      "parameters": {
        "options": {},
        "operation": "extractHtmlContent",
        "extractionValues": {
          "values": [
            {
              "key": "build_number",
              "cssSelector": "#breadcrumbs > li:nth-child(3) > a"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1f5caaf9-9837-4c9f-adf6-9ff9597f7ac0",
      "name": "Set the fields correctly for AI",
      "type": "n8n-nodes-base.set",
      "position": [
        2032,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "2720d3fe-5902-4d86-b436-71d2e592f82d",
              "name": "environment",
              "type": "string",
              "value": "={{ $node[\"Retrieve Google Sheet data\"].json.Environment }}"
            },
            {
              "id": "bfe0fce6-ec66-45f7-847a-e1b8673b0994",
              "name": "build_Number",
              "type": "string",
              "value": "={{ $node[\"Extract the build number\"].json }}"
            },
            {
              "id": "733f8aa4-dd97-4c63-9cc4-5d8283a04851",
              "name": "payload",
              "type": "string",
              "value": "={{ $json.test_data }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "1ce71933-6135-4e49-8d60-38d04dd542ee",
      "name": "Perform HTTP Request with depth 2 to Jenkins Server",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1808,
        240
      ],
      "parameters": {
        "url": "={{ $node[\"Retrieve Google Sheet data\"].json.BaseUrl }}/{{ $node[\"Retrieve Google Sheet data\"].json.Environment }}/lastCompletedBuild/testReport/{{ $node[\"Retrieve Google Sheet data\"].json.FeatureClass }}.{{ $node[\"Retrieve Google Sheet data\"].json.Feature }}/api/json?depth=2",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "text",
              "outputPropertyName": "test_data"
            }
          }
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "177fa0fa-f952-440f-8f62-a42b02570a7c",
      "name": "Trigger workflow daily on set time",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        912,
        240
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9,
              "triggerAtMinute": 5
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "68c7a94b-5cc5-4f07-9a34-a84e97727fc9",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1312,
        48
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 368,
        "content": "## Retrieve the Jenkins Test Data\n* First we have to retrieve the report in order to get the build numbers, needed for the AI to know which report we are talking about.\n* Then we extract the build numbers from the test reports using the HTML extract node.\n* In order to have a complete test report, we perform an additional HTTP request but with an \"/api/json?depth=2\" to get all data, including the failed results."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "831c055d-561d-4cec-b17c-281f6578fc82",
  "connections": {
    "Jenkins Report Analyzer": {
      "main": [
        [
          {
            "node": "Send the test results based on the MailingList",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract the build number": {
      "main": [
        [
          {
            "node": "Perform HTTP Request with depth 2 to Jenkins Server",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Jenkins Report Analyzer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Google Sheet data": {
      "main": [
        [
          {
            "node": "Perform HTTP Request to Jenkins Server for build numbers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set the fields correctly for AI": {
      "main": [
        [
          {
            "node": "Aggregate the data for AI processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger workflow daily on set time": {
      "main": [
        [
          {
            "node": "Retrieve Google Sheet data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate the data for AI processing": {
      "main": [
        [
          {
            "node": "Jenkins Report Analyzer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Perform HTTP Request with depth 2 to Jenkins Server": {
      "main": [
        [
          {
            "node": "Set the fields correctly for AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Perform HTTP Request to Jenkins Server for build numbers": {
      "main": [
        [
          {
            "node": "Extract the build number",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

As a test automation engineer, staying on top of daily test runs in Jenkins is essential. This workflow automates that process: it pulls specific test details from a Google Sheet, retrieves data from your local Jenkins environment, and uses AI to generate a concise summary…

Source: https://n8n.io/workflows/13808/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

The Multi-Model Agency Content Engine is a high-performance editorial system designed for agencies. It solves the "blank page" problem by alternating between real-world social proof and strategic expe

Google Sheets, Gmail, Google Drive +6
AI & RAG

This workflow helps you find and evaluate job opportunities automatically, without spending hours searching and comparing roles. It uses your resume to look for relevant jobs on LinkedIn, checks how w

Google Drive, HTTP Request, Google Gemini Chat +3
AI & RAG

When I was applying for roles, I learned the hard way that a one-size-fits-all resume never wins. I obsessively tailored my resume for each posting, reflecting the exact scope, impact, and stack the t

Google Drive, Google Sheets, HTTP Request +3
AI & RAG

Who is this template for? This workflow is perfect for competitive‑intel analysts, product managers, content marketers, and anyone who tracks multiple company blogs or news sources. If you need a week

HTTP Request, Output Parser Structured, Agent +5
AI & RAG

This workflow fetches the latest blog post from a WordPress API and checks against a Google Sheets tracker to prevent duplicate processing. If a new post is found, the workflow updates the tracker and

Google Gemini Chat, LinkedIn, Google Sheets +3