跳转至

Github Action and Workflow

这里强烈推荐根据上述的两个教程进行code-based study,我就是跟着这两个教程动手做的,总用时40min左右,效果很好。

本文仅对上述教程中的一些知识点进行总结,是跟着教程做完后的复盘文档。

Why Github Actions

想象一个情形,当developers提出pr以后,我们希望能够自动化地对pr进行一些检查,以减少人力成本。

在这样的需求背景下,Github Actions就应运而生了。

Github Actions是Github提供的一项服务,可以在Github上自动化地运行一些工作流程,比如当有人提出pr的时候,自动化地对pr进行一些检查,如:代码格式化,代码测试,代码覆盖率...

How to make a workflow

GitHub Actions会执行当前分支中的工作流文件,而不是仅限于main分支。但有几个重要的注意事项:

  • 工作流文件必须位于 .github/workflows 目录下才能被识别和执行
  • 每个分支可以有自己的工作流文件,当在该分支上触发事件时,会执行该分支上的工作流文件

alt text

这里展示了设置workflow的.yml文件,它会告诉github服务器应该如何执行workflow。

值得注意的是:

  1. 我们不会在这里详细教你如何写.yml文件,你需要根据不同的需求/负载,自行编写
  2. 编写完成,workflow不是在本地运行的,而是在github服务器上运行的

我们这里举个例子,此处的需求是:当一个用户提出pr后,会自动在评论区回复 Welcome to the repository!

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# (main branch) under .github/workflows
# create a new file named `welcome.yml`
name: Post welcome comment # workflow name
on: # trigger event
  pull_request:
    types: [opened] # when we open a new pr, this welcome workflow is triggered
permissions:
  pull-requests: write # we need to write into pr, so permission is needed
jobs:
  build:
    name: Post welcome comment # job name
    runs-on: ubuntu-latest # this job(task) is running on ubuntu-latest remote machine
    steps: # if there are many commands, we can use steps to organize them, they will be executed in order
      - run: gh pr comment $PR_URL --body "Welcome to the repository!" # this is the command we want to run
        env: # ENVIRONMENT VARIABLES for the command above
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_URL: ${{ github.event.pull_request.html_url }}

How to check the workflow

From PR itself

当我们提出pr后,我们可以在pr的页面中看到workflow的执行情况。

alt text

点击 Details 可以看到workflow的详细执行情况。

alt text

我们将在下一部分详细介绍如何勘查workflow的执行情况。

From Actions Tab

alt text

在主页面点击Actions Tabs后,可以看到所有的workflow的执行情况。

比如这个仓库显示18 workflow runs,说明截至目前这个仓库已经运行过18个workflows。

我们点击一个workflow,可以看到它的详细执行情况:

alt text

这里非常值得注意的是,我们可以看到workflow的执行情况,包括每一步的执行情况、执行时间,这对于我们排查问题非常有帮助。

比如我们可以看到这个workflow由两个jobs组成,其依赖关系是Check current step number而后On trigger

这与我们在.yml文件中定义的一致:

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
jobs:
  # Get the current step to only run the main job when the learner is on the same step.
  get_current_step:
    name: Check current step number
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - id: get_step
        run: |
          echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
    outputs:
      current_step: ${{ steps.get_step.outputs.current_step }}

  on_trigger:
    name: On trigger
    needs: get_current_step

    # We will only run this action when:
    # 1. This repository isn't the template repository.
    # 2. The step is currently 5.
    # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
    # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
    if: >-
      ${{ !github.event.repository.is_template
          && needs.get_current_step.outputs.current_step == 5 }}
    # We'll run Ubuntu for performance instead of Mac or Windows.
    runs-on: ubuntu-latest

    steps:
      # We'll need to check out the repository so that we can edit the README.
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Let's get all the branches.

      # In README.md, switch step 5 for step X.
      - name: Update to step X
        uses: skills/action-update-step@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          from_step: 5
          to_step: X
          branch_name: test-workflow

点击每个job,可以看到每个job的详细执行情况,我们会在接下来看到steps的执行顺序及过程:

alt text

alt text

注意这张图里的执行命令,它们与上述的.yml文件中的定义是一致的:

  • get_current_step:
    • name: Checkout (the only step of 1st job)
  • on_trigger:
    • name: Checkout (step1 of 2nd job)
    • name: Update to step X (step2 of 2nd job)

How to utilize workflow logs

在未来执行完任务,观察jobs依赖图时,我们会发现某些jobs正常工作,有些jobs构建失败,此时需要寻找原因:

alt text

  • 如果一个job执行成功,那么皆大欢喜,结束
  • 如果一个job执行失败,那么我们可以点击Details查看logging,寻找失败的原因

这里我们在ci分支中进行了build这个job,但是构建失败,报错信息:Process completed with exit code 1.

Text Only
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v4

      # # Runs a single command using the runners shell
      # - name: Run a one-line script
      #   run: echo Hello, world!

      # # Runs a set of commands using the runners shell
      # - name: Run a multi-line script
      #   run: |
      #     echo Add other actions to build,
      #     echo test, and deploy your project.
      - name: Run markdown lint
        run: |
          npm install remark-cli remark-preset-lint-consistent
          npx remark . --use remark-preset-lint-consistent --frail

alt text

点击这个jobs,可以看到详细的logging,我们可以看到报错信息:

Bash
1
2
3
4
5
6
resume.md
9:18-9:23    warning Unexpected emphasis marker `*`, expected `_`                      emphasis-marker remark-lint
  [cause]:
    3:1-3:79 info    Emphasis marker style `'_'` first defined for `'consistent'` here emphasis-marker remark-lint

⚠ 1 warning

上面的报错显示存在markdown-lint问题,因此我们回到resume.md文件中,修改错误,然后重新提交,此时build这个job就会成功。

to be specific, the error message is:

Bash
1
2
resume.md: 问题出在resume.md这个文件上
9:18-9:23: 问题聚焦在第9行的18-23列上