Update README on New Issues #48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Update README on New Issues | |
| on: | |
| schedule: | |
| # Run every Thursday at 00:00 UTC | |
| - cron: '0 0 * * 4' | |
| issues: | |
| types: [opened] | |
| workflow_dispatch: # Allow manual trigger | |
| jobs: | |
| update-readme: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| issues: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.x' | |
| - name: Check for new issues and update README | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| python - <<'EOF' | |
| import os | |
| import re | |
| import json | |
| import subprocess | |
| from datetime import datetime, timedelta | |
| # GitHub API setup | |
| github_token = os.environ['GITHUB_TOKEN'] | |
| repo = os.environ['GITHUB_REPOSITORY'] | |
| # Function to get issues from the last week | |
| def get_recent_issues(): | |
| # Check if triggered by issue event | |
| event_name = os.environ.get('GITHUB_EVENT_NAME') | |
| if event_name == 'issues': | |
| # Get the issue that triggered this workflow | |
| with open(os.environ['GITHUB_EVENT_PATH'], 'r') as f: | |
| event_data = json.load(f) | |
| issue = event_data.get('issue', {}) | |
| if issue: | |
| return [issue] | |
| else: | |
| # For scheduled runs, get issues from the last week | |
| one_week_ago = (datetime.now() - timedelta(days=7)).isoformat() | |
| cmd = f'''curl -s -H "Authorization: token {github_token}" \ | |
| "https://api.github.com/repos/{repo}/issues?state=all&since={one_week_ago}&sort=created&direction=desc"''' | |
| result = subprocess.run(cmd, shell=True, capture_output=True, text=True) | |
| issues = json.loads(result.stdout) | |
| # Filter for issues created in the last week | |
| recent_issues = [] | |
| for issue in issues: | |
| created_at = datetime.strptime(issue['created_at'], '%Y-%m-%dT%H:%M:%SZ') | |
| if created_at > datetime.now() - timedelta(days=7): | |
| recent_issues.append(issue) | |
| return recent_issues | |
| return [] | |
| # Function to parse issue title | |
| def parse_issue_title(title): | |
| # Expected format: "2025.08.27 - #48 - WALL-OSS, ORB-SLAM-Python, Robix, ..." | |
| # More strict pattern matching to ensure exact format | |
| pattern = r'^(\d{4}\.\d{2}\.\d{2})\s*-\s*#(\d+)\s*-\s*(.+)$' | |
| match = re.match(pattern, title) | |
| if match: | |
| date_str = match.group(1) | |
| issue_num = match.group(2) | |
| topics_str = match.group(3).strip() | |
| # Keep date format as is (YYYY.MM.DD) | |
| formatted_date = date_str | |
| # Clean up topics - preserve the comma-separated format | |
| topics = ', '.join([t.strip() for t in topics_str.split(',')]) | |
| return formatted_date, topics, issue_num | |
| return None, None, None | |
| # Function to update README | |
| def update_readme(new_entries): | |
| if not new_entries: | |
| print("No new issues to add to README") | |
| return False | |
| # Read current README | |
| with open('README.md', 'r') as f: | |
| content = f.read() | |
| # Find the table - match table with proper row endings | |
| table_pattern = r'(\|Date\|Topics\|Link\|Video\|\n\|[-]+\|[-]+\|[-]+\|[-]+\|(?:\n\|[^\n]+\|)*)' | |
| match = re.search(table_pattern, content) | |
| if not match: | |
| print("Could not find the table in README.md") | |
| return False | |
| table_content = match.group(1) | |
| # Parse existing entries to check for duplicates and maintain order | |
| existing_entries = [] | |
| lines = table_content.strip().split('\n') | |
| for line in lines[2:]: # Skip header lines | |
| if line.strip() and line.startswith('|'): | |
| existing_entries.append(line) | |
| # Check for duplicates and add new entries | |
| added_count = 0 | |
| new_rows = [] | |
| for entry in new_entries: | |
| # Check if this issue is already in the table | |
| issue_link = f"[meeting log]({entry['link']})" | |
| if not any(issue_link in row for row in existing_entries): | |
| new_row = f"|{entry['date']}| {entry['topics']} |{issue_link}| |" | |
| new_rows.append(new_row) | |
| added_count += 1 | |
| print(f"Added new entry: {entry['date']} - {entry['topics']}") | |
| if added_count == 0: | |
| print("All issues already exist in the table") | |
| return False | |
| # Combine all entries and sort by date | |
| all_rows = existing_entries + new_rows | |
| # Sort entries by date (assuming YYYY.MM.DD format) | |
| def get_date_key(row): | |
| date_match = re.search(r'\|(\d{4}\.\d{2}\.\d{2})\|', row) | |
| if date_match: | |
| return date_match.group(1) | |
| return '9999.99.99' # Put malformed rows at the end | |
| all_rows.sort(key=get_date_key) | |
| # Rebuild the table with proper formatting | |
| header = "|Date|Topics|Link|Video|\n|------|---|---|---|" | |
| sorted_rows = '\n'.join(all_rows) | |
| new_table = f"{header}\n{sorted_rows}" | |
| # Replace old table with new table | |
| new_content = content.replace(table_content, new_table) | |
| # Write updated README | |
| with open('README.md', 'w') as f: | |
| f.write(new_content) | |
| print(f"Successfully added {added_count} new entries to README.md") | |
| return True | |
| # Main execution | |
| recent_issues = get_recent_issues() | |
| if not recent_issues: | |
| print("No new issues found") | |
| exit(0) | |
| new_entries = [] | |
| for issue in recent_issues: | |
| # Skip pull requests | |
| if 'pull_request' in issue: | |
| continue | |
| date, topics, issue_num = parse_issue_title(issue['title']) | |
| if date and topics: | |
| new_entries.append({ | |
| 'date': date, | |
| 'topics': topics, | |
| 'link': issue['html_url'] | |
| }) | |
| print(f"Processing issue #{issue_num}: {date} - {topics}") | |
| else: | |
| print(f"Issue '{issue['title']}' does not match expected format, skipping") | |
| if new_entries: | |
| if update_readme(new_entries): | |
| print("README.md has been updated") | |
| else: | |
| print("No updates needed for README.md") | |
| else: | |
| print("No valid issues to process") | |
| EOF | |
| - name: Commit and push changes | |
| run: | | |
| git config --local user.email "action@github.com" | |
| git config --local user.name "GitHub Action" | |
| # Check if there are changes | |
| if git diff --quiet; then | |
| echo "No changes to commit" | |
| else | |
| git add README.md | |
| git commit -m "Update README.md with new issue information" | |
| git push | |
| echo "Changes pushed to repository" | |
| fi |