之前因为 jsDelivr 的 ICP 备案突然被扬了,用第三方的服务总还是感觉不放心,于是自己整了个放静态资源的 CDN,速度和稳定性是有保障了,但是每次主题之类的有什么更新都要在 GitHub 上手动下载然后传到存储桶上,这对于我这样的懒狗绝对是不能接受的,于是开始考虑写脚本自动化这个流程。

检测仓库更新并下载到本地

使用 GitHub 官方提供的 API 获取仓库最新的 tag

def GetTagName(repo):
    response = requests.get(f"https://api.github.com/repos/{repo}/releases/latest")
    return response.json()["tag_name"]

与本地存储的 tag 进行对比,不同则使用 git clone 指定的 tag 版本到本地

def CheckRepo(repo,repo_name,local_tag):
    tag_name = GetTagName(repo)
    if tag_name != local_tag :
 
        SaveRepo(repo,repo_name,tag_name)
 
def SaveRepo(repo,repo_name,tag):
    os.system(f"git clone -b {tag} --depth=1 https://github.com/{repo}")

将克隆下来的文件根据 tag 归档,更新数据库中的本地 tag

os.rename(f"{root_path}/{repo_name}",f"{root_path}/lib/{repo_name}/{tag}")
conn.execute(f"UPDATE repo SET local_tag = '{tag}' WHERE repo = '{repo}'")

将归档文件同步到存储桶上

CDN 后端存储用的是腾讯云的对象存储 COS,本来是打算直接用 Python 上传的,但是在翻 COS 的 Python SDK 文档的时候,发现 COS 官方的命令行工具 COSCLI 自带了同步文件夹的功能,于是偷个懒直接用 COSCLI 上传,拿宝塔创建了个定时任务自动同步。

./coscli sync lib/ cos://bucket-appid/lib/ --exclude ".git" -r
rm -rf lib

Bark 推送及 Log 记录

最后简单整了个日志记录和 Bark 推送通知到手机。

def LogInit():
    logger_raw = logging.getLogger()
    logger_raw.setLevel(logging.INFO)
    formatter = logging.Formatter("[%(asctime)s] [%(levelname)s]: %(message)s")
    formatter.converter = lambda x: time.localtime(x + 28800 + time.timezone)
    console_handler = logging.StreamHandler(stream=sys.stdout)
    console_handler.setFormatter(formatter)
    logger_raw.addHandler(console_handler)
    try:
        file_handler = logging.FileHandler(log_file, encoding='utf-8')
        file_handler.setFormatter(formatter)
        logger_raw.addHandler(file_handler)
    except:
        ...
 
data = {"title":"RepoSync","body":f"已同步 {repo_name} 的 {tag} 版本"}
response = requests.post(url=bark_url,data=data)
str = json.loads(response.text)
if str['message'] == "success":
    logging.info("通知推送成功")
else:
    logging.warning("通知推送失败")

结语

第一次写 Python 程序,边查文档边百度花了半天才做出来,本地和服务器都测试通过没什么问题,不过没考虑网络波动等等问题,这玩意儿的稳定性还要用一段时间才知道。

顺便扔个 GitHub 地址,纯新手,没什么参考价值就是了。
OriLight152/RepoSync