Github Action 入坑指南

date
Aug 8, 2021
slug
seafcpkm
status
Published
tags
Github
summary
type
Post
 

背景

今年目标之一是重构博客,完善知识体系的建设,榜样是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/
notion image
从图中看到累积耗时 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
notion image
接着进入问题分析环节:
问题 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
notion image
问题 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
notion image
初步怀疑是配置问题,过程中进行如下的踩坑分析,比如:
  • secrets的多次重命名
  • token的多次重新生成
结合两个 issue:Invalid username or password #624Commit fails with “process ‘/usr/bin/git’ failed with exit code 128” #308,还是没有解决,于是怀疑这个 uses 本身的问题。但在 issue#308 中离答案已经很近了。

uses 替换为peaceiris/actions-gh-pages(推荐)

又把uses切换为 2.2k star 的peaceiris/actions-gh-pages,根据文档配置改动deploy.yml
这个仓库里有对不同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 }}
notion image
同样使用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_srcSecretsPublic Key要配置在blogDeploy Keys
再次调整配置后,果然成功了!!!最后再去尝试JamesIves/github-pages-deploy-action也成功了,玛德!

action/cache

github action 本质是建立在 Docker 运用的基础上,所以每次执行 action 都要新跑一个 Docker 实例,然后在里面执行仓库的本地动作,比如:yarn installyarn 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阶段的时间:
notion image

自定义 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 官方市场awesome actions中找感兴趣的内容进行研究。比如:ssh deploy

结束语

本次从学习 github action,到从 action 爬出来,耗时 12 小时左右。
1、网上大部分 action 教程是针对同一仓库的不同分支操作,比如:master 是源码、gh-pages 是打包后的内容,而我是在不同仓库之间的使用。
2、问题根结还是对 action 中 ssh 方式的理解不到位,然后导致 token 的配置错误。关于 SSH keys 的更多信息
3、熟悉了 YAML 文件,理解了 github 的不同 token 的作用。
4、收获了 action 原理的初步了解,思考了 action 在其他方面的运用,比如:其他 git 服务、Serverless 等。

参考资料


© 刘德华 2020 - 2023