Hexo 实现 Github/Coding 持续集成
文章最初载于 szhshp 的第三边境研究所
转载请注明
开发背景
- 为知笔记的搜索太慢了。
- 我想要迁移笔记。
- 我想要迁移笔记。
- 我想要迁移笔记。
- 我想要迁移笔记。
- 我想要迁移笔记。
- 我想要迁移笔记。
- 我想要迁移笔记。
- 我想要迁移笔记。
- 我很需要迁移笔记。
- 为知笔记的搜索太慢了。
- 希望能有一个免费的笔记托管平台。
Github & Coding 的服务差异
主要配置:
- 一个 Source Repo, 用于存放源码
- 一个 Release Repo, 用于存放 build 之后的 pages 文件
Pages 服务的限制:
- Github 的 pages 服务 repo 必须设置为开源, 因此 Source Repo 可以设置为闭源
- Coding 的 pages 服务 repo 没有任何限制, 所以 两个都可以设置为闭源.
其他 CI/CD 服务的限制:
- Travis 可以用于 Github, 但是不能用于国内的 Coding
- https://travis-ci.org 不支持私有仓库, https://travis-ci.com 才支持选择私有仓库 (但是对于私有仓库只有 100 次次数限制)
最终决定:
- Github 端使用 Github Actions
- Coding 端使用新开放的
持续集成
功能, 类似 Github Actions
Hexo 站点搭建
(略)
Github 操作方法
主要目的:
- 创建一个 Github Action
- 当我 push 代码的时候自动 build
- 由于 hexo 自身就有用 deploy 的功能, 所以只需要在 push 的时候执行以下
hexo deploy
将生成的文件全部部署到 Release Repo - 需要实现从 Source Repo 中提交到 Release Repo 的认证
- 最大的麻烦就是这一步
认证模式: SSH
生成一对公钥和私钥
公钥放置在 请求操作端: 本机或者远程服务器 (一般放置在 .ssh/rsa_id)
私钥放置在 目标端, 可以放在两个地方:
- 如果放置在用户级别的私钥处设置 (Github-Setting-SSH and GPG Keys), 那么可以不需要账号密码操作整个用户的所有 repo
- 如果放置在单个 repo 的 deploy key 中, 那么如果拥有这个私钥, 就可以不需要账号密码操作单个 repo
设置 SSH
我们这里实现单个 repo 的 SSH 访问
首先本地使用 ssh-keygen 可以生成一个私钥, 一个公钥
首先跑到 bash 里面执行 ssh-genkey
如果是 windows 系统, 就可以直接跑到
${GitDirectory}\usr\bin\ssh-keygen.exe
然后使用 管理员权限 + CMD 执行
最后生成了一个公钥 TESTKEY.PUB
, 一个私钥 TESTKEY
.
将生成的 私钥全部内容 (不要担心格式) 放置在 Source Repo 的 Serect 里面, 然后取一个名字, 比如我给他取名成 DEPLOY_KEY
然后将 公钥全部内容 放置到 Release Repo 的 Deployed Keys 里面, 并且要赋予读写的权限, 公钥的名字不重要
这个公钥并不是放置在用户的公钥设置里面, 我们仅仅对 Release Repo 进行操作
_config.yml 设置
这一段代码放置在 Source Repo 里面. 下方设置了对应的 Release Repo 的名字以及对应的分支名字.
deploy:
type: git
repo: git@github.com:szhielelp/notebook-release.git # 改成你自己的 repo 地址,需要设置 SSH 地址。
branch: master # 改成你自己的分支名称。
设置完之后本地测试一下
hexo d
因为对应的私钥同时也保存在本地, 所以应该可以部署成功.
创建 Github Action
跑到 Github Action 的页面创建一个新的 action, 然后这个 action 就会被放置在 Repo 的根目录的 .github/workflows/nodejs.yml
文件夹下面
name: Notebook Deployment
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x]
steps:
- name: Deployment Start
uses: actions/checkout@v1
- name: Setup Node ${{matrix.node-version}}
uses: actions/setup-node@v1
with:
node-version: ${{matrix.node-version}}
- name: Setup Git Env
env:
DEPLOY_KEY: ${{secrets.DEPLOY_KEY}} # 这里写上刚才在 Secret 里面设置的变量名
run: |
mkdir -p ~/.ssh/
echo "$DEPLOY_KEY" > ~/.ssh/id_rsa # 将私钥的全部内容输出到一个文件里面。
chmod 600 ~/.ssh/id_rsa # 修改对应私钥文件的权限。
ssh-keyscan github.com >> ~/.ssh/known_hosts # 将 Github.com 添加到已知文件列表。
git config --global user.name "你的 Github 用户名" # 设置一下提交的姓名和邮箱。
git config --global user.email "你的 Github 邮箱"
- name: Setup Hexo CI
run: |
npm i -g hexo-cli # 全局安装需要的库。
npm i
- name: Setup other package
run: |
npm install
- name: Deploy
run: |
rm -rf .deploy_git
hexo g && hexo deploy # 开始部署
rm ~/.ssh/id_rsa
Coding 操作方法
主要目的基本相同, 但是选用的一个完全不同的认证方法
SSH 认证模式的问题
理论上按照 github 的模式可以实现, 但是 SSH 模式请求的时候一直报 Permission denied (publickey)
我说尝试过的方法:
- 修改权限为 7, Github 上方脚本里面设置的权限为 6
- 生成一对完全不同的新的公钥
- 使用 ssh-add 将添加公钥到设备
- 公钥对于 git.coding.net 无效,应该改成 e.coding.net
最终发现用户级别公钥可以实现本地的部署, 但是无法实现 repo 之间的部署, 一直出现 Permission denied (publickey)
最终决定选用另一种认证方式.
2020-03-23 更新: Alliot 同学实现了 SSH 认证方法, 但是他是最终通过 scp 提交到他自己的服务器。和我的需求不同, 有需要可以查看一下: https://www.iots.vip/post/hexo-coding-ci-scp-server.html
认证模式: Token
-
首先创建一个 token
-
是在 repo - 开发者选项 - 项目令牌里面生成
- 这个东西生成一次就无法再看到了, 一定要复制保存
-
Token 也可以放在两个地方: 一个是用户级的 Token 可以操作所有 Repo, 一个是 Repo 级的 token 只能操作单个 repo
Config.yml 设置
同样的, 在 Source Repo 那边设置:
注意, 下方需要设置的是 HTTPS 的链接, 然后需要将你得到的 token 的账号密码扔进去.
deploy:
type: git
repo: https://[token name]:[token password]@e.coding.net/szhshp/szhshp-notebook-release.git
branch: master
同样现在本地测试一下, 这种模式上并没有使用任何的 SSH 访问, 直接就可以部署成功
创建持续集成任务
因为这个地方没有使用 SSH 访问, 并且 token 已经设置到了上方的链接当中, 直接 push 即可.
pipeline {
agent any
stages {
stage('检出') {
steps {
checkout([$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]],
userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]])
}
}
stage('构建') {
steps {
echo '构建中。..'
sh '''
git config --global user.name szhshp
git config --global user.email szhshp@sina.com
npm i -g hexo-cli
npm i
rm -rf .deploy_git
hexo g && hexo deploy
'''
echo '构建完成。'
}
}
}
environment {
HOSTINFO = 'Host coding.net IdentityFile ~/.ssh/id_rsa.coding User szhshp'
}
}
Troubleshoot
版本不同
建议在脚本的前三行写上, 这样调试的时候可以先确定是否是因为版本不同的问题导致的。
node -v
npm -v
yarn -v
Hint-考虑使用 cnpm 或 yarn
本身在本地调试的时候使用 cnpm 下载一些库 (比较典型的就是 sass 的 loader) 就非常慢, 换到 Coding 服务器用 npm 可能也很慢.
因此在这个时候可以考虑一下在扣钉上使用 cnpm 或者 yarn, 一个 cnpm 的例子:
下面这一段是放到可视化编辑框里面的, 如果直接粘贴到 Jenkin 脚本, 记得将里面的单引号进行转义。
cd clientV2
npm install cnpm -g
cnpm install
cnpm run build
git clone https://{token name}:{token pswd}@e.coding.net/szhshp/notebook/release.git
mv dist/* release/
cd release
git config user.email "szhshp@sina.com"
git config user.name "szhshp"
git add -A
git commit -a -m "Build & Release"
git push
另外也可以考虑换用 yarn
Nice Work !!!
花了我三天, 搞定了累死我了
Coding 单 Repo 多仓库操作方法
Coding 更新后, 一个项目里面可以有多个仓库
实际上就是多个 Repo
在这种情况下完全可以只用一个项目控制 Source Repo 和 Release Repo
处理方法很简单:
- 因为是同一个 Repo, 在 Repo 里面创建一个项目 Token
- 将 _config.yml 里面 deploy 一列的 repo 改为 release 仓库对应的 HTTPS 连接, 记得带上 token
deploy:
type: git
repo: https://{token name}:{token pswd}@e.coding.net/szhshp/szhshp-notebook/release.git
branch: master
- CI 脚本如上文设置 Coding 操作方法
- 这样子以后就不需要了来回跑两个不同的 repo 了
参考文献
- https://www.iots.vip/post/hexo-ci-wiki.html
- https://segmentfault.com/a/1190000002900848
- https://blog.csdn.net/qq_33619378/article/details/81191564
- https://zhuanlan.zhihu.com/p/26625249
- https://hexo.io/zh-cn/docs/commands.html
- https://www.jianshu.com/p/5691815b81b6
- https://www.voidking.com/dev-hexo-travis-ci/
- https://www.cnblogs.com/milovetingting/p/12159100.html
- https://hdj.me/github-actions-hexo-cicd/
- https://yanyinhong.github.io/2017/05/02/How-to-insert-image-in-hexo-post/