开始使用 note 做笔记后,大事小事都记录在笔记里,已经不怎么屁大点事都会发博客了。
痛点在于,需要手动同步文章和关联的图片到博客项目,push 到 github 后,触发自动部署更新静态页面。
想做一个类似点击公开,自动分享到博客项目的持续继承功能。
设想如下:
- 本身 markdown 有 attribute 数据。
 - 增加 article: true 表示是需要发表到博客的项目。
 - 每次提交的时候,通过 github 提供的免费的 CI 功能 actions,扫描带有 article: true 的 markdown 文件, 发送到博客项目单独分支。
 - 博客项目生成一个 pr , 方便检查文章格式等,通过人工审核后,同意合并至 master 分支,更新静态页面。
 
下面讲讲各个步骤细节,方便大佬们抄作业。
博客项目 同步相关
博客相关 actions 配置
- 需要获取一个提交用的 github token , 我这里设置的名称为 blog_sync
 
name: sync-note
on:
  push:
    branches:
      - develop # Change this to your default branch
    paths:
      - "note/docs/articles/*.md"
jobs:
  make-html-send-email:
    name: make-time-file
    runs-on: ubuntu-latest
    steps:
      - name: get blog repository
        uses: actions/checkout@master
      - run: |
          cd ..
          git config --global user.email "z740713651@outlook.com"
          git config --global user.name "AngusWG"
          git config --global credential.helper cache
          git clone https://${{secrets.blog_sync}}@github.com/AngusWG/AngusWG
          cd AngusWG
          git checkout dev_auto 2>/dev/null || git checkout -b dev_auto
      - name: cd into note repo
        run: cd ../WG & pwd
      - name: install python script requirement
        run: pip install .
      - name: run the script sync note to blog repo 
        run: python wg sync_note note /home/runner/work/WG/AngusWG/docs
      - name: commit note
        run: |
          cd /home/runner/work/WG/AngusWG
          git add .
          git commit -m "sync note $(date +"%Y-%m-%d %H:%M:%S")" || true
          git push origin dev_auto
同步博客的 python 脚本
- 直接用的话 需要做入参适当修改。
 - 设置 article: true 的文章会自动发表到博客。
 - 当 date 不一样时,会自动同步笔记的内容到博客。
 
需要笔记文件夹和博客有以下目录结构
- sorce_note_dir: 笔记文件夹
- articles: 可以发布的文章文件夹
- a.md (article: true)
 - b.md (article: true)
 - c.md (article: false)
 
 - images: 笔记图片文件夹
- a1.png
 - a2.png
 - c1.png
 
 
 - articles: 可以发布的文章文件夹
 - target_note_dir: 笔记文件夹
- articles: 已经发布的博客文件夹
- a.md (article: true)
 - b.md (article: true)
 
 - images: 博客图片文件夹
- a1.png
 - a2.png
 
 
 - articles: 已经发布的博客文件夹
 
#!/usr/bin/env python
# encoding: utf-8
# @Time   : 2022/04/18 18:22:22
# @author : zza
# @Email  : z740713651@outlook.com
# @File   : sync_markdown_note.py
"""同步笔记用"""
import os
import frontmatter
import re
import shutil
default_dir = "articles"
article_attribute = "article"
def _need_sync(file_path: str, output_dir: str) -> bool:
    """
    判断是否要同步笔记
    1 笔记里存在 属性 publish:true
    2 笔记日期 > 已发布笔记日期
    """
    post = frontmatter.load(file_path)
    # publish
    if not post.get(article_attribute):
        return False
    # update date
    old_file = os.path.join(output_dir, default_dir, os.path.basename(file_path))
    if os.path.exists(old_file):
        current_date = post.get("date")
        old_date = frontmatter.load(old_file).get("date")
        if current_date == old_date:
            return False
    return True
def sync_pic(file_path: str, output_dir: str) -> None:
    """copy pic to output dir"""
    # find pic in markdown file
    with open(file_path, "r", encoding="utf-8") as f:
        markdown_body = f.read()
    pic_str_list = re.findall(r"\!\[.*\]\((.*)\)", markdown_body)
    for pic_str in pic_str_list:
        print(f"  find pic {pic_str}")
        pic_file = os.path.join(os.path.dirname(file_path), pic_str)
        if not os.path.exists(pic_file):
            continue
        # copy pic
        output_pic_file = os.path.join(output_dir, "images", os.path.basename(pic_file))
        print(f"  copy {os.path.abspath(pic_file)} to {output_pic_file}")
        shutil.copyfile(pic_file, output_pic_file)
    return
def handler_file(root: str, file: str, output_dir: str) -> None:
    """处理单个 markdown 文件"""
    file_path = os.path.join(root, file)
    if not _need_sync(file_path, output_dir):
        return
    # copy file
    output_file_path = os.path.join(output_dir, default_dir, file)
    print(f"copy {file_path} to {output_file_path}")
    shutil.copyfile(file_path, output_file_path)
    # copy pic
    sync_pic(file_path, output_dir)
def main(
    markdown_path: str = r"E:\PycharmProjects\WG\note",
    output_dir: str = r"E:\PycharmProjects\AngusWG\docs",
) -> None:
    """
    遍历 note 文件夹 articles 文件夹下所有的 md 文件
    并同步到另一边文件夹下的 articles 文件夹下
    - sorce_note_dir: 笔记文件夹
      - articles: 可以发布的文章文件夹
        - a.md (article: true)
        - b.md (article: true)
        - c.md (article: false)
      - images: 笔记图片文件夹
        - a1.png
        - a2.png
        - c1.png
    - target_note_dir: 笔记文件夹
      - articles: 已经发布的博客文件夹
        - a.md (article: true)
        - b.md (article: true)
      - images: 博客图片文件夹
        - a1.png
        - a2.png
    """
    # walk directory
    root = os.path.join(markdown_path, default_dir)
    for file  in os.listdir(root):
        if file.endswith(".md"):
            handler_file(root, file, output_dir)
if __name__ == "__main__":
    main()
    # handler_file(
    #     r"E:\PycharmProjects\WG\note\docs\创作",
    #     "笔记自动发布。md",
    #     r"E:\PycharmProjects\AngusWG\docs",
    # )
博客项目生成 pr
name: SYNC NOTE
on:
  push:
    branches:
      - dev_auto
jobs:
  SYNC_NOTE:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: master
      - run: ls
      - name: Reset main branch
        run: |
          git fetch origin dev_auto:dev_auto
          git reset --hard dev_auto
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v4
        id: cpr
        with:
          commit-message: publish note to blog
          title: sync note pull request
          body: $(date +"%Y-%m-%dT%H:%M:%S%z")
          branch: dev_auto
          base: master
小坑:
报错 Branch 'X' no longer differs from base branch 'Y'
actions 好像将本地的分支提交一次,最开始的时候写错了, 导致反向 master 覆盖了 dev_auto 分支, 然后因为没有 git fetch ,认为无修改不生成 pr。 看 action 日志+看 issus 解决的。 action 的运行方式有点想当然了。
总结
最开始想用 tag: publish 去识别是否要发布,但是刷 attribute 的脚本不支持增加,支持覆盖, 想了想还是新弄个属性,反正人也看不到。
目前还有一个问题是,这个 action 是每次提交就会检测一遍,然后装 python 依赖的时候,其实挺慢的, 找了一下,并没有限制最小部署间隔的参数(有知道的小伙伴请告诉我)想想机器又不累,不要在乎这么多。