阅读 933

是时候体验一下github action的魅力了

github action
github actiongithub推出的自动化CI/CD的新功能,随着2019年11月后github对该功能的全面开放,现在所有的github用户可以直接使用该功能(此时不得不说Github🐂🍺)。

Github Action VS Travis CI

github推出action之前,Travis CI是一个很好对Github中仓库做自动化的一个工具,其语法也很简单,功能强大,深受用户的青睐。那么action出来后,势必会和travis对比。在笔者的实际体验中,觉得action比较吸引我的点:

  • 支持私有仓库
  • actiongithub各个事件的支持更为全面,如果releasepull-requestissue事件等等
  • githubaction编写的支持更为友好,包括在线编辑器和marketplace的共享actions

捣鼓一下Action

启动Action

如果想在仓库中开始action, 可以手动在仓库的根目录下新建.github/workflows文件夹,然后新建任意以.yml或者.yaml结尾的多个文件,这些文件都是action的配置文件,相当于travis中的.travis.yml

当然,正如前面提到的,githubaction的支持还是十分友好的。启动action也可以通过github仓库界面创建(后续查看action记录也是在这),点击Actions选项:

action entry

点击后会进入以下界面,此时我们可以直接使用官方的一些预设的模块,或者使用空模板

action template

下图就是github官方提供的action编辑器,能提供简单的语法提示和错误检测;右边可以直接搜索Marketplace里面的一下action使用,也可以通过Documentation查看文档。实际体验下来还是蛮爽。

action editor

Action 语法

有了配置文件,就该讲讲配置语法了,action的语法是以yml为基础,对yml不熟悉的,可以看看阮一峰的YAML语言教程。我们先来看看配置文件大概长什么样子。

name: Greet Everyone
on: [push]

jobs:
  build:
    name: Greeting
    runs-on: ubuntu-latest
    steps:
      - name: Hello world
        uses: actions/hello-world-javascript-action@v1
        with:
          who-to-greet: 'Mona the Octocat'
        id: hello
      - name: Echo the greeting's time
        run: echo 'The time was xxxx'
复制代码

第一行name规定配置文件的名字,这很直观,无需多言。

触发条件

on规定action的触发条件:

  • 使用web事件触发工作流,并且可以具体指定branchestags以及文件路径
  • 使用cron语法指定时间触发工作流

其中web事件可以指定如上述例子的push事件,如果想指定多个事件,格式为:

on: [push, pull_request]
复制代码

如果不特别指定某一个分支,触发机制会应用到所有分支,如果要具体指定到某一个分支,可使用branch选项:

on:
  push:
    branches: [master]
  pull_request:
    branches: [other]
复制代码

触发条件还可以过滤特定的tag或者文件路径,通过使用tags或者paths选项,如果想只在v1这个tag被推送时或者是当前推送包含test的文件时,构建操作被触发,可以使用下面配置 :

on:
  push:
    tags: [v1]
    paths: ['test/*']
复制代码

同时,还可以忽略某些branch, tag或者文件,通过使用branches-ignoretags-ignore, paths-ignore, 如branches-ignore:[second],可以排除second分支的更改,它等同于braches:[!second]需要特别注意的是:无法对工作流程中的同一事件同时使用 branches 和 branches-ignore 过滤器。 需要过滤肯定匹配的分支和排除分支时,建议使用 branches 过滤器。 只需要排除分支名称时,建议使用 branches-ignore 过滤器,tags-ignore和paths-ignore也是如此。

如果希望定时触发工作流,此时schedule就登场了,如果希望每10分钟运行一次,配置为:

on:
  schedule:
    - cron:  '*/10 * * * *'
复制代码

简单说明cron中每一项的含义:第一项是分钟,第二项是小时,第三项是天,第四项是月,第五项是星期几。可使用crontab在线配置想要的时间。action中可以运行预定工作流程的最短间隔是每 5 分钟一次

完整事件详见触发工作流程的事件

jobs

工作流默认包含一个或者多个job,每一个job都是一个独立的工作单元,如上述例子的buildjob属性主要包含:

  • name: job显示的名字
  • runs-on: 指定job运行的机器
  • steps: 一个job包含多个step, step是job的最小单元,所有step配置在steps中
  • env: 指定环境变量
  • needs: 指定job的依赖

id和name

其中namejob id可能一开始会让人有点混淆,如:

jobs:
  build:
    name: Greeting
复制代码

其中job id指的是build,是在配置文件中可别其他部分引用。name指的是Greeting, 他将会显示在action的记录页面中。

job name

runs-on

action可使用的机器包括:

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

并且每台机器的配置都是:2-core CPU,7 GB RAM 内存,14 GB SSD 硬盘空间。可以说是相当良心了。

needs

