在作业之间重复使用GitHub Action的部分

91

我在一个单体库中使用CI的工作流程,这个工作流程会构建两个项目。这些工作正常运行,但是我想知道是否有一种方法可以从workflow.yml文件中删除设置runner的重复部分。我把它们拆分成并行运行,因为它们彼此不依赖且完成速度更快。等待CI完成时,5分钟和10+之间有很大的时间差异。

jobs:
  job1:
    name: PT.W Build
    runs-on: macos-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v1

      - name: Setup SSH-Agent
        uses: webfactory/ssh-agent@v0.2.0
        with:
          ssh-private-key: |
            ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Setup JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Setup Permobil-Client
        run: |
          echo no | npm i -g nativescript
          tns usage-reporting disable
          tns error-reporting disable
          npm run setup.all

      - name: Build PT.W Android
        run: |
          cd apps/wear/pushtracker
          tns build android --env.uglify

  job2:
    name: SD.W Build
    runs-on: macos-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v1

      - name: Setup SSH-Agent
        uses: webfactory/ssh-agent@v0.2.0
        with:
          ssh-private-key: |
            ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Setup JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Setup Permobil-Client
        run: |
          echo no | npm i -g nativescript
          tns usage-reporting disable
          tns error-reporting disable
          npm run setup.all

      - name: Build SD.W Android
        run: |
          cd apps/wear/smartdrive
          tns build android --env.uglify

在这里,您可以看到这些工作几乎有相同的流程,只是不同应用程序本身的构建。我想知道是否有一种方法可以将工作中的重复块提取出来,并创建一种只需编写一次并在两个工作中重复使用的方式。


我还没有掌握实现它的正确语法。但是,我正在尝试创建一个本地操作,以在我的主工作流程内运行重复的步骤。 参考:https://github.community/t5/GitHub-Actions/Path-to-action-in-the-same-repository-as-workflow/td-p/38761 这似乎是解决问题的方法,但目前作业失败了,我还没有找出设置路径的正确语法。 - Brad Martin
当前错误:##[error]在'/Users/runner/runners/2.163.1/work/-client/-client/.github/actions/build-setup-action.yml'下找不到'action.yml'或'Dockerfile'。您是否忘记在运行本地操作之前运行actions/checkout? - Brad Martin
这个回答解决了你的问题吗?Github Actions如何在jobs之间共享工作区和产物? - gcode
3个回答

100

在GitHub Actions中,代码重用有三种主要方式:

以下详细信息来自我的文章,描述了它们的优缺点:

可重复使用工作流

显然的选项是使用“可重复使用工作流”功能,它允许您将某些步骤提取到单独的“可重复使用”工作流中,并在其他工作流中调用此工作流作为一个任务。

总结:

  • 允许嵌套可重复使用工作流调用(最多4级),但不允许循环。
  • 环境变量不会被继承。可以使用特殊的secrets: inherit作业参数来继承密钥。
  • 如果需要提取和重用一个作业中的多个步骤,则不方便。
  • 由于它作为一个单独的任务运行,您必须使用构建工件来在可重用工作流和主工作流之间共享文件。
  • 您可以同步或异步地调用可重用工作流(使用needs键管理作业顺序)。
  • 可重用工作流可以定义输出,从执行步骤中提取输出/结果。它们可以很容易地用于将数据传递给“主”工作流。
  • 分派工作流程

    Github 给我们提供的另一种可能性是workflow_dispatch事件,它可以触发工作流程运行。简而言之,您可以手动或通过GitHub API触发工作流程,并提供其输入。

    市场上有操作可用,允许您将“分派”的工作流程作为“主”工作流程的一步来触发。

    其中一些还允许同步方式操作(等待已调度的工作流完成)。值得一提的是,此功能通过轮询存储库工作流状态实现,这在并发环境下不太可靠。此外,它受到GitHub API使用限制的限制,因此在找出已调度的工作流状态时会有延迟。

    要点

    • 您可以进行多个嵌套调用,从一个触发的工作流中触发另一个工作流。但是如果不小心处理,可能会导致无限循环。
    • 您需要一个具有“工作流程”权限的特殊令牌;您通常的secrets.GITHUB_TOKEN无法使您调度工作流。
    • 您可以在一个作业内触发多个已调度的工作流。
    • 没有简单的方法将某些数据从已调度的工作流返回到主要工作流中。
    • 在“发射和忘记”方案中效果更好。等待已调度的工作流完成有一些限制。
    • 您可以观察已调度的工作流运行并手动取消它们。

    组合操作

    在这种方法中,我们将步骤提取到一个独立的组合操作中,该操作可以位于同一个或不同的存储库中。
    从您的“主”工作流程中,它看起来像是一个普通的操作(单个步骤),但内部实际上由多个步骤组成,每个步骤都可以调用自己的操作。
    要点:
    • 支持嵌套:组合操作的每个步骤都可以使用另一个组合操作。
    • 内部步骤运行可视化效果较差:在“主”工作流程中,它显示为一个普通的步骤运行。在原始日志中,您可以找到内部步骤执行的详细信息,但这并不太友好。
    • 共享环境变量与父作业,但不共享机密信息,机密信息应通过输入显式传递。
    • 支持输入和输出。输出是从内部步骤的输出/结果准备的,并且可以轻松地用于将数据从组合操作传递到“主”工作流程。
    • 组合操作在“主”工作流程的作业内运行。由于它们共享一个常见的文件系统,因此无需使用构建产物将文件从组合操作传输到“主”工作流程。
    • 您不能在组合操作内部使用continue-on-error选项。

    这个回答的某些部分可能已经过时。例如,截至2023年1月,可重用工作流可以调用其他可重用工作流,并且在调用可重用工作流的作业中支持strategy属性。更多信息请参见此处:https://github.blog/changelog/2022-08-22-github-actions-improvements-to-reusable-workflows-2/ - kamilz
    3
    @kamilz 感谢您的更新,您是100%正确的!我已经更新了答案。 - Cardinal

    26

    据我所知,目前没有办法重复使用步骤
    但在这种情况下,您可以使用strategy来进行并行构建和不同变化:

    jobs:
      build:
        name: Build
        runs-on: macos-latest
        strategy:
          matrix:
            build-dir: ['apps/wear/pushtracker', 'apps/wear/smartdrive']
        steps:
          - name: Checkout Repo
            uses: actions/checkout@v1
    
          - name: Setup SSH-Agent
            uses: webfactory/ssh-agent@v0.2.0
            with:
              ssh-private-key: |
                ${{ secrets.SSH_PRIVATE_KEY }}
    
          - name: Setup JDK 1.8
            uses: actions/setup-java@v1
            with:
              java-version: 1.8
    
          - name: Setup Permobil-Client
            run: |
              echo no | npm i -g nativescript
              tns usage-reporting disable
              tns error-reporting disable
              npm run setup.all
    
          - name: Build Android
            run: |
              cd ${{ matrix.build-dir }}
              tns build android --env.uglify
    

    如需更多信息,请访问https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategy


    太棒了。我正在尝试解决一个类似但不同的问题,你的答案帮了我大忙。 - aahnik

    13

    自2021年10月以来,"可重用工作流现已普遍可用"

    现在可使用可重用工作流。
    可重用工作流帮助您通过使整个工作流程可重复使用,从而减少重复工作。自beta版于十月发布以来,进行了许多改进:

    • 您可以利用输出将数据从可重用工作流传递到调用方工作流中的其他作业
    • 您可以将环境密钥传递给可重用工作流
    • 审计日志包括有关所使用的可重用工作流的信息

    请参阅“重用工作流”了解更多信息。

    workflow

    使用另一个工作流的工作流称为“调用方”工作流
    可重用工作流是“被调用”工作流

    一个调用方工作流可以使用多个被调用工作流
    每个被调用工作流在一行中引用。

    结果是,当运行呼叫者工作流时,呼叫者工作流文件可能只包含几行YAML,但可能执行大量任务。重用工作流时,整个被调用的工作流将被使用,就像它是呼叫方工作流的一部分。

    例如:

    在可重用工作流中,使用inputssecrets关键字定义将从呼叫方工作流传递的输入或密码。

    # .github/actions/my-action.yml
    # Note the special trigger 'on: workflow_call:'
    
    on:
      workflow_call:
        inputs:
          username:
            required: true
            type: string
        secrets:
          envPAT:
            required: true
    
    引用输入或保密信息以在可重复使用的工作流中使用。
    jobs:
      reusable_workflow_job:
        runs-on: ubuntu-latest
        environment: production
        steps:
          - uses: ./.github/actions/my-action
            with:
              username: ${{ inputs.username }}
              token: ${{ secrets.envPAT }}
    

    使用./.github/actions/my-action作为你自己仓库中my-action.yml文件的名称。

    可重复使用工作流不必在同一仓库中,也可以在另一个公共仓库中。

    Davide Benvegnù aka CoderDave在《避免重复!GitHub Actions可重复使用的工作流程》中说明:


    这个答案可以通过添加代码片段来展示如何使用该功能而得到改进。目前,我认为它只是一个边缘链接答案。 - jtbandes
    @jtbandes 感谢您提供的反馈。我已相应地编辑了答案。 - VonC
    2
    谢谢更新。就问题的实质而言,我认为如何使用这些代码片段仍然不清楚,因为第二个片段中引用了“my-action”,但是第一个片段没有——“my-action”是第一个片段的文件名吗? - jtbandes
    @jtbandes 我进一步澄清了答案并添加了一个具体的例子。 - VonC
    不是特殊触发器开启:workflow_call。我想你的意思是“注意”吧? - maerteijn

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接