GitHub Action 入门教程


导言

感到为了持续集成注册一堆账号、设置一堆 token 很麻烦?或是被自建 GitLab 的内存泄露烦扰?不如来尝试下 GitHub 新推出的内置 CI/CD 工具 GitHub Action

作为 GitLab CI 和 Travis CI 的一个可能替代品,GitHub Action 同样提供免费方案,且对于个人用户完全够用。功能基本类似,但还是有些细微差别。本文将简要介绍其基本概念、工作流程和配置方法。

参考链接

基本概念

CI/CD

持续集成、持续部署。不用多说了⑧,不知道这个也没必要看本文。

Event

触发一个 Workflow 的事件。包含了各种操作:推送、合并、合并请求、打标签、发行…

Action

说白了一个 Action 就是一步独立的操作。给力的是 Action 可以将复杂操作封装为一步,并且 GitHub 官方和社区提供了成吨的现成 Action 供引用。

Step

就是一步操作。可以是自己写的指令,也可以是引用 Action。

Job

在一个给定环境下(操作系统、容器)执行一系列 Step。(各个 Job 环境是独立的)

Runner

执行 Job 的机器。GitHub 提供了一些,你也可以自建。

Workflow

工作流。由一个 Event 触发的一系列 Job。

Artifact

产物。就是说干完一个活之后产出了什么(二进制文件、log、质量报告之类的)。

工作流程

这是一个 Job:根据配置创建出一个虚拟环境,然后执行一系列你指定的 Step 中的命令或 Action。

这是一个 Workflow:当一个事件发生了,这个 Workflow 里面的 Job 将按照依赖关系并行地或先后地执行。

Workflow 语法介绍

name

# File Path: /.github/workflows/main.yml
name: "A Sample Workflow"

on

# Trigger on Event
on: [push, pull_request]
# or
on:
  push:
    paths:
      # Trigger only when src/** changes
      - "src/**"
      # Ignore when only doc/** changes
      - "!doc/**"
    paths-ignore:
      - "doc/**"

    branches:
      - master
      - "!ignored"
    branches-ignore:
      - ignored

    tags:
      - "v*"
      - "!v0.*"
    tags-ignore:
      - "v0.*"

  release:
    types: [published, unpublished, created, edited, deleted, prereleased]

  schedule:
    # Trigger every 15 min(UTC)
    - cron:  '*/15 * * * *'

env

# Workflow Environment (Step ENV > Job ENV > Workflow ENV)
env:
  SERVER: production
  KEY: 123456

jobs

jobs:
  job1:
    name: Job 1
  job2:
    name: Job 2
    needs: job1

  job3:
    name: A Job runs on Host machine
    needs: [job1, job2]

job(host)

job3:
  name: A Job runs on Host machine
  needs: [job1, job2]

  timeout-minutes: 20
  # Or windows-latest, ubuntu-18.04, macos-10.15
  runs-on: ubuntu-latest
  env:
    # override workflow env
    KEY: 12345678

  # See https://help.github.com/en/actions/reference/contexts-and-expression-syntax-for-github-actions
  if: <expression>

  steps:
    - name: Step A(simply run)
      if: <expression>
      continue-on-error: true
      timeout-minutes: 10

      env:
        # override workflow, job env
        KEY: 1234567890
      working-directory: ./docs

      # or python, cmd, powershell, ...
      shell: bash
      run: |
        npm ci
        npm run build

    - name: Step B(uses action)
      uses: "{owner}/{repo}/{path}@{ref}"
      # or
      uses: "./path/to/action"

      with:
        tag_name: ${{ github.ref }}
        token: ${{ secrets.GITHUB_TOKEN }}

    - name: Step B(uses docker)
      uses: "docker://{image}:{tag}"
      with:
        entrypoint: /bin/echo
        args: The ${{ github.event_name }} event triggered this step.

job(container)

job4:
  name: A Job runs in Container
  image: ubuntu:bionic
  env:
    KEY: 123
  ports:
    - 80:80
  volumes:
    - /source:/data
  # See https://docs.docker.com/engine/reference/commandline/create/#options
  options: --cpus 1
  steps:
    - name: Same as host jobs
      run: echo hello

job(service)

job5:
  name: A Job uses services

  services:
    nginx:
      image: nginx
      ports:
        - 8080:80
      volumes:
        - /src:/data
      options: --cpus 1
    redis:
      image: redis
      ports:
        - 6379/tcp

job(matrix)

runs-on: ${{ matrix.os }}
strategy:
  matrix:
    os: [macos-latest, windows-latest, ubuntu-18.04]
    node: [4, 6, 8, 10]
    include:
      # includes a new variable of npm with a value of 2 for the matrix leg matching the os and version
      - os: windows-latest
        node: 4
        npm: 2
    exclude:
      # excludes node 4 on macOS
      - os: macos-latest
        node: 4

steps:
  - uses: actions/setup-node@v1
    with:
      node-version: ${{ matrix.node }}

Filter pattern

https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet

常用 Action

checkout

- uses: actions/checkout@v2
  with:
    # Repository name with owner. For example, actions/checkout
    # Default: ${{ github.repository }}
    repository: ''

    # The branch, tag or SHA to checkout. When checking out the repository that
    # triggered a workflow, this defaults to the reference or SHA for that event.
    # Otherwise, defaults to `master`.
    ref: ''

    # Auth token used to fetch the repository. The token is stored in the local git
    # config, which enables your scripts to run authenticated git commands. The
    # post-job step removes the token from the git config. [Learn more about creating
    # and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
    # Default: ${{ github.token }}
    token: ''

    # Whether to persist the token in the git config
    # Default: true
    persist-credentials: ''

    # Relative path under $GITHUB_WORKSPACE to place the repository
    path: ''

    # Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching
    # Default: true
    clean: ''

    # Number of commits to fetch. 0 indicates all history.
    # Default: 1
    fetch-depth: ''

    # Whether to download Git-LFS files
    # Default: false
    lfs: ''

upload-artifacts

steps:
- uses: actions/checkout@v1

- run: mkdir -p path/to/artifact

- run: echo hello > path/to/artifact/world.txt

- uses: actions/upload-artifact@v1
  with:
    name: my-artifact
    path: path/to/artifact

download-artifacts

steps:
- uses: actions/checkout@v1

- uses: actions/download-artifact@v1
  with:
    name: my-artifact
    path: path/to/artifact

- run: cat path/to/artifact

create-release

- name: Create Release
  id: create_release
  uses: actions/create-release@latest
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
  with:
    tag_name: ${{ github.ref }}
    release_name: Release ${{ github.ref }}
    body: |
      Changes in this Release
      - First Change
      - Second Change
    draft: false
    prerelease: false

upload-release-asset

- name: Upload Release Asset
  id: upload-release-asset
  uses: actions/upload-release-asset@v1
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
  asset_path: ./my-artifact.zip
  asset_name: my-artifact.zip
  asset_content_type: application/zip

setup-python

steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
  with:
    # Version range or exact version of a Python version to use, using SemVer's version range syntax
    python-version: '3.x'
    # optional x64 or x86. Defaults to x64 if not specified
    architecture: 'x64'
- run: python my_script.py