action中有多个job时,默认是并行运行,如果某一个job需要依赖另一个job,可使用needs属性,如:

jobs:
  job1:
  job2:
    needs: job1
复制代码

job2会在job1成功完成后才会开始执行

steps

job中所有的操作都在steps中,每个step主要包含id,name, run, uses等属性。如:

jobs:
  first_job:
    steps:
      - name: first step
        uses: actions/heroku@master
      - name: second step
        run: echo 'finish'
复制代码

run指定具体命令,如果是多条命令,格式为:

run: |
  echo 'first line'
  echo 'second line'
复制代码

uses用于使用其他用户所发布的action, 如actions/heroku@master,如果其他action需要参数,使用with传参,如:

- name: Setup Node.js for use with actions
  uses: actions/setup-node@v1.1.0
  with:
    version:10.x
复制代码

可以在github action marketplace查看更多好用的action。

至此就是acion的基础语法,更多细节参见完整语法

Action进阶用法

为工作流加一个Badge

在action的面板中,点击Create status badge就可以复制badge的markdown内容到README.md中,之后就可以直接在README.md中看到当前的构建结果。

baged

使用构建矩阵

如果我们想在多个系统或者多个语言版本上测试构建,就该构建矩阵发挥作用了。如果我们想在多个node版本下跑测试,可以使用如下配置,action会分别使用10.x12.x的版本各运行一次job

jobs:
  build:
    strategy:
      matrix:
        node-version: [10.x, 12.x]

    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}

      - run: npm ci
      - run: npm test
复制代码

使用Secrets

构建过程可能需要用到ssh或者token等敏感数据,而我们是不希望这些数据直接暴露在仓库中,此时就可以使用secrets。选择Settings-> Secrets即可创建secret.

secrets
配置文件中的使用方法:

steps:
  - name: use secrets
    env: 
      super_secret: ${{ secrets.YourSecrets }}
复制代码

secret name不区别大小写,所以如果新建secret的的名字是name, 使用时secrets.name或者secrets.Name都是ok的。并且就算此时直接使用echo打印secret, 控制台也只会打印出********来保护secret

cache

在构建过程中,会安装很多第三方依赖,而这些依赖并不需要每次都重新下载,可以将这些依赖缓存起来,加快构建速度。主要使用action/cache。该action主要包含三个属性:

  • path: 需要缓存的文件的路径
  • key: 对缓存的文件指定的唯一表示
  • restore-key: 主要用于没有再找目标key的缓存的backup选项(可选项)

下面我以node项目为例,将node_modules缓存起来。这里只列出关键步骤:

steps:
      - name: Cache Node Dependencies
        id: cache
        uses: actions/cache@v1
        with:
          path: node_modules
          key: ${{runner.OS}}-npm-caches-${{ hashFiles('package-lock.json') }}

      - name: Install Dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: npm install
复制代码

首先使用action/cache指定pathkey,这里的key包含OS信息和package-lock.json文件的hash值,通常OS是固定下来的;而一旦使用了新的第三方库,package-lock.json的hash值就会改变,得到一个新的keyaction/cache会抛出一个cache-hit的输出,如果找到对应key的缓存,值为true。在随后的安装步骤中,可以使用ifcache-hit做判断。如果找到缓存就跳过,否则就安装依赖。

在第一次运行时,cache找不到,执行npm install,在随后的post cache步骤中对node_modules做缓存。

cache-install

第二次运行时,找到cache, 则跳过npm install,直接使用缓存

cache-hit

artifact

在构建过程中,可能需要输出一些构建产物,并且不同于cache,这些构建产物在action执行完成后,用户还是可以下载查看。通常artifact主要有:日志文件,测试结果等等。主要使用action/upload-artifactdownload-artifact 进行构建参悟的相关操作。

这里以输出jest测试报告为例,jest测试后的测试报告的路径是coverage:

steps:
      - run: npm ci
      - run: npm test

      - name: Collect Test Coverage File
        uses: actions/upload-artifact@v1.0.0
        with:
          name: coverage-output
          path: coverage

复制代码

执行成功后就能在对应action面板看到生成的artifact

artifact

Action限制

这里简单列出action的各种使用限制:

  • action的最大执行时间是72小时,超过该时间,action会自动失败
  • action一小时最大的API请求数量是1000
  • action中每个job最大执行时间为6小时,超过该时间,job会自动失败
  • action中矩阵最多能构建256个job
  • action中多个job默认会并行执行,但对于最大的并行数也是有限制的:
GitHub 计划 同时运行的作业总数 MacOS 作业同时运行的最大数量
免费 20 5
Pro 40 5
团队 60 5
企业 180 50

关于GitHub Actions付费条款详见About billing for GitHub Actions

结语

总体来说,github action提供的资源对个人来说完全够用;语法也相对简单;一体性也很好,大家enjoy。