Dina pull requests är ”klara”… tills granskningen förvandlas till en lint-debatt. Efterföljande kommatecken. Importordning. Ett dussin små kommentarer som ger noll produktvärde, men ändå bromsar mergningen.
Engineering Managers märker det i ledtiden. Tech Leads märker det som granskningströtthet. Och om du driver ett litet produktteam märker du det i alla kontextbyten. Den här GitHub Gemini lint-automationen flyttar stilfixar ut från huvud-PR:en, så att granskare kan fokusera på den faktiska förändringen.
Nedan är exakt hur workflowet beter sig, vad du får ut av det och vad du behöver för att köra det stabilt i flera repos.
Så här fungerar automationen
Hela n8n-workflowet, från trigger till slutresultat:
n8n Workflow Template: GitHub + Google Gemini: lintfix utan omarbete
flowchart LR
subgraph sg0["AI Agent Flow"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Listen for Trigger from Gith.."]
n1@{ icon: "mdi:robot", form: "rounded", label: "AI Agent", pos: "b", h: 48 }
n2["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Respond to Webhook"]
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get PR Files"]
n4["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get File Contents"]
n5@{ icon: "mdi:cog", form: "rounded", label: "Convert Base64 to Text File", pos: "b", h: 48 }
n6@{ icon: "mdi:cog", form: "rounded", label: "Extract from File", pos: "b", h: 48 }
n7@{ icon: "mdi:swap-vertical", form: "rounded", label: "Create Code/FilePath Object", pos: "b", h: 48 }
n8@{ icon: "mdi:cog", form: "rounded", label: "Collect All Files Changed", pos: "b", h: 48 }
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get PR GitHub Branch"]
n10@{ icon: "mdi:web", form: "rounded", label: "Create GitHub Blob", pos: "b", h: 48 }
n11@{ icon: "mdi:web", form: "rounded", label: "Create GitHub Tree", pos: "b", h: 48 }
n12@{ icon: "mdi:web", form: "rounded", label: "Create GitHub Commit", pos: "b", h: 48 }
n13@{ icon: "mdi:web", form: "rounded", label: "Create Pull Request", pos: "b", h: 48 }
n14@{ icon: "mdi:web", form: "rounded", label: "Create Branch", pos: "b", h: 48 }
n15["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get Latest Main Branch Commi.."]
n16["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get Latest Main Branch Tree .."]
n17@{ icon: "mdi:web", form: "rounded", label: "Get Branch", pos: "b", h: 48 }
n18@{ icon: "mdi:brain", form: "rounded", label: "Google Gemini Chat Model", pos: "b", h: 48 }
n19["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Set Common Fields"]
n1 --> n2
n17 -.-> n1
n3 --> n4
n14 -.-> n1
n6 --> n7
n4 --> n5
n19 --> n9
n10 -.-> n1
n11 -.-> n1
n13 -.-> n1
n12 -.-> n1
n9 --> n15
n18 -.-> n1
n8 --> n1
n5 --> n6
n7 --> n8
n16 --> n3
n15 --> n16
n0 --> n19
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n1 ai
class n18 aiModel
class n0,n2,n3,n4,n9,n10,n11,n12,n13,n14,n15,n16,n17 api
class n19 code
classDef customIcon fill:none,stroke:none
class n0,n2,n3,n4,n9,n15,n16,n19 customIcon
Problemet: lint-feedback blåser upp PR-granskningar
Linting är viktigt, men PR-trådar är en usel plats att driva igenom det. En granskare skriver ”kör prettier” och författaren pushar en ny commit, som ändrar diffen, som triggar mer granskning, som skapar fler notiser. Multiplicera det med fem ingenjörer och några repos så får du ett konstant dropp av mikrojobb. Det värsta är den dolda kostnaden: folk börjar skumma granskningar eftersom de förväntar sig brus, och riktiga problem slinker igenom.
Det summerar snabbt. Här är var det brister i vardagsteam.
- Granskare lägger cirka 10 minuter per PR på att kommentera formatering i stället för logik.
- Författare ”churnar” samma PR med commits som bara gäller lint, vilket gör diffar svårare att läsa.
- Små stilavvikelser smyger sig in eftersom allas editor-konfiguration skiljer sig lite.
- Merge-tiden drar ut, eftersom ”snabba fixar” ändå kräver en ny granskningsrunda.
Lösningen: AI-genererade lint-fixar som en separat PR
Det här workflowet (LintGuardian) lyssnar efter nya pull requests i GitHub, hämtar listan över ändrade filer och hämtar sedan själva filinnehållet. Det konverterar och läser filerna så att texten kan analyseras strukturerat, och skickar sedan relevant kod och kontext till Google Gemini via en AI Agent. Gemini föreslår lint-fixar utifrån dina regler, och workflowet bygger korrigerade versioner av de ändrade filerna. Till sist skapar det en ny branch, committar fixarna och öppnar en separat pull request med ”lint fixes” mot samma bas, så att du kan merga den med ett klick utan att grumla den ursprungliga feature-PR:en.
Workflowet startar när en GitHub pull request-händelse träffar din n8n-webhook. Därifrån samlar det in ändrade filer, kör Gemini-baserad linting och förbereder en korrekt formaterad commit. Utfallet är en andra PR som är dedikerad till formatering och stil, vilket håller diskussionen i original-PR:en fokuserad.
Det du får: automation vs. resultat
| Vad detta workflow automatiserar | Resultat du får |
|---|---|
|
|
Exempel: så här ser det ut
Säg att ditt team levererar cirka 20 PR:er i veckan. Om varje PR triggar ”kör lint / fixa formatering / begär granskning igen” och den dansen kostar cirka 15 minuter för författaren och 10 minuter för en granskare, så bränner ni runt 8 timmar i veckan på stilchurn. Med det här workflowet öppnar författaren bara PR:en som vanligt, n8n hämtar de ändrade filerna, Gemini genererar fixar och en andra städ-PR dyker upp i repot. Realistiskt lägger du 2 minuter på att skumma och merga lint-PR:en, och går sedan vidare.
Det här behöver du
- n8n-instans (testa n8n Cloud gratis)
- Alternativ för self-hosting om du föredrar det (Hostinger fungerar bra)
- GitHub för pull requests, branches och commits
- Google Gemini (Google AI) för att generera lint-fixar från kod
- GitHub Personal Access Token (skapa den i GitHub Settings → Developer settings)
- Google AI API-nyckel (hämta den från Google AI Studio / Google Cloud-konsolen)
Svårighetsgrad: Medel. Du klistrar in API-nycklar, sätter repo/org-värden och bekräftar webhook-behörigheter i GitHub.
Vill du inte sätta upp detta själv? Prata med en automationsexpert (gratis 15-minuters konsultation).
Så fungerar det
En PR-händelse träffar din webhook. GitHub (ofta via ett litet workflow-steg i repot) skickar PR-nummer, reponamn, head-branch och base-branch till din n8n-webhook-endpoint.
Ändrade filer samlas in och förbereds. n8n anropar GitHub API för att hämta PR:ens fillista, hämtar innehållet för varje fil, avkodar det och extraherar text så att AI:n ser koden tydligt. Det finns också en setup med delade fält så att repo/org-värden inte dupliceras mellan noder.
Gemini föreslår ändringar som bara gäller lint. AI Agent använder Gemini-chattmodellen plus minne för att hålla instruktioner konsekventa mellan filer. Den identifierar problem, producerar korrigerad kod och returnerar fixar strukturerat så att workflowet kan applicera dem.
En städ-branch och PR skapas. n8n bygger en git blob/tree/commit, skapar en ny branch från rätt commit-SHA och öppnar en ny pull request med en titel för lint-fixar, riktad mot den ursprungliga base-branchen.
Du kan enkelt justera vilka filtyper som ska processas för att ignorera genererade filer eller vendor-kod utifrån dina behov. Se hela implementationsguiden nedan för anpassningsalternativ.
Steg-för-steg-guide för implementation
Steg 1: Konfigurera webhook-triggern
Det här arbetsflödet startar när GitHub skickar en webhook-händelse till n8n.
- Lägg till och öppna Inbound GitHub Hook.
- Ställ in Path på
1da5a6e1-9453-4a65-bbac-a1fed633f6ad. - Ställ in Response Mode på
responseNodeså att svaret hanteras av Return Webhook Reply. - I GitHub konfigurerar ni webhook-URL:en till produktions-URL:en som visas i Inbound GitHub Hook.
- Bekräfta att Inbound GitHub Hook är kopplad till Define Shared Fields i canvasen.
Tips: Säkerställ att er GitHub-webhook-händelse innehåller pull request-data så att uttryck som {{ $('Inbound GitHub Hook').item.json.pull_request_number }} kan tolkas korrekt.
Steg 2: Anslut GitHub och definiera delade repo-inställningar
Definiera repo-kontexten och autentisera GitHub API-anropen som används för att hämta data om pull requests och commits.
- Öppna Define Shared Fields och verifiera att repo-värdena i jsCode är korrekta:
'gitHubRepoName': 'my-membership'och'gitHubOrgName': 'carved-rock-fitness-gym'. - Säkerställ att bas-endpointen byggs i Define Shared Fields med
https://api.github.com/repos/${commonFields.gitHubOrgName}/${commonFields.gitHubRepoName}. - Öppna Fetch PR Branch Info och bekräfta att URL är satt till
{{ $json.gitHubApiBaseEndpointUri }}/pulls/{{ $('Inbound GitHub Hook').item.json.pull_request_number }}. - Autentiseringsuppgift krävs: Anslut era githubApi-autentiseringsuppgifter i Fetch PR Branch Info, Fetch Main Commit SHA och Fetch Main Tree Hash.
- Bekräfta att exekveringsflödet fortsätter från Fetch PR Branch Info → Fetch Main Commit SHA → Fetch Main Tree Hash.
⚠️ Vanlig fallgrop: Om repo-namnet eller org-namnet i Define Shared Fields är fel kommer alla GitHub API-anrop att misslyckas på grund av felaktiga endpoint-URL:er.
Steg 3: Sätt upp insamling av pull request-filer
Samla in alla ändrade filer från pull requesten, avkoda dem och aggregera koden för analys.
- Öppna Fetch PR File List och ställ in URL på
{{ $('Define Shared Fields').item.json.gitHubApiBaseEndpointUri }}/pulls/{{ $('Inbound GitHub Hook').item.json.pull_request_number }}/files. - I Retrieve File Contents ställer ni in URL på
{{ $json.contents_url }}så att respektive fils endpoint för innehåll hämtas. - I Decode Base64 File ställer ni in Operation på
toBinaryoch Source Property påcontent. - I Read Text From File ställer ni in Operation på
textför att extrahera läsbar kod. - I Assemble Code Path Data bekräftar ni tilldelningarna: code =
{{ $json.data }}och filePath ={{ $('Retrieve File Contents').item.json.path }}. - I Aggregate Changed Files ställer ni in Aggregate på
aggregateAllItemDataför att skicka en enda samling till AI-agenten.
Steg 4: Sätt upp AI-orkestreraren för lintning
AI-agenten analyserar den aggregerade koden och styr GitHub-åtgärder med anslutna AI-verktyg.
- Öppna Linting AI Orchestrator och ställ in Text på
=.{{ JSON.stringify($json.data) }} - Granska systemmeddelandet i Linting AI Orchestrator, som refererar till
{{ $('Fetch PR Branch Info').item.json.head.ref }}och{{ $('Inbound GitHub Hook').item.json.pull_request_number }}. - Öppna Gemini Chat Model och ställ in Model Name på
models/gemini-2.0-flash. - Autentiseringsuppgift krävs: Anslut era googlePalmApi-autentiseringsuppgifter i Gemini Chat Model.
- Säkerställ att Gemini Chat Model är ansluten som språkmodell för Linting AI Orchestrator.
Tips: AI-verktygsnoder som Generate Git Blob och Build Git Tree är verktyg för Linting AI Orchestrator; hantering av autentiseringsuppgifter ska göras på respektive verktygsnod även om de anropas av agenten.
Steg 5: Konfigurera GitHub-skrivåtgärder och svar
AI-verktyg skapar blobs, träd, commits, brancher och pull requests, och sedan svarar arbetsflödet till GitHub.
- Verifiera att alla GitHub-verktygsnoder är anslutna som AI-verktyg till Linting AI Orchestrator: Generate Git Blob, Build Git Tree, Create Git Commit, Create Git Branch, Lookup Branch och Open Pull Request.
- I Generate Git Blob bekräftar ni att URL är
{{ $('Define Shared Fields').item.json.gitHubApiBaseEndpointUri }}/git/blobsoch att Method ärPOST. - I Build Git Tree verifierar ni att JSON Body innehåller
{{ $('Fetch Main Tree Hash').item.json.tree.sha }}och{{ $fromAI('json_array_of_files','','string') }}. - I Create Git Commit validerar ni att JSON Body innehåller commit-meddelandet och parent-SHA med
{{ $('Fetch Main Commit SHA').item.json.object.sha }}. - I Create Git Branch och Open Pull Request säkerställer ni att parametrarna för branch och PR är AI-genererade och att basen är
main. - Autentiseringsuppgift krävs: Anslut era githubApi-autentiseringsuppgifter i alla GitHub-verktygsnoder: Generate Git Blob, Build Git Tree, Create Git Commit, Create Git Branch, Lookup Branch och Open Pull Request.
- Öppna Return Webhook Reply och ställ in Respond With på
allIncomingItemsför att bekräfta webhook-förfrågan.
⚠️ Vanlig fallgrop: Om GitHub API-autentiseringsuppgifterna saknar skrivbehörigheter kommer AI-verktygen att misslyckas med att skapa brancher eller pull requests.
Steg 6: Testa och aktivera ert arbetsflöde
Kör ett manuellt test för att validera lintning och GitHub-uppdateringsflödet end-to-end innan ni går live.
- Klicka på Execute Workflow och trigga en test-webhook för pull request från GitHub.
- Verifiera att Fetch PR File List hämtar ändrade filer och att Aggregate Changed Files matar ut ett enda aggregerat objekt.
- Bekräfta att Linting AI Orchestrator tar emot
-payloaden och anropar GitHub-verktygen för att skapa commits och PR:er. - Kontrollera att Return Webhook Reply svarar korrekt och att GitHub får ett 200-svar.
- När ni har validerat, slå om arbetsflödet till Active för produktionsanvändning.
Vanliga fallgropar
- GitHub-credentials kan gå ut eller kräva specifika behörigheter. Om det slutar fungera: kontrollera GitHub → Settings → Developer settings → Personal access tokens (och bekräfta scopes: repo, workflow och admin:repo_hook) först.
- Om du använder Wait-noder eller extern rendering varierar processtiderna. Öka väntetiden om nedströmsnoder fallerar på tomma svar.
- Standardprompter i AI-noder är generiska. Lägg in er tonalitet tidigt, annars kommer du redigera outputs för alltid.
Vanliga frågor
Cirka en timme om du redan har tokens och repo-åtkomst.
Nej. Du kommer mest kopiera in credentials i n8n och uppdatera dina repo/org-värden. Den enda ”kodlika” delen är att redigera en liten GitHub-workflowfil så att den pekar på din webhook-URL.
Ja. n8n har ett gratis self-hosted-alternativ och en gratis provperiod på n8n Cloud. Cloud-planer börjar på 20 USD/månad för högre volym. Du behöver också räkna in kostnader för Google Gemini API-användning, som beror på hur många filer du processar per PR.
Två alternativ: n8n Cloud (hanterat, enklast setup) eller self-hosting på en VPS. För self-hosting är Hostinger VPS prisvärt och hanterar n8n bra. Self-hosting ger obegränsade körningar men kräver grundläggande serverhantering.
Ja, och det bör du. Det enklaste är att filtrera listan över ändrade filer innan den når AI Agent, så att bara sökvägar som src/ eller filändelser som .ts och .js processas. Många team hoppar också över lockfiler, minifierade bundles och genererade mappar för att undvika meningslösa ”fixar”. Om du vill ha striktare beteende justerar du AI Agentens systemmeddelande så att Gemini följer era lint-regler och ignorerar allt annat.
Oftast är det en token som gått ut eller en token som saknar scopes. Skapa om din GitHub Personal Access Token och säkerställ att den kan läsa/skriva till repot och hantera webhooks, och uppdatera sedan credential i n8n. Dubbelkolla också att du pekar på rätt org/repo i noden med delade fält, eftersom ett enda skrivfel kan se ut som ett auth-fel. Om du kör detta på många PR:er samtidigt kan rate limits också dyka upp.
På en typisk n8n Cloud-plan kan du hantera tusentals PR-triggade körningar per månad, och self-hosting har ingen fast exekveringsgräns (det beror på din server). I praktiken är flaskhalsen oftast hur många filer du skickar till Gemini per PR.
Ofta, ja. n8n är helt enkelt smidigare för Git-operationer som att bygga commits och skapa branches, och det är enklare att hålla logiken samlad när du behöver loopar, aggregering och villkorshantering. Self-hosting är också en stor grej, eftersom du inte betalar per litet steg när en PR rör många filer. Zapier eller Make kan fortfarande fungera för lätta notifieringar, men det här workflowet ligger närmare ”DevOps-plumbing” än marknadsföringsautomation. Är du osäker, prata med en automationsexpert så får du en rak rekommendation.
Lint-städning behöver inte vara en mänsklig diskussion i varje PR. Sätt upp detta en gång, och låt granskningarna återgå till det som spelar roll.
Kontakta oss
Hör av dig, så diskuterar vi hur just din verksamhet kan dra nytta av alla fantastiska möjligheter som AI skapar.