Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

How to Find Stale GitHub Issues in Python

Filter a list of GitHub issues to find those not updated within a configurable number of days using Python datetime arithmetic.

Easy Python 3.9+ Jun 28, 2026 Automation & scripting 18 views 0 copies

Python code

47 lines
Python 3.9+
import os
from datetime import datetime, timezone, timedelta
import re

# Simulated GitHub issue data structure
SAMPLE_ISSUES = [
    {"number": 101, "title": "Login button not working", "updated_at": "2025-06-01T12:00:00Z", "assignee": "alice"},
    {"number": 102, "title": "Fix database migration error", "updated_at": "2025-10-20T08:30:00Z", "assignee": None},
    {"number": 103, "title": "Update API documentation", "updated_at": "2025-10-15T14:15:00Z", "assignee": "bob"},
    {"number": 104, "title": "Refactor authentication module", "updated_at": "2025-09-01T09:00:00Z", "assignee": None},
]

STALE_DAYS = 30  # Consider issues stale if not updated in this many days

def parse_github_date(date_str):
    """Parse GitHub ISO 8601 date string to datetime object."""
    # Remove trailing Z and add UTC timezone
    if date_str.endswith('Z'):
        date_str = date_str[:-1] + '+00:00'
    return datetime.fromisoformat(date_str)

def is_stale(issue, stale_days):
    """Check if an issue is stale based on last update time."""
    last_updated = parse_github_date(issue["updated_at"])
    now = datetime.now(timezone.utc)
    return now - last_updated > timedelta(days=stale_days)

def find_stale_issues(issues, stale_days=STALE_DAYS):
    """Filter list of issues to find only stale ones."""
    stale_issues = []
    for issue in issues:
        if is_stale(issue, stale_days):
            stale_issues.append(issue)
    return stale_issues

if __name__ == "__main__":
    stale_issues = find_stale_issues(SAMPLE_ISSUES)
    
    print(f"Checking for issues stale more than {STALE_DAYS} days...\n")
    
    if not stale_issues:
        print("No stale issues found.")
    else:
        print(f"Found {len(stale_issues)} stale issue(s):\n")
        for issue in stale_issues:
            assignee = issue.get("assignee", "unassigned")
            print(f"  #{issue['number']}: {issue['title']} (last updated: {issue['updated_at']}, assignee: {assignee})")

Output

stdout
Checking for issues stale more than 30 days...

Found 2 stale issue(s):

  #101: Login button not working (last updated: 2025-06-01T12:00:00Z, assignee: alice)
  #104: Refactor authentication module (last updated: 2025-09-01T09:00:00Z, assignee: unassigned)

How it works

The script parses GitHub's ISO 8601 date strings into datetime objects using datetime.fromisoformat() after converting the trailing 'Z' to '+00:00'. It subtracts the parsed update time from the current UTC time and compares the resulting timedelta to a stale_days threshold. The is_stale helper encapsulates the check, and find_stale_issues builds a filtered list. This approach works entirely with the Python standard library so no third-party packages are needed.

Common mistakes

  • Forgetting to handle the trailing 'Z' in GitHub's date strings before parsing with `fromisoformat`.
  • Comparing naive datetimes without timezone info to aware datetimes, causing a `TypeError`.
  • Hardcoding the stale-days threshold instead of making it a parameter like `stale_days`.

Variations

  1. Use `dateutil.parser.isoparse` from the `python-dateutil` package for more robust date parsing.
  2. Wrap the logic in a class like `StaleIssueDetector` to manage configuration and issue data together.

Real-world use cases

  • Running a weekly cron job to tag issues that haven't been updated in 30 days and assign them to a triage team.
  • Integrating into a CI/CD pipeline that auto-closes stale PRs or issues after a grace period.
  • Building a dashboard widget that highlights inactive items across your repositories for maintainers.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Automation & scripting

Related tutorials and quizzes for this topic.