GitHub Actions 备忘

GitHub Actions 如何仅在某些文件发生更改时执行特定的 job, 给 GitHub Actions write contents 权限

GitHub Actions 如何仅在某些文件发生更改时执行特定的 job

要实现某些 job 仅在特定文件发生更改时执行,您可以在工作流中使用 if 语句来检查变更文件。这需要使用 actions/checkoutdorny/paths-filter 动作。下面是一个示例,仅在 my_folder 中的文件发生更改时才执行名为 run_job 的 job:

yaml
1name: Conditional Job Execution
2
3on: [push, pull_request]
4
5jobs:
6  check_changes:
7    runs-on: ubuntu-latest
8    outputs:
9      has_changes: ${{ steps.filter.outputs.has_changes }}
10
11    steps:
12      - name: Checkout repository
13        uses: actions/checkout@v2
14
15      - name: Check for changes in my_folder
16        uses: dorny/paths-filter@v2
17        id: filter
18        with:
19          filters: |
20            has_changes:
21              - 'my_folder/**'
22
23  run_job:
24    runs-on: ubuntu-latest
25    needs: check_changes
26    if: ${{ needs.check_changes.outputs.has_changes == 'true' }}
27
28    steps:
29      - name: Checkout repository
30        uses: actions/checkout@v2
31
32      - name: Run task only if my_folder files changed
33        run: echo "Files in my_folder have changed, running the task."

在这个示例中,我们首先创建一个名为 check_changes 的 job,使用 dorny/paths-filter 动作来检查是否有变更的文件。然后,我们将其输出设置为 has_changes,并在 run_jobif 语句中使用该输出,如果 has_changestrue,则执行 run_job。这样,仅当 my_folder 中的文件发生更改时,run_job 才会执行。

默认 Actions 只有部分权限

Workflows have read permissions in the repository for the contents and packages scopes only.

使用 permissions.contents 字段增加写入权限,如下:

yaml
1name: 'GitHub CI'
2
3permissions:
4  contents: write

GitHub Actions run 命令如何换行?

GitHub Actions 中的 run 命令是用来执行 shell 命令的,你可以使用 shell 的语法来实现换行。这样,你可以在同一个 run 语句中执行多个命令。以下是一些示例:

使用多行字符串:

yaml
1steps:
2  - name: My first step
3    run: |
4      echo 'Hello, world!'
5      echo 'Another command'
6      echo 'And another'

使用分号 (;):

yaml
1steps:
2  - name: My first step
3    run: echo 'Hello, world!'; echo 'Another command'; echo 'And another'

使用 && (如果你想要前一个命令成功时才运行下一个命令):

yaml
1steps:
2  - name: My first step
3    run: echo 'Hello, world!' && echo 'Another command' && echo 'And another'

上述的每个例子中,echo 'Hello, world!'echo 'Another command'echo 'And another' 都被看作独立的命令,并且会按照它们出现的顺序被执行。

另外,注意在YAML中,如果你想在一行内包含多个命令,使用分号 (;) 或 && 是一种好方法。如果你想让你的代码更容易读,那么使用管道符 (|) 来创建一个多行字符串可能是一个更好的选择。

分号(;) 和 && 的区别

在 shell 脚本和命令行中,分号 (;) 和 && 用来在同一行中运行多个命令,但它们之间存在一些关键的差异。

  • 分号 (;):它允许你在同一行中运行多个命令,这些命令会按照从左到右的顺序依次执行,无论前一个命令是否成功执行。

    例如:command1 ; command2 ; command3。在这里,无论 command1 是否成功,command2 都会执行,然后是 command3

  • &&:它也允许你在同一行中运行多个命令,但是后面的命令只有在前面的命令执行成功(返回值为0)时才会执行。

    例如:command1 && command2 && command3。在这里,如果 command1 执行成功,那么 command2 会被执行,如果 command2 也成功,那么 command3 会被执行。如果 command1command2 失败(返回值非0),那么后面的命令将不会执行。

因此,你可以根据你的需求选择使用哪种方式来在一行中运行多个命令。如果你希望无论前一个命令是否成功,都执行所有的命令,那么使用分号 (;)。如果你希望只有在前一个命令成功的情况下才执行下一个命令,那么使用 &&

在 GitHub Actions 环境使用 xsel

解决 Can't open display: (null) 报错:
如果你的程序需要在无头环境(比如 GitHub Actions)中运行并且需要访问 X11 显示服务(比如使用 xsel 访问剪贴板),你可以使用 Xvfb(虚拟帧缓冲 X 服务器)作为替代方案。

Xvfb 是一个运行在内存中的显示服务器,用于运行图形应用程序,但不显示任何图形输出,这使得它非常适合在无头环境中使用。

你可以在 GitHub Actions 中安装并启动 Xvfb,然后运行你的程序。以下是一个例子:

yaml
1name: Your Workflow
2
3on: [push, pull_request]
4
5jobs:
6  your-job:
7    runs-on: ubuntu-latest
8
9    steps:
10    - name: Checkout code
11      uses: actions/checkout@v2
12
13    - name: Install and run Xvfb
14      run: |
15        sudo apt-get install -y xvfb
16        Xvfb :99 & 
17        export DISPLAY=:99
18
19    - name: Run your program
20      run: |
21        # Run your program here

在这个示例中,Xvfb :99 & 启动了一个新的 Xvfb 实例,并将其指定为显示编号 99。export DISPLAY=:99 将 DISPLAY 环境变量设置为这个 Xvfb 实例,这样,你的程序就会将其作为默认的 X 显示服务器。

注意每个步骤都是在单独的 shell 中执行的,不同步骤之间的环境变量不会共享

如果你使用的是 Xvfb,你可能需要将 DISPLAY 设置为 Xvfb 服务的编号,比如 :99

bash
1export DISPLAY=:99

然后,你就可以运行 xsel 命令,它会使用 DISPLAY 环境变量中指定的 X 显示服务器。

如果你在 GitHub Actions 环境中运行 xsel,你可能需要在运行 xsel 命令的同一个步骤(step)中设置 DISPLAY 环境变量,因为每个步骤都是在单独的 shell 中执行的,不同步骤之间的环境变量不会共享。这就是为什么之前的示例中在运行程序前设置 DISPLAY 环境变量的原因。