1#!/usr/bin/env python323import os4import sys5import json6import asyncio7import aiohttp8import argparse9import subprocess10from typing import List11from dataclasses import dataclass121314try:15 _github_token = subprocess.check_output(['pass', 'dev/github.com/repo_token']).decode().strip()16except:17 _github_token = ""1819outlocker = asyncio.Lock()20headers={21 "X-GitHub-Api-Version": "2022-11-28",22 "Accept": "application/vnd.github+json",23 "Authorization": _github_token,24}2526@dataclass27class RepoInfo:28 name: str29 version: str30 commit: str = "unknown"3132async def list_tags(sess: aiohttp.ClientSession, repo: str, num: int = 3) -> List[RepoInfo]:33 info = list()34 resp = await sess.get(f"/repos/{repo}/tags", params={"per_page": num})35 assert resp.status == 200, await resp.text()36 data = await resp.json()37 async with outlocker:38 for i in range(min(num, len(data))):39 info.append(RepoInfo(40 name = repo,41 version=data[i].get("name"),42 commit = data[i].get("commit", {}).get("sha")43 ))44 return info4546async def list_releases(sess: aiohttp.ClientSession, repo: str, num: int=3) -> List[RepoInfo]:47 info = list()48 resp = await sess.get(f"/repos/{repo}/releases", params={"per_page": num})49 assert resp.status == 200, await resp.text()50 data = await resp.json()51 async with outlocker:52 for i in range(min(num, len(data))):53 info.append(RepoInfo(54 name = repo,55 version = data[i].get("tag_name")56 ))57 #print(f'{repo: <20} {data[i].get("name"): <30} {data[i].get("tag_name", "None")}')58 return info5960async def main():61 parser = argparse.ArgumentParser()6263 subparsers = parser.add_subparsers(dest="cmd")64 tags_cmd = subparsers.add_parser("tags")65 tags_cmd.add_argument("-n", "--num", default=3, type=int)66 tags_cmd.add_argument("repo", nargs='+')6768 releases_cmd = subparsers.add_parser("rels")69 releases_cmd.add_argument("-n", "--num", default=3, type=int)70 releases_cmd.add_argument("repo", nargs='+')7172 args = parser.parse_args()7374 async with aiohttp.ClientSession(base_url="https://api.github.com", headers=headers) as sess:75 if args.cmd == "tags":76 infos = await asyncio.gather(*[list_tags(sess, repo, args.num) for repo in args.repo])77 elif args.cmd == "rels":78 infos = await asyncio.gather(*[list_releases(sess, repo, args.num) for repo in args.repo])79 for line in infos:80 for info in line:81 print(f"{info.name: <20}\t{info.version: <30}\t{info.commit}")828384if __name__ == '__main__':85 asyncio.run(main())