背景
GitHub Pages 相信大家都不陌生,它是 GitHub 推出的一项静态站点托管服务,能将 GitHub 仓库中的 HTML、CSS 等发布为网站,也可以通过 Jekyll 将 Markdown 创建为静态网站。让没有主机的人,可以把产品的首页、个人博客免费托管在 GitHub Pages 上。GitHub Pages 还提供了二级域名,个人首页为 https://username.github.io
,项目首页为 http://username.github.io/repository
。
GitHub Actions 则是 GitHub 前段时间推出的自动化流程工具,可以用于执行 CI/DI (持续集成和持续部署)作业等。
Nuxt 经常读我博客的朋友一定都很熟悉了,我的博客就是使用 Nuxt 开发的,它是一款基于 Vue.js 的 Web 框架,提供了包括 SSR(服务器端渲染)、静态化等功能。
通常而言,GitHub Pages 可以通过已经编写好的静态 HTML 以及 Markdown 生成,这就意味着如果我们的站点是使用诸如 Vue.js 这样动态化的技术开发的话,GitHub Pages 是无法正确处理 .vue
这样的文件的,必须经过编译(例如执行 npm run build
)生成 HTML 和 JavaScript 等文件才可以部署到 GitHub Pages 上。
每次修改网站内容后还得手动 build 并将生成的内容 commit 到相关仓库中,繁琐且不够智能,不过正好可以借助 GitHub Actions 来自动化这个步骤。
思路很简单,准备两个仓库,一个用于存放 Nuxt 站点源代码,另一个用于存放生成好的静态文件。当我们修改了源代码的仓库后,触发 GitHub Actions 的构建动作,并将构建生成的静态文件提交到静态文件仓库即可。
本文以自动生成个人首页 huhubun.github.io
这个站点为例,站点源代码仓库为 https://github.com/huhubun/huhubun.github.io-source,静态文件仓库为 https://github.com/huhubun/huhubun.github.io,最终效果可以访问 https://huhubun.com/ 查看。
创建仓库
首先将上述的两个仓库创建好:
huhubun.github.io
仓库:用于存放生成的静态文件。因为是个人首页,仓库名称要满足 GitHub Pages 的命名规范username.github.io
huhubun.github.io-source
仓库:用于存放站点的源代码。在站点名称后面增加了-source
后缀,便于区分。Nuxt 项目的页面代码往这里提交
站点创建好后,将源代码提交。
为静态文件仓库启用 GitHub Pages
默认情况下 GitHub Pages 是不激活的,打开 GitHub 网页,进入静态文件仓库后点击 Settings
进入仓库的设置页面。往下滚动网页找到 GitHub Pages 部分,点击 Source
下拉菜单,将其从 None
修改为 master
即可。
如果你不想使用 GitHub 的二级域名,可以在这里添加一个自己的域名,具体方式这里不再赘述,可以参考 GitHub 文档 Configuring a custom domain for your GitHub Pages site。
创建 access token
为了能让 GitHub Actions 拥有访问仓库和提交代码的权限,我们需要先创建一个 access token。
从 GitHub 右上角头像处的下拉菜单,选择 Settings
- Developer settings
- Personal access tokens
。然后点击右侧的 Generate new token
按钮,进入 New personal access token 界面。在 Note
文本框中输入 token 的用途,并勾选 Select scopes
区域中的 repo
前的复选框。
创建好后及时将页面显示的 token 复制下来,之后不会再显示,如果没复制下来重新创建一个就行。
配置 repository secret
复制好 token 后,通过 GitHub 网站进入用于提交源代码的仓库,依次进入 Settings
(注意是仓库的 Settings) - Secrets
,点击右侧的 New repository secret
按钮,进入 New secret 界面。在 Name
文本框中输入 DEPLOY_KEY
,然后在 Value
文本域中粘贴刚刚复制的 token,接着点击 Add secret
按钮完成添加。
编写 GitHub Actions 工作流配置文件
创建工作流文件
在本地打开源代码项目,并在根目录下创建 .github
文件夹,然后在 .github
文件夹中创建 workflows
文件夹,然后再在 workflows
文件夹中创建 deploy.yml
文件。GitHub Actions 将按照这个文件里的配置进行工作,下面开始编辑这个文件。
首先为我们的工作流添加一个名字,例如叫 Deploy huhubun.github.io
:
name: Deploy huhubun.github.io
我希望在提交代码后就触发工作流,通过 on
命令进行配置:
on: [push]
配置 Node.js 环境
我们的站点使用 Nuxt 开发,和本地运行时一样,需要向 GitHub Actions 的容器提供 Node.js 环境。使用 GitHub 提供的 setup-node
步骤即可:
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: '12'
我们还可以将相关信息打印到 log 中,便于排除问题时使用,例如这里通过 run
执行了输出 node 和 npm 版本的命令:
- name: Verify Node.js
run: node --version
- name: Verify npm
run: npm -v
Checkout 源代码仓库
接着需要将源代码 checkout 到 GitHub Actions 的容器中,使用现成的 actions/checkout
步骤即可:
- name: Checkout source
uses: actions/checkout@v2
with:
path: source
因为 checkout 的是当前项目,所以不需要配置任何路径。需要注意的是,path
节点表示将代码 checkout 到 GitHub Actions 容器的 source
文件夹中,如果没有这个文件夹会自动创建。
生成静态文件
源代码到手,接下来就是生成静态文件了,Nuxt 默认使用 generate
命令生成静态文件。不过别忘了,需要先 cd
到 source
文件夹,以及安装相关依赖:
- name: Generate
run: |
cd ./source
npm install
npm run build
npm run generate
Checkout 站点仓库
接着把站点仓库也 checkout 到容器中:
- name: Checkout huhubun.github.io site
uses: actions/checkout@v2
with:
repository: huhubun/huhubun.github.io
path: site
token: ${{ secrets.DEPLOY_KEY }}
和 checkout 源代码仓库不同的是:
- 因为不是当前仓库,所以需要指定
repository
,格式为owner/repository-name
- 设置另一个独立的目录名称,这里使用了
site
- 需要用到之前创建的 access token。
DEPLOY_KEY
就是前面步骤在 Repository Secret 部分设置的名称。通过${{ }}
语法可以访问secrets
对象,并将DEPLOY_KEY
的值设置给token
节点。全程不会泄露我们的 access token
更新站点仓库
静态文件生成好了,站点也 checkout 完成,可以把生成好的文件复制到站点文件夹中了。
- name: Copy generated file to site
run: cp -r ./source/dist/. ./site
虽然生成静态文件时,我们使用了 cd
命令进入了 source
文件夹,但当这个步骤完成,新的步骤开始后,又会回到默认的工作目录,不会保持在 source
文件夹中。所以使用 cp
命令时可以直接从当前文件夹层级来访问 source
和 site
两个文件夹。
提交更新后的站点
只差最后一步,把站点提交就大功告成,这里直接使用 git
命令来操作:
- name: Push site
run: |
cd ./site
git config user.name github-actions
git config user.email github-actions@github.com
git add .
current_time=`date '+%Y-%m-%d %H:%m:%S'`
git commit -m "Update at $current_time"
git push
- 首先切换到
site
文件夹中 - 配置 git 的用户名和 email
- 别忘了执行
git add .
以及git commit
添加提交记录。因为使用的是 linux 主机,和 bash 脚本一样,可以创建变量等。这里创建了名为current_time
的变量用于将更新时间写入的提交记录中 - 最后
git push
将内容推送到服务器上
到这里工作流文件就编写完成了,完整文件可以参考 https://github.com/huhubun/huhubun.github.io-source/blob/master/.github/workflows/deploy.yml。
查看 Actions 的执行状态
保存好文件,并推送到源代码仓库中,就会立即触发 push
事件,执行我们上面编写的工作流。
我们可以打开 GitHub 网页,进入源代码仓库 - Actions
页面查看执行的情况。当看见可爱的绿色✔出现时,则说明执行完成。
由于 GitHub Pages 更新站点有一定延迟,虽然 Actions 执行完成,静态文件仓库也更新了,但站点可能尚未更新,稍等片刻后再访问我们的站点,就能发现已经有内容了~
以后网页内容如果发生了变化,我们只需要往源代码仓库中提交代码即可,剩下的 GitHub Actions 会自动的帮我们完成,省时省力 get~