This repository was archived by the owner on Aug 10, 2026. It is now read-only.
Update README Projects #16
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 Projects | |
| on: | |
| schedule: | |
| - cron: '0 5 * * 5' | |
| workflow_dispatch: | |
| repository_dispatch: | |
| types: [repo-created, repo-updated] | |
| jobs: | |
| update-readme: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout profile repo | |
| uses: actions/checkout@v4 | |
| - name: Fetch org repos and update README | |
| env: | |
| GH_TOKEN: ${{ secrets.ORG_TOKEN }} | |
| ORG_NAME: readme-SVG | |
| run: | | |
| python3 << 'EOF' | |
| import urllib.request | |
| import json | |
| import re | |
| import os | |
| org = os.environ["ORG_NAME"] | |
| token = os.environ["GH_TOKEN"] | |
| def gh_get(url): | |
| req = urllib.request.Request(url, headers={ | |
| "Authorization": f"Bearer {token}", | |
| "Accept": "application/vnd.github+json", | |
| "X-GitHub-Api-Version": "2022-11-28" | |
| }) | |
| with urllib.request.urlopen(req) as r: | |
| return json.loads(r.read()) | |
| SKIP = {f"{org}".lower(), ".github"} | |
| repos, page = [], 1 | |
| while True: | |
| url = f"https://api.github.com/orgs/{org}/repos?per_page=100&page={page}&sort=created&direction=asc" | |
| batch = gh_get(url) | |
| if not batch: | |
| break | |
| for r in batch: | |
| name_lower = r["name"].lower() | |
| if not r["archived"] and not r["fork"] and not r["private"] and name_lower not in SKIP: | |
| repos.append(r) | |
| page += 1 | |
| LANG_COLORS = { | |
| "Python": "#3572A5", | |
| "JavaScript": "#f1e05a", | |
| "TypeScript": "#2b7489", | |
| "HTML": "#E34F26", | |
| "CSS": "#563d7c", | |
| "Shell": "#89e051", | |
| "Go": "#00ADD8", | |
| "Rust": "#dea584", | |
| } | |
| def lang_badge(lang): | |
| if not lang: | |
| return "" | |
| color = LANG_COLORS.get(lang, "#888888").lstrip("#") | |
| label = lang.replace("-", "--").replace(" ", "_") | |
| return f"" | |
| def stars_badge(full_name): | |
| return ( | |
| f"[]" | |
| f"(https://github.com/{full_name}/stargazers)" | |
| ) | |
| rows = [] | |
| for r in repos: | |
| name = r["name"] | |
| full_name = r["full_name"] | |
| lang = r.get("language") or "" | |
| link = f"[**{name}**](https://github.com/{full_name})" | |
| rows.append( | |
| f"| {link} | {stars_badge(full_name)} | {lang_badge(lang)} |" | |
| ) | |
| table = "\n".join([ | |
| "| Project | Stars | Language |", | |
| "|:-------:|:-----:|:--------:|", | |
| *rows, | |
| ]) | |
| block = ( | |
| "<!-- PROJECTS_START -->\n" | |
| "<div align=\"center\">\n\n" | |
| + table + "\n\n" | |
| "</div>\n" | |
| "<!-- PROJECTS_END -->" | |
| ) | |
| readme_path = "profile/README.md" | |
| with open(readme_path, "r", encoding="utf-8") as f: | |
| content = f.read() | |
| pattern = r"<!-- PROJECTS_START -->.*?<!-- PROJECTS_END -->" | |
| if re.search(pattern, content, re.DOTALL): | |
| updated = re.sub(pattern, block, content, flags=re.DOTALL) | |
| else: | |
| updated = re.sub( | |
| r"(## 📦 Projects\s*)(.*?)(\n---)", | |
| r"\1\n" + block + r"\3", | |
| content, | |
| flags=re.DOTALL | |
| ) | |
| with open(readme_path, "w", encoding="utf-8") as f: | |
| f.write(updated) | |
| print(f"✅ Updated {len(repos)} repos") | |
| EOF | |
| - name: Commit if changed | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git diff --quiet && echo "No changes" && exit 0 | |
| git add profile/README.md | |
| git commit -m "chore: auto-update projects table [skip ci]" | |
| git push |