ci, gh-pages, gh-deploy, github,

曲折的CI踩坑初记录 - mkdocs实现自动gh-deploy

DolorHunter DolorHunter Follow Apr 18, 2021 · 40 mins read

曲折的CI踩坑初记录 - mkdocs实现自动gh-deploy
Share this

最近 lib-hfut/lib-hfut 项目终于有人来提交PR了,Star数量也成长到了快一百,可喜可贺的同时也出现了新的问题。

因为之前都是我个人维护,因此只需要在本地使用Git完成仓库管理,之后再commit & push到GitHub的master分支(文件)和gh-pages分支(网页,通过mkdocs生成)即可。相当于我本地仓库与GitHub仓库是同级关系,只是因为GitHub位于公网并且24/7在线,因此需要把内容发布到GitHub上;GitHub并不完全是一个一般来讲的一对多的中心节点。

但是项目越来越大,整个仓库大小已经接近5G,因为考虑到我也没什么材料可上传了,并且已经在README中说明,如果需要PR请直接对GitHub仓库进行PR就行了,因此就直接把本地的仓库删除了。按照我的设想,我只要偶尔进行以下PR审核与merge就行了,甚至之后直接把管理帐号交给别人管理也行。

但是,前几天我突然发现自己忽略了其中的一个问题。PR合并后提交,虽然在master分支下的文件能够完成合并,但是在gh-pages并不能完成内容的更新。依然需要在GitHub上在完成PR的merge后,到本地pull以下master分支,之后再使用mkdocs工具手动进行gh-pages的更新;否则只要网页没有手动更新,即使有新提交的PR,通过网页查看内容的用户也无法发现有新的文件更新。

这就很不自动化了,岂不是我还要在找到下一个管理员前,还要在本地维护网页页面吗?不可能,懒人将视线转向CI,在GitHub上叫做GitHub Action,看看能不能依靠CI实现master分支有更新就自动完成网页构建。如果成功实现的话,那我之后只要在网页上手动进行PR(其实用CI自动PR也行),之后action就会自动构建网页,这样工作量就小了许多,本地也可以把文件删掉了。

之前自己写了个脚本用于对GitHub同步本地到master分支和gh-pages分支。是在Windows系统下使用 *.bat 文件完成的。

具体操作分为三部分:

  1. CD:先切换到D盘下的当前目录
  2. gh-pages分支:创建docs目录,运行python生成各个课程目录下的md文件,还要复制仓库的README到index作为主页,之后使用mkdocs gh-deploy命令完成GitHub pages的部署,之后再删除site(网页)和docs(编译成网页前的课程目录)。
  3. master分支:add添加文件到暂存区,commit提交文件到Git,push到远程目录(GitHub)的master分支。
D:
cd %~dp0

md docs
python gen-md.py
copy README.md .\docs\index.md
mkdocs gh-deploy
rmdir /s /q site docs

git add *
git commit -m "Add files via upload"
git push -f origin master

pause

我认为只要把这个脚本改一改,把需要用到的部分(上面脚本的第二部分)变成shell语法,再运行在GitHub Action上就行了吧。然后就开始了我的曲折踩坑之旅。

参考了一下用到python的GitHub action脚本,大概长这样。name为脚本名称;on为触发条件;jobs为执行内容,其中runs-on为运行此任务的的虚拟机,steps为任务的步骤,python任务通常包括建立,安装依赖,运行三部分。因此只要在依赖内写上mkdocs,再把上面脚本的第二部分改写为shell语法写到第三部分应该就行了。

# This is a basic workflow to help you get started with Actions
name: Update gh-pages
# Controls when the action will run. 
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - name: Set up Python 3.9
        uses: actions/setup-python@v2
        with:
          python-version: 3.9
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install mkdocs
      # Runs a set of commands using the runners shell
      - name: Update gh-pages
        run: |
          echo "hello world"
          python hello.py

第一版本的第三部分,单纯把bat语法改为shell语法:

 - name: Update gh-pages
  run: |
    mkdir docs
    python gen-md.py
    cp README.md ./docs/index.md
    mkdocs gh-deploy
    rm -rf site docs

错误如下,查 资料 后在首行加入了fetch(git fetch origin gh-pages:gh-pages)

! [rejected] master -> master (fetch first)
error: failed to push some refs to ''
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

第二版本的第三部分,加入了fetch,删除了旧的(本地)gh-pages分支,重新从github上fetch此分支:

 - name: Update gh-pages
  run: |
    git fetch origin gh-pages:gh-pages
    mkdir docs
    python gen-md.py
    cp README.md ./docs/index.md
    mkdocs gh-deploy
    rm -rf site docs

之后运行就没有问题了,但是网页的根目录(root url/repo url)变为了 lib-huft.github.io,虽然各个分页面没有问题,但是主页和主页跳转的页面地址都损坏了。我猜想是因为没有mkdocs gh-deploy的配置(mkdocs.yml):

site_name: 贵校课程资料民间整理
theme: readthedocs
repo_url: https://github.com/lib-hfut/lib-hfut

因此又在mkdocs gh-deploy后加入了 –config-file mkdocs.yml。但是并没有效果,比较奇怪。经过了很长时间的调试之后发现是因为没有设置相对目录的原因,改成–config-file ./mkdocs.yml就能正常运行了。不过本地执行时(相同版本)并不需要指定配置位置也可以正常完成配置,因此第一版无设置此内容。

这是第三版本的第三部分,修改了相对目录:

- name: Update gh-pages
  run: |
    git fetch origin gh-pages:gh-pages
    mkdir docs
    python gen-md.py
    cp README.md ./docs/index.md
    mkdocs gh-deploy --config-file ./mkdocs.yml
    rm -rf site docs

不由的说shell还是需要一些细心的,而且CI不太好调试。有时在同目录下不写相对目录可以正常执行(手动执行),有时又不行(通常是自动执行脚本任务下)。并且关于CI/shell的相关资料较少,查资料时相对其他编程语言的参考资料并不多。

最近看了看面试题中有关于你遇到的最难问题是什么,我觉得目前遇到的最大问题就是在查找解答时无资源,无法求助Google只能自己慢慢调试,就这个角度来看shell比py/java/c等语言要困难得多,虽然shell语言算不上难。

参考资料:

Join Newsletter
Get the latest news right in your inbox. We never spam!
DolorHunter
Written by DolorHunter
Developer & Independenet Blogger