Github Action 入坑指南
背景
今年目标之一是重构博客,完善知识体系的建设,榜样是docker_practice:
- 博客主题好看,star 有 19k 了
- Docker 内容很完善,肯定帮助了不少人
- docker_practice 仓库用到了很多自动化的技术,值得深入学习
总之,我想打造属于自己的博客,而且里面具有代表内容。
6 月底用vuepress-theme-hope重构完成之后,就一直计划迁移到 github pages,然后昨天想起这事就开干。
入门
大致看了下阮一峰老师的GitHub Actions 入门教程,对基本语法有个入门,和 Jenkins Pipeline 很像,有一个 workflow 的文件。
第一次实践
接着使用jenkey2011/vuepress-deploy快速尝试,很快第一次 Github Action 就成功了。
name: Build and Deployon: pushjobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@master - name: vuepress-deploy uses: jenkey2011/vuepress-deploy@master env: ACCESS_TOKEN: ${{ secrets.ACTION_DEPLOY_GITHUB }} TARGET_REPO: stelalae/blog TARGET_BRANCH: master BUILD_SCRIPT: yarn && yarn build BUILD_DIR: dist/
从图中看到累积耗时 3 分 51 秒,主要耗时阶段:
- Build jenkey2011/vuepress-deploy@master:主要是执行 jenkey2011/vuepress-deploy 中的Dockfile,包含 node、git 的编译安装,和环境变量的配置。
- vuepress-deploy:执行
BUILD_SCRIPT
,即上面配置的yarn && yarn build
,然后通过ACCESS_TOKEN
强制推送到TARGET_REPO
。
这个过程给我的体验是:
- 耗时很长:同样仓库本地打包才 30 秒,参考部门的 openmouse 仓库 jenkinsfile 才最长 2 分钟,可以看出 Docker 比宿主机多了少量无形的损耗。
- 存在
f
强制推送:这个因人因事而异,但我不喜欢f
,强迫症。
- 存在使用
Personal Access Token (PAT)
:虽 github 对 token 管理机制很完善,强迫症+1。
尝试优化
uses 替换为JamesIves/github-pages-deploy-action
我在搜索其他教程是,发现很多博主在使用JamesIves/github-pages-deploy-action,阅读文档之后发现支持 PAT、SSH 两种方式,后者符合我意。
初步改造 deploy.yml 文件,发现速度提升到 2 分 25 秒,可能是因为没有 node、git 的安装耗时。
name: Build and Deployon: pushjobs: github-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@master - name: Install and Build run: | yarn yarn build - name: Deploy uses: JamesIves/github-pages-deploy-action@4.1.4 with: ssh-key: ${{ secrets.DEPLOY_KEY }} repository-name: stelalae/blog branch: master folder: dist
接着进入问题分析环节:
问题 1:从下图看到
fatal: unable to access 'https://github.com/stelalae/blog.git/': The requested URL returned error: 403
,明明我是配置的 ssh-token,难倒不应该使用git@github.com:stelalae/blog.git
吗?- name: Deploy uses: JamesIves/github-pages-deploy-action@4.1.4 with: ssh-key: ${{ secrets.DEPLOY_KEY }} repository-name: stelalae/blog branch: master folder: dist
问题 2:我明明配置 token,为啥还提示
remote: Invalid username or password.
呢?而且反复检查 token 是存在的。- name: Deploy uses: JamesIves/github-pages-deploy-action@4.1.4 with: token: ${{ secrets.DEPLOY_KEY }} repository-name: stelalae/blog branch: master folder: dist
初步怀疑是配置问题,过程中进行如下的踩坑分析,比如:
secrets
的多次重命名
token
的多次重新生成
- constants.ts和util.ts的源码分析
结合两个 issue:Invalid username or password #624、Commit fails with “process ‘/usr/bin/git’ failed with exit code 128” #308,还是没有解决,于是怀疑这个 uses 本身的问题。但在 issue#308 中离答案已经很近了。
uses 替换为peaceiris/actions-gh-pages
(推荐)
这个仓库里有对不同Supported Tokens的对比,可仔细分析下。
name: GitHub Pageson: push: branches: - main - master pull_request:jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Install Dependencies run: yarn - name: Build run: yarn build - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: deploy_key: ${{ secrets.DEPLOY_SSH_TOKEN }} external_repository: stelalae/blog publish_dir: ./dist commit_message: ${{ github.event.head_commit.message }}
同样使用
ssh-token
方式,但提示Action failed with "not found deploy key or tokens"
,所以说我的token
压根就没配置正确???突然反应过来 github action 的中角色关系是:
- action 是在
blog_src
中执行,action 是模拟本地电脑往blog
推送 git commit。
- SSH 方式中
Private Key
要配置在blog_src
的Secrets,Public Key
要配置在blog
的Deploy Keys。
再次调整配置后,果然成功了!!!最后再去尝试
JamesIves/github-pages-deploy-action
也成功了,玛德!action/cache
github action 本质是建立在 Docker 运用的基础上,所以每次执行 action 都要新跑一个 Docker 实例,然后在里面执行仓库的本地动作,比如:
yarn install
、yarn build
等,这个和 gitlab CI/CD 是一样的本质。不同于在本地环境中,部分内容已经缓存到本地,比如
node_modules
,那么如何才能做到类似效果呢?好在 github 官方提供了action/cache,而且针对不同的环境和脚手架写了Implementation Examples
,比如node + yarn,结合Github Actions 总结,我的 cache 配置如下(完整的 deploy.yml):name: GitHub Pageson: push: branches: - main - master pull_request:jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Get Node Dependencies Directory Path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn cache dir)" - name: Cache Node Dependencies uses: actions/cache@v2 id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - name: Install Dependencies run: yarn - name: Build run: yarn build - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: deploy_key: ${{ secrets.DEPLOY_SSH_TOKEN }} external_repository: stelalae/blog publish_branch: master publish_dir: ./dist full_commit_message: ${{ github.event.head_commit.message }}
贴上使用了 cache 后效果,比之前缩短了
Install Dependencies
阶段的时间:自定义 Docker
从前面已经知道 action 本质是 docker 的运用,到目前为止都是使用的官方 docker:
ubuntu-latest
,那么我们是否可自定义 Docker 呢?答案是肯定的,请参考本文最开始提到的jenkey2011/vuepress-deploy,可在此基础上进一步优化。虽说自定义 Docker 在 github action 使用方面意义不太大,但可将此思路运用在工作中其他地方,所以赶紧学习 Docker 吧,首推我的博客榜样docker_practice!
action 与其他服务之间的联动
在多种 token 之间选择 ssh-token 的原因是:
- 信任 github 的 token 管理模型,即 secrets 机制
- ssh-token 可以作为不同服务之间授权凭据,然后可远程执行其他有意思的脚本
Deploying to a server via SSH and Rsync in a Github Action中介绍了shimataro/ssh-key-action的使用案例,
ssh-key-action
中还支持Install multiple keys,个人感觉这个比 jenkins 里面的凭据管理友好太多。结束语
本次从学习 github action,到从 action 爬出来,耗时 12 小时左右。
1、网上大部分 action 教程是针对同一仓库的不同分支操作,比如:master 是源码、gh-pages 是打包后的内容,而我是在不同仓库之间的使用。
2、问题根结还是对 action 中 ssh 方式的理解不到位,然后导致 token 的配置错误。关于 SSH keys 的更多信息。
3、熟悉了 YAML 文件,理解了 github 的不同 token 的作用。
4、收获了 action 原理的初步了解,思考了 action 在其他方面的运用,比如:其他 git 服务、Serverless 等。