最近 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 文件完成的。
具体操作分为三部分:
- CD:先切换到D盘下的当前目录
- gh-pages分支:创建docs目录,运行python生成各个课程目录下的md文件,还要复制仓库的README到index作为主页,之后使用mkdocs gh-deploy命令完成GitHub pages的部署,之后再删除site(网页)和docs(编译成网页前的课程目录)。
- 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语言算不上难。
参考资料: