使用 GitHub Actions 实现博客自动化部署

549 阅读8分钟

前言

本人之前使用Travis进行博客的自动化部署,可自从Travis域名统一从 .org 迁移到 .com 后,Travis出现了一系列问题,Travis login 莫名登陆失败,只能通过token方式登陆,且登陆成功后也无法进行操作;每次部署都会收到两条邮件推送,分别来自两个域名。查阅了很多资料但并未得以解决,各位读者若遇到相同问题,欢迎交流指导,非常感谢!

鉴于此,决定改用 Github Actions 进行自动部署,关于如何迁移网上有很多相关文章,也可参考从 Travis CI 迁移到 GitHub Actions
本文主要记录一下关键步骤及注意点,详细步骤可参考官网GitHub Actions

使用 GitHub Actions

现在主流的公用免费的持续集成服务有:

  • Travis CI (仅支持github)
  • Jenkins
  • Circle CI
  • Azure Pipeline
  • GitHub Actions (仅支持github)

GitHub Actions 是 GitHub 自家的持续集成及自动化工作流服务。在仓库根目录建立.github/workflows文件夹,将你的工作流配置(YAML 文件)放到这个目录下,就能启用 GitHub Actions 服务。

建立 SSH 密钥对

要把文件部署到远程服务器,首先要解决登录校验的问题 SSH 密钥可以一劳永逸。

  1. 生成ssh密钥

    > ssh-keygen -t rsa -f <mysite> # mysite 选填, 默认id_rsa
    

    一路回车即可,会在~/.ssh下生成两个文件:mysite(私钥)和mysite.pub(公钥)。其中私钥是你的个人登录凭证,不可以分享给他人,如果别人得到了你的私钥,就能登录到你的服务器。公钥则需要放到登录的目标服务器上。

  2. 将公钥mysite.pub的内容贴到目标服务器的~/.ssh/authorized_keys

  3. 【非必要】确保服务器~/.ssh文件夹的权限低于 711,我这里直接用 600(仅本用户可读写):

    > chmod 600 -R ~/.ssh
    
  4. 最后,查看私钥文件mysite,将内容复制下来以备后续使用,私钥的文件内容大致如下:

      -----BEGIN RSA PRIVATE KEY-----
      ...
      -----END RSA PRIVATE KEY-----
    

这里提一句,默认的私钥,公钥名称为 id_rsa, id_rsa_pub ,如果以默认名称的密钥配置到服务器,则本机就可以实现免密登陆

将密钥配置到 GitHub 仓库

打开你的网站代码仓库,点击 Settings 标签,找到 Secrets 设定:
创建secret,写入刚刚生成的密钥,名称自己定义, 直接上图:

github-Actions-生成scrite.png

github-Actions-生成scrite2.png

编写工作流文件

GitHub Actions 的配置文件叫做 workflow 文件,存放在代码仓库的.github/workflows目录。

workflow 文件采用 YAML 格式,文件名可以任意取,但是后缀名统一为.yml,比如foo.yml。一个库可以有多个 workflow 文件。GitHub 只要发现.github/workflows目录里面有.yml文件,就会自动运行该文件。

workflow 文件的配置字段非常多,详见官方文档 GitHub Actions 的工作流程语法 。下面是一些基本字段。

  • name
    工作流程的名称。 GitHub 在仓库的操作页面上显示工作流程的名称。 如果省略 name,GitHub 将其设置为相对于仓库根目录的工作流程文件路径。

  • on 必填。 触发工作流程的 GitHub 事件的名称。 您可以提供单一事件 string、事件的 array、事件 typesarray 或事件配置 map,以安排工作流程的运行,或将工作流程的执行限于特定文件、标记或分支更改。 有关可用事件的列表,请参阅“触发工作流程的事件”。

  • on.<push|pull_request>.<tags|branches> 指定触发事件时,可以限定分支或标签。

    on:
      push:
        branches:    
          - master
    
  • on.schedule
    您可以使用 POSIX cron 语法安排工作流程在特定的 UTC 时间运行。 预定的工作流程在默认或基础分支的最新提交上运行。 您可以运行预定工作流程的最短间隔是每 5 分钟一次。

  • env 环境变量的 map 可用于工作流程中所有作业的步骤。 您还可以设置仅适用于单个作业的步骤或单个步骤的环境变量。
    示例:

      env:
        SERVER: production
    
  • defaults
    将应用到工作流程中所有作业的默认设置的 map。 您也可以设置只可用于作业的默认设置。

    使用相同名称定义了多个默认设置时,GitHub 会使用最具体的默认设置。 例如,在作业中定义的默认设置将覆盖在工作流程中定义的同名默认设置。

  • jobs
    工作流程运行包括一项或多项作业。 作业默认是并行运行。 要按顺序运行作业,您可以使用 <job_id>needs 关键词在其他作业上定义依赖项。

    每个作业在 runs-on 指定的运行器环境中运行。

    在工作流程的使用限制之内可运行无限数量的作业。

  • jobs.<job_id>
    每项作业必须关联一个 ID。 键值 job_id 是一个字符串,其值是作业配置数据的映像。 必须将 <job_id> 替换为 jobs 对象唯一的字符串。 <job_id> 必须以字母或 _ 开头,并且只能包含字母数字字符、- 或 _。

    jobs:
      my_first_job:
        name: My first job
      my_second_job:
        name: My second job
    
  • env
    环境变量的 map 可用于作业中的所有步骤。 您也可以设置整个工作流程或单个步骤的环境变量。
    当多个环境变量使用相同的名称定义时,GitHub 会使用最特定的环境变量。 例如,步骤中定义的环境变量在步骤执行时将覆盖名称相同的作业和工作流程变量。 为作业定义的变量在作业执行时将覆盖名称相同的工作流程变量。

      jobs:
        job1:
          env:
            FIRST_NAME: Mona
    
  • jobs.<job_id>.name
    任务的说明。

      jobs:
        my_first_job:
          name: My first job
        my_second_job:
          name: My second job
    
  • jobs.<job_id>.runs-on
    runs-on 字段指定运行所需要的虚拟机环境。必填。 要运行作业的机器类型。 机器可以是 GitHub 托管的运行器或自托管的运行器。

    可用的 GitHub 托管的运行器类型包括:

    虚拟环境YAML 工作流程标签
    Windows Server 2019windows-latest 或 windows-2019
    Uuntu 20.04ubuntu-latest 或 ubuntu-20.04
    Ubuntu 18.04ubuntu-18.04
    Ubuntu 16.04ubuntu-16.04
    macOS Big Sur 11.0macos-11.0
    macOS Catalina 10.15macos-latest 或 macos-10.15

    注:MacOS 11.0 虚拟环境目前仅作为私人预览提供。 任何已经在使用此运行器的用户或组织都可以继续使用它。 但我们目前不接受任何其他用户或组织。 macos-latest YAML 工作流程标签仍使用 MacOS 10.15 虚拟环境。

    示例:

      runs-on: ubuntu-latest
    
  • jobs.<job_id>.steps
    steps字段指定每个 Job 的运行步骤,可以包含一个或多个步骤。每个步骤都可以指定以下三个字段。

    • jobs.<job_id>.steps.name:步骤名称。
    • jobs.<job_id>.steps.run:该步骤运行的命令或者 action。
    • jobs.<job_id>.steps.env:该步骤所需的环境变量。
  • jobs.<job_id>.needs
    识别在此作业运行之前必须成功完成的任何作业。 它可以是一个字符串,也可以是字符串数组。 如果某个作业失败,则所有需要它的作业都会被跳过,除非这些作业使用让该作业继续的条件表达式。
    要求相关作业成功的示例:

    jobs:
      job1:
      job2:
        needs: job1
      job3:
        needs: [job1, job2]
    

    不要求相关作业成功的示例

    jobs:
      job1:
      job2:
        needs: job1
      job3:
        if: always()
        needs: [job1, job2]
    

    在此示例中,job3 使用 always() 条件表达式,因此它始终在 job1 和 job2 完成后运行,不管它们是否成功。 更多信息请参阅“ 上下文和表达式语法”。

  • jobs.<job_id>.steps[*].run
    使用操作系统 shell 运行命令行程序。 如果不提供 name,步骤名称将默认为 run 命令中指定的文本。

    命令默认使用非登录 shell 运行。 您可以选择不同的 shell,也可以自定义用于运行命令的 shell。

    每个 run 关键词代表运行器环境中一个新的进程和 shell。 当您提供多行命令时,每行都在同一个 shell 中运行。 例如:

    • 单行命令:
        - name: Install Dependencies
        run: npm install
      
    • 多行命令:
        - name: Clean install dependencies and build
        run: |
          npm ci
          npm run build
      

tips: 配置项很多,详情请参考官网docs.github.com/cn/actions

案例

以下是我个人用于记录杂七杂八的学习内容的gitbook网站配置信息; 在仓库根目录中创建.github/workflows文件夹,再创建一个 YAML 文件,文件名自定,我这里起名叫deploy.yml,所以文件的完整路径应该为.github/workflows/deploy.yml,我将配置的意义写在注释中,文件内容如下:

# main.yml
name: deploy to aliyun
# 触发方式
on: 
  push: # 触发动作
    branches:
      # 触发分支
      - master 
# 任务
jobs:
  # 第一个任务 build
  build:
    # 选择虚拟机
    runs-on: ubuntu-latest
    # 步骤
    steps:
      # 使用 node:10
      - name: use Node.js 10
        uses: actions/setup-node@v1
        with:
          node-version: 10
      # npm install
      - name: npm install and build
        run: |
          npm install -g gitbook-cli
          gitbook install
          gitbook build
        env:
          CI: true
      # Deploy
      - name: Deploy
        uses: easingthemes/ssh-deploy@v2.0.7
        env:
          SSH_PRIVATE_KEY: ${{ secrets.AL_ACCESS_TOKEN }}
          ARGS: "-avz --delete"
          SOURCE: "_book"
          REMOTE_HOST: # your host
          REMOTE_USER: # your username
          TARGET: # your project dir
      # Back and rename
      - name: Restart server # 第三步,重启服务
        uses: appleboy/ssh-action@master
        with:
          host: "118.190.52.53" # 下面三个配置与上一步类似
          username: "root"
          key: ${{ secrets.AL_ACCESS_TOKEN }}
          # 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器,本例由于部署前端文件,故不需重启服务,这里只做文件的备份
          script: |
            cd /opt/html/book
            mv noteBook noteBook_$(date "+%Y%m%d_%H%M%S")
            mv _book noteBook

此时当向master分支提交代码后,actions 会自动触发,执行上述配置进行一系列操作:

打开github项目文件 => Actions 查看日志

github-Actions-构建日志.png

至此,项目自动部署完成。

可以发现 GitHub Actions 的最大特点就是有很多第三方提供的镜像,已经把一些常用的步骤封装好了,你只需要填下配置即可。而这些镜像也很容易提供,发布在自己的 GitHub 仓库即可,所以扩展性很强。关于Actions的编写,可以参考(Github action 的开发到发布)[juejin.cn/post/687037…]

参考:
docs.github.com/cn/actions