如何避免同一GitHub Workflow在两个几乎同时的事件中被触发两次?

67次阅读
没有评论

问题描述

在使用GitHub Actions时遇到了一个问题:他在一个仓库中有两个目录,一个包含用于构建C库的Makefile,另一个包含用于构建基于Node-API的Node.js C插件和使用该插件的小型JS/TS API的Makefile。后者依赖于前者。用户希望根据代码提交的位置和内容,最小限度地运行所需的GitHub Workflows。

具体来说,当只有C目录发生变更时,用户希望运行涉及C库的Workflow和涉及Node.js C插件的Workflow。当只有Node.js C插件目录发生变更时,用户只希望运行涉及Node.js C插件的Workflow。当C目录和Node.js C插件目录都发生变更时,用户希望运行两个Workflow,但是Node.js C插件的Workflow只运行一次。

然而,当前的设置中,当C目录和Node.js C插件目录都发生变更时,Node.js C插件的Workflow被触发了两次,一次是因为Node.js C插件目录的变更,另一次是因为C目录的Workflow成功完成。

用户希望解决这个问题,避免Node.js C插件的Workflow重复触发。

解决方案

解决方案1

在GitHub Actions中,可以通过以下步骤来解决这个问题:

  1. 在Workflow文件中,添加一个步骤以获取提交/PR中所修改的文件列表。可以使用GitHub提供的API来获取这些信息。
  2. 根据文件列表的内容,决定是否运行C目录的Workflow和Node.js C插件的Workflow。
  3. 对于Node.js C插件的Workflow,可以使用一个标志来标记是否已经运行过,以避免重复触发。

以下是一个伪代码示例,演示了如何在Workflow中实现这个解决方案:

name: Check Changes

on:
  push:
    paths:
      - 'C/*'
      - 'NAPI/*'

jobs:
  check-changes:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Get changed files
        run: |
          CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }})
          echo "Changed files: $CHANGED_FILES" > changed_files.txt

      - name: Check C directory
        run: |
          if grep -q 'C/' changed_files.txt; then
            echo "Run C Workflow"
            # Run C Workflow here
          fi

      - name: Check NAPI directory
        run: |
          if grep -q 'NAPI/' changed_files.txt; then
            if [ ! -f "napi_workflow_run.txt" ]; then
              echo "Run NAPI Workflow"
              touch napi_workflow_run.txt
              # Run NAPI Workflow here
            else
              echo "NAPI Workflow already run"
            fi
          fi

解决方案2

另一种解决方案是将C目录的Makefile和Node.js C插件的Makefile合并成一个Makefile。然后在GitHub Workflow中运行make all命令,并使用GitHub Actions的缓存功能,只有在依赖发生更改时才重新构建组件。

此外,你可以使用GitHub Actions的concurrency功能,确保多个运行不会同时重叠。

以下是一个伪代码示例,演示了如何在Makefile和Workflow中实现这个解决方案:

name: Build

on:
  push:
    paths:
      - '**/*'

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 14

      - name: Install dependencies
        run: npm install

      - name: Build all
        run: make all

      - name: Save cache
        uses: actions/cache@v2
        with:
          path: |
            ~/.npm
            node_modules
          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

      - name: Cleanup
        run: make clean

通过合并Makefile和使用缓存,可以实现更高效的构建和部署过程。

请根据你的实际情况选择适合的解决方案,并在实施之前做好充分的测试。

正文完