DEV Community

Tracepilot
Tracepilot

Posted on

Build a Daily Python Trending Repos Notifier with GitHub Issues

Build a Daily Python Trending Repos Notifier with GitHub Issues

What we're building: A bot that watches GitHub's daily trending Python repos and posts them automatically as a GitHub Issue comment โ€” so you never miss what's hot in the Python ecosystem.

Prerequisites

  • Node.js 18+
  • A GitHub account (free tier works)
  • An OpenAI API key (for the AI summary)
  • A TracePilot API key (free tier available)

Step 1: Set Up the Project

mkdir python-trending-notifier
cd python-trending-notifier
npm init -y
npm install axios cheerio cron node-cron openai tracepilot-sdk
Enter fullscreen mode Exit fullscreen mode

You'll also need a GitHub personal access token with repo scope. Create one here.

Step 2: Scrape GitHub Trending Python Repos

// lib/scraper.js
import axios from 'axios';
import * as cheerio from 'cheerio';

export async function getTrendingPythonRepos() {
  const { data } = await axios.get('https://github.com/trending/python?since=daily', {
    headers: { 'User-Agent': 'Mozilla/5.0' }
  });

  const $ = cheerio.load(data);
  const repos = [];

  $('article.Box-row').each((i, el) => {
    const name = $(el).find('h2 a').text().trim().replace(/\s+/g, '');
    const description = $(el).find('p').text().trim();
    const stars = $(el).find('.octicon-star').parent().text().trim();
    const forks = $(el).find('.octicon-repo-forked').parent().text().trim();
    const todayStars = $(el).find('.float-sm-right').text().trim();

    repos.push({
      name,
      description: description || 'No description',
      stars: stars || '0',
      forks: forks || '0',
      todayStars: todayStars || '0 stars today',
      url: `https://github.com/${name}`
    });
  });

  return repos.slice(0, 10); // Top 10
}
Enter fullscreen mode Exit fullscreen mode

This scrapes the GitHub trending page for Python repos. It's the same data you see at github.com/trending/python?since=daily โ€” but now you own it.

Step 3: Generate an AI Summary

// lib/summarizer.js
import OpenAI from 'openai';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export async function generateSummary(repos) {
  const prompt = `Summarize today's top 10 trending Python repos in 3-4 sentences. 
Focus on patterns (e.g., "lots of AI tools this week" or "a new web framework emerged").
Repos: ${repos.map(r => `${r.name}: ${r.description}`).join('\n')}`;

  const response = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: prompt }],
    max_tokens: 150
  });

  return response.choices[0].message.content;
}
Enter fullscreen mode Exit fullscreen mode

You got this. The AI turns raw repo data into a readable trend report โ€” no manual digging required.

Step 4: Post to a GitHub Issue

// lib/github.js
import axios from 'axios';

export async function postToIssue(repos, summary) {
  const body = `## ๐Ÿ Python Trending Repos โ€” ${new Date().toDateString()}

${summary}

### Top 10 Repos

${repos.map((r, i) => `${i + 1}. **[${r.name}](${r.url})** โ€” ${r.description}
   โญ ${r.stars} ยท ๐Ÿด ${r.forks} ยท ๐Ÿ”ฅ ${r.todayStars}`).join('\n\n')}

---

*Automated daily update via [github-trending-repos](https://github.com/vitalets/github-trending-repos)*`;

  await axios.post(
    `https://api.github.com/repos/vitalets/github-trending-repos/issues/7/comments`,
    { body },
    {
      headers: {
        Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
        'User-Agent': 'trending-bot'
      }
    }
  );
}
Enter fullscreen mode Exit fullscreen mode

Replace the owner/repo and issue number with your own. The comment gets posted right under the issue โ€” subscribers get notified automatically.

Step 5: Wire It All Together

// index.js
import cron from 'node-cron';
import { getTrendingPythonRepos } from './lib/scraper.js';
import { generateSummary } from './lib/summarizer.js';
import { postToIssue } from './lib/github.js';

async function run() {
  console.log('Fetching trending Python repos...');
  const repos = await getTrendingPythonRepos();

  console.log('Generating AI summary...');
  const summary = await generateSummary(repos);

  console.log('Posting to GitHub issue...');
  await postToIssue(repos, summary);

  console.log('โœ… Done!');
}

// Run daily at 9 AM
cron.schedule('0 9 * * *', run);

// Run immediately on first start
run();
Enter fullscreen mode Exit fullscreen mode

That's it. Three files, one cron job. Your bot is ready.

Adding Observability

This is where TracePilot comes in. When your bot fails at 3 AM (and it will โ€” GitHub rate limits, malformed HTML, API timeouts), you need to know why.

npm install tracepilot-sdk
Enter fullscreen mode Exit fullscreen mode

Now wrap your main function:

// index.js (updated)
import { TracePilot } from 'tracepilot-sdk';
import cron from 'node-cron';
import { getTrendingPythonRepos } from './lib/scraper.js';
import { generateSummary } from './lib/summarizer.js';
import { postToIssue } from './lib/github.js';

const tp = new TracePilot(process.env.TRACEPILOT_API_KEY);

async function run() {
  await tp.startTrace('python-trending-bot');

  const { result: repos } = await tp.wrapToolCall(
    'scrape-trending',
    () => getTrendingPythonRepos(),
    null, 1
  );

  const { result: summary } = await tp.wrapOpenAI(
    () => generateSummary(repos),
    [{ role: 'user', content: `Summarize: ${repos.map(r => r.name).join(', ')}` }],
    null, 2
  );

  await tp.wrapToolCall(
    'post-to-github',
    () => postToIssue(repos, summary),
    null, 3,
    true // destructive โ€” modifies GitHub state
  );
}

cron.schedule('0 9 * * *', run);
run();
Enter fullscreen mode Exit fullscreen mode

One line change per step. Now every scrape, every AI call, every GitHub post is tracked in your TracePilot Dashboard. When the bot fails, you see exactly where โ€” and you can fork the execution to test fixes without redeploying.

Next Steps

Your bot is live. Here's what to do next:

  1. Deploy it โ€” Use a free cron service like Cron-job.org or Railway. Set the three env vars (GITHUB_TOKEN, OPENAI_API_KEY, TRACEPILOT_API_KEY).
  2. Add error handling โ€” Wrap the scraper in a retry loop. GitHub's HTML changes sometimes.
  3. Extend to other languages โ€” Change the URL to /trending/javascript or /trending/rust. One line.
  4. Watch the dashboard โ€” Open tracepilotai.com/dashboard after the first run. You'll see the full execution tree.

You just built a production-grade trending repo notifier. No complex infrastructure, no Docker, no Kubernetes. Three files, one cron job, and a dashboard that shows you everything.

You got this.


Debugging AI agents shouldn't feel like reading The Matrix.
Join other engineers who are building reliable autonomous workflows in our community: TracePilot Discord

Top comments (1)

Collapse
 
topstar_ai profile image
Luis Cruz

I appreciate how the getTrendingPythonRepos function uses Cheerio to parse the GitHub trending page, and the use of axios to handle the HTTP requests. The implementation of the AI summary generator using OpenAI's API is also quite interesting, as it allows for a more human-readable summary of the trending repos. One potential improvement could be to add some error handling for cases where the API requests fail or the parsing doesn't work as expected. Have you considered adding any logging or monitoring to track the performance of the bot and identify potential issues?