📹 Watch the demo
The problem
I got tired of doing the same thing every week: opening GitHub, checking which PRs I'd merged across a couple of repos, scrolling through commits, then typing up a summary for myself or my team. None of it is hard. It's just the kind of repetitive task that has no business eating up my time when it could just happen on its own.
So I built a pipeline that does it for me. It pulls my GitHub activity across org and personal repos, has AI write a clean summary, and drops it into Slack. No manual digging, no forgetting, it just shows up.
Why n8n
If you haven't used it before: n8n is an open-source automation tool, kind of like Zapier or Make but self-hostable and much more developer-friendly. You build workflows visually. Each "node" does one job (hit an API, transform some data, send a message) and you connect them on a canvas instead of writing everything as one script.
A few things about it made this project click faster than I expected:
- Native GitHub, Slack, and OpenAI nodes, so I wasn't writing auth boilerplate for the easy 80%
- A Code node for the parts that don't fit a pre-built integration, like pagination, filtering, and branch detection
- Built-in scheduling, so it just runs
- You can actually see the data flowing at every step, which made debugging way less painful than staring at console logs
How it's put together
Schedule Trigger
→ Get My Organizations (pulled dynamically, no hardcoding)
→ Loop Repos
→ Fetch PRs (for repos that go through PR review)
→ Fetch commits from the default branch (for repos that merge straight to main)
→ Filter down to my activity, scoped to the reporting window
→ Aggregate everything
→ AI Summary node
→ Combine into one formatted report
→ Send to Slack
It splits into two paths because not everything I work on follows the same process. Some repos go through PRs. My personal projects usually just get merged straight to main. I needed both covered without assuming one shape for every repo.
A few things I had to get right
Don't assume main or master. Every repo can name its default branch differently, so instead of hardcoding one, the workflow just asks GitHub what it actually is before pulling commits:
// Ask GitHub which branch is actually the default, never assume
const repoInfo = await this.helpers.httpRequest({
method: 'GET',
url: `https://api.github.com/repos/${repoFullName}`,
headers: authHeaders,
json: true
});
const defaultBranch = repoInfo.default_branch;
Pagination that doesn't waste calls. GitHub caps results at 100 per page. I sort by newest first and bail out as soon as I've crossed the reporting window, instead of always walking every page:
// Sorted newest first, so we can bail as soon as we're past the reporting window
const oldestOnPage = new Date(pageResults[pageResults.length - 1].created_at);
if (oldestOnPage < reportingWindowStart) break;
One config node, not scattered values. GitHub username, lookback window, report label. All of it lives in a single node, and everything downstream reads from it instead of me hardcoding the same value five different places:
// One source of truth for the report label, referenced everywhere it's needed
const reportLabel = $('Set Report Config').first().json.reportLabel || "Commit";
const headerText = "*📊 " + reportLabel + " Summary*\n\n";
This last one mattered more than I expected. It's the difference between a script that only works for me and something I could actually hand to someone else.
How it's working out
It just runs now. Every week, a clean summary shows up in Slack without me touching anything. Small thing, but not having it in my head as a Monday chore anymore is a nice bit of mental space back.
Try it yourself
I open-sourced the whole thing. The exported n8n workflow, a setup README, and the demo video are all here: github.com/smusman437/github-slack-report-automation
Grab it, plug in your own GitHub, Slack, and OpenAI credentials, and point it at your repos. Everything you need to configure lives in one node, so there's nothing else to go hunting for.
If you've built something similar, or you've got a cleaner way of handling repos that mix PR-based and direct-to-main workflows, I'd genuinely like to hear it. Drop it in the comments.
Top comments (0)