Project Icon

skip-duplicate-actions

GitHub Actions工作流程优化利器

skip-duplicate-actions是一款专为GitHub Actions设计的优化工具。它可以智能跳过重复和并发工作流运行、忽略特定路径变更、取消过时运行,通过高效的回溯算法确保必要检查完成。该工具不仅节省时间和成本,还提供灵活配置,适应各类复杂工作流场景,是提升GitHub Actions效率的理想选择。

跳过重复操作

skip-duplicate-actions 提供以下功能来优化 GitHub Actions:

所有这些功能都有助于节省时间和成本,特别是对于长时间运行的工作流。 您可以选择使用其中的任意功能组合。

跳过重复的工作流运行

如果您使用功能分支,可能会看到许多重复的工作流运行。 例如,当在功能分支上执行工作流运行后,合并该功能分支时可能会再次重复执行工作流运行。 skip-duplicate-actions 可以防止这种情况发生。

  • 完全可追溯: 在干净的合并后,您将看到类似 跳过执行,因为完全相同的文件已在 <previous_run_URL> 中成功检查 的消息。
  • 完全可配置: 默认情况下,手动触发和定时任务永远不会被跳过。
  • 灵活的 Git 使用: skip-duplicate-actions 不关心您使用快进合并、变基合并还是压缩合并。 但是,如果合并产生的结果与源分支不同,那么结果工作流运行将不会被跳过。 这通常发生在合并"过时分支"的情况下。

跳过并发的工作流运行

有时,即使触发了两次,您也不希望同时运行某些工作流。 因此,skip-duplicate-actions 提供以下选项,在同一工作流已经运行时跳过工作流运行:

  • 始终跳过: 适用于您永远不希望同时运行两次的工作流。
  • 仅跳过相同内容: 例如,当工作流同时具有 pushpull_request 触发器时,或在推送提交后立即推送标签时,这可能很有用。 (已弃用,请使用 same_content_newer 代替)
  • 仅跳过具有相同内容的较新运行: 如果同一工作流正在运行完全相同的内容,则跳过较新的运行。same_content_newer 确保至少有一个这样的工作流会运行,而 same_content 可能会跳过所有运行。
  • 仅跳过过时的运行: 例如,这对于不在作业开始时进行的跳过检查很有用。
  • 永不跳过: 这会禁用并发跳过功能,但仍允许您使用所有其他选项,如重复跳过。

跳过被忽略的路径

在许多项目中,对于仅文档更改的情况,运行所有测试是不必要的。 因此,GitHub 本身提供了 paths-ignore 功能。 然而,GitHub 的 paths-ignore 有一些限制:

  • GitHub 的 paths-ignore 无法查看先前的提交。这意味着结果取决于您推送更改的频率。
  • 因此,GitHub 的 paths-ignore 对于必需检查不起作用。 如果您对必需检查使用 path-ignore,那么拉取请求将永远无法合并。

为了克服这些限制,skip-duplicate-actions 提供了一个更灵活的 paths_ignore 功能,使用高效的回溯算法。 paths_ignore 不会简单地查看当前提交,而是在您的提交历史中寻找成功的检查。

如果您需要在单个工作流中定义多个 paths_ignore 模式,可以使用 paths_filter 选项。

如果路径未变更则跳过

在某些项目中,只有在特定子目录发生变更时才应执行某些任务。 因此,GitHub 本身提供了 paths 功能。 然而,GitHub 的 paths 有一些限制:

  • GitHub 的 paths 无法跳过工作流中的单个步骤。
  • GitHub 的 paths 不适用于您真正希望成功通过的必需检查。

为了克服这些限制,skip-duplicate-actions 提供了一个更复杂的 paths 功能。 回溯算法不会盲目地跳过检查,而是只有在您的提交历史中找到合适的检查时才会跳过。

如果您需要在单个工作流中定义多个 paths 模式,可以使用 paths_filter 选项。

取消过时的工作流运行

通常,工作流应该只针对最新的提交运行。 因此,当您向分支推送更改时,可以配置 skip-duplicate-actions 以取消针对过时提交运行的任何先前工作流运行。

  • 完全可追溯: 如果工作流运行被取消,您将看到类似 已取消 <previous_run_URL> 的消息。
  • 保证执行: 取消算法保证无论如何都会完成一组完整的检查。

输入

paths_ignore

包含被忽略路径模式的 JSON 数组。 有关路径模式示例,请参阅备忘单。 有关支持的路径模式的详细信息,请参阅 micromatch

示例: '["**/README.md", "**/docs/**"]'

默认值: '[]'

paths

包含路径模式的 JSON 数组。 如果非空,skip-duplicate-actions 将尝试跳过未更改这些路径的提交。 它使用与 paths_ignore 相同的语法。

示例: '["platform-specific/**"]'

默认值: '[]'

paths_filter

包含命名的 paths_ignore / paths 模式的 YAML 字符串。

示例:

frontend:
  paths_ignore:
    - 'frontend/docs/**'
  paths:
    - 'frontend/**'
backend:
  paths:
    - 'backend/**'
  ### 在这里您可以选择控制/限制回溯
  # 布尔值或数字(默认值:true)
  # 'false' 表示完全禁用回溯
  # '5' 表示在回溯 5 个提交后停止
  backtracking: 5

当您在一个工作流中有多个作业,并希望根据不同的 paths_ignore / paths 模式跳过它们时很有用。 请参阅相应的 paths_result 输出和示例配置

cancel_others

如果为 true,则会取消来自过时提交的工作流运行。

默认值: 'false'

skip_after_successful_duplicate

如果为 true,在找到已完成的重复运行时跳过。

默认值: 'true'

do_not_skip

包含不应跳过的触发器的 JSON 数组。

可能的值有 pull_requestpushworkflow_dispatchschedulereleasemerge_group

默认值: '["workflow_dispatch", "schedule", "merge_group"]'

concurrent_skipping

如果同一工作流已在运行,则跳过工作流运行。

可选值:neversame_contentsame_content_neweroutdated_runsalways

默认值: 'never'

输出

should_skip

如果根据您配置的规则应跳过当前运行,则返回 'true'。这应该用于评估单个步骤或整个作业。

reason

当前运行被认为可跳过或不可跳过的原因。大致对应于输入选项。

示例: skip_after_successful_duplicate

skipped_by

返回导致当前运行被跳过的工作流运行的相关信息。

示例:

{
  "id": 1709469369,
  "runNumber": 737,
  "event": "pull_request",
  "treeHash": "e3434bb7aeb3047d7df948f09419ac96cf03d73e",
  "commitHash": "4a0432e823468ecff81a978165cb35586544c795",
  "status": "completed",
  "conclusion": "success",
  "htmlUrl": "https://github.com/fkirc/skip-duplicate-actions/actions/runs/1709469369",
  "branch": "master",
  "repo": "fkirc/skip-duplicate-actions",
  "workflowId": 2640563,
  "createdAt": "2022-01-17T18:56:06Z"
}
  • 仅当当前运行被认为是可跳过时才返回信息,否则返回空对象({})。

paths_result

返回 paths_filter 中每个配置的过滤器的信息。

示例:

{
  "frontend": {
    "should_skip": true,
    "backtrack_count": 1,
    "skipped_by": {
      // 工作流运行的相关信息
    },
  "backend": {
    "should_skip": false,
    "backtrack_count": 1,
    "matched_files": ["backend/file.txt"]
  },
  "global": {
    "should_skip": false,
    "backtrack_count": 0
  }
}
  • global 键对应"全局" paths_ignorepaths 选项。
  • 如果有匹配的文件,会在 matched_files 中返回匹配文件列表。
  • skipped_by 返回值的行为与"全局" skipped_by 输出相同。
  • backtrack_count 显示在找到适当的提交之前回溯(跳过)了多少个提交。
  • 如果 skip-duplicate-actions 在执行路径检查之前终止(例如,当找到成功的重复运行时),则返回空对象({})。

changed_files

一个二维数组,包含每个被追溯的提交的已更改文件列表。

示例: [["some/example/file.txt", "another/example/file.txt"], ["frontend/file.txt"]]

  • 使用二维列表使处理更加灵活。例如,可以将列表展平(并去重)以获取所有被追溯的提交中的已更改文件。或者可以使用 changed_files[0] 获取最新提交的已更改文件。也可以使用 paths_result 中的 backtrack_count 输出来处理已更改文件的列表。
  • 仅当设置了 paths_ignorepathspaths_filter 选项之一时才返回信息。
  • 如果 skip-duplicate-actions 在执行路径检查之前终止(例如,当找到成功的重复运行时),则返回空数组([])。

使用示例

你可以使用 skip-duplicate-actions 来跳过单个步骤或整个作业。 为了最小化对现有作业的更改,通常更容易跳过整个作业。

注意

  • 你可能需要使用 fromJSON 来访问对象输出的属性。例如,对于 skipped_by.id,你可以使用表达式:${{ fromJSON(steps.skip_check.outputs.skipped_by).id }}

  • 对于将 GITHUB_TOKEN默认权限设置为"宽松(只读)"的 GitHub 仓库,必须在工作流中包含以下行(参见权限语法):

    # skip-duplicate-actions 所需的最小权限
    permissions:
      actions: write
      contents: read
    

示例 1:跳过整个作业

要跳过整个作业,你应该添加一个 pre_job 作为 main_job 的前置条件。 虽然这个示例看起来代码很多,但在你的特定项目的 main_job 中只有两行额外的代码(needs 子句和 if 子句):

jobs:
  pre_job:
    # continue-on-error: true # 完成集成后取消注释
    runs-on: ubuntu-latest
    # 将步骤输出映射到作业输出
    outputs:
      should_skip: ${{ steps.skip_check.outputs.should_skip }}
    steps:
      - id: skip_check
        uses: fkirc/skip-duplicate-actions@v5
        with:
          # 所有这些选项都是可选的,如果你对默认值满意,可以删除它们
          concurrent_skipping: 'never'
          skip_after_successful_duplicate: 'true'
          paths_ignore: '["**/README.md", "**/docs/**"]'
          do_not_skip: '["pull_request", "workflow_dispatch", "schedule"]'

  main_job:
    needs: pre_job
    if: needs.pre_job.outputs.should_skip != 'true'
    runs-on: ubuntu-latest
    steps:
      - run: echo "运行耗时测试..." && sleep 30

示例 2:跳过单个步骤

以下示例演示了如何使用 if 子句和 id 跳过单个步骤。 在这个示例中,如果 src/dist/ 中没有文件被更改,则该步骤将被跳过:

jobs:
  skip_individual_steps_job:
    runs-on: ubuntu-latest
    steps:
      - id: skip_check
        uses: fkirc/skip-duplicate-actions@v5
        with:
          cancel_others: 'false'
          paths: '["src/**", "dist/**"]'
      - if: steps.skip_check.outputs.should_skip != 'true'
        run: |
          echo "仅在 src/ 或 dist/ 发生更改时运行..." && sleep 30
          echo "执行其他操作..."

示例 3:使用 paths_filter 跳过

[!警告]
如果 paths_filter 选项无法正常工作,你可以根据需要多次复制"示例 1"(详见 https://github.com/fkirc/skip-duplicate-actions/issues/326)。

如果工作流中有多个作业,并且想根据不同的 paths_ignore / paths 模式跳过它们,可以使用 paths_filter 选项。定义这些过滤器时,操作会在 paths_result 输出中返回相应的信息。 例如,在一个单体仓库中,你可能希望仅在相应的 "frontend/" 文件夹中的某些文件发生更改时运行与"前端"相关的作业,对"后端"也是如此。可以通过以下配置实现:

jobs:
  pre_job:
    runs-on: ubuntu-latest
    outputs:
      should_skip: ${{ steps.skip_check.outputs.should_skip }}
      paths_result: ${{ steps.skip_check.outputs.paths_result }}
    steps:
      - id: skip_check
        uses: fkirc/skip-duplicate-actions@v5
        with:
          paths_filter: |
            frontend:
              paths_ignore:
                - 'frontend/docs/**'
              paths:
                - 'frontend/**'
            backend:
              paths:
                - 'backend/**'
          # 可以与"全局" 'paths_ignore' / 'paths' 选项混合使用,例如:
          # paths_ignore: '["**/README.md"]'

前端: 需要:pre_job # 如果'skip-duplicate-actions'在执行路径检查之前终止(例如,找到成功的重复运行时),'paths_result'会输出一个空对象('{}')。 # 可以在作业的if条件中通过首先检查"全局"'should_skip'输出的结果来轻松拦截这种情况。 如果:needs.pre_job.outputs.should_skip != 'true' && !fromJSON(needs.pre_job.outputs.paths_result).frontend.should_skip # ...

后端: # ...


## 它是如何工作的?

`skip-duplicate-actions`使用[工作流运行API](https://docs.github.com/en/rest/reference/actions#workflow-runs)来查询工作流运行。
`skip-duplicate-actions`只会查看属于当前工作流运行的同一工作流的工作流运行。
查询这些工作流运行后,它会将它们与当前工作流运行进行如下比较:

- 如果存在具有相同树哈希的工作流运行,那么我们就找到了一个重复的工作流运行。
- 如果存在正在进行的工作流运行,那么我们可以根据您的配置取消或跳过它。

## 路径跳过是如何工作的?

如上所述,`skip-duplicate-actions`提供了一个路径跳过功能,这与GitHub原生的`paths`和`paths_ignore`功能有些相似。
然而,路径跳过并不完全简单,因为存在多种执行路径跳过的选项:

### 选项1:只查看"当前"提交

这是GitHub目前正在做的事情,我们认为它是不够的,因为它对"必需"检查不起作用。
另一个问题是,结果可能高度依赖于提交的推送顺序。

### 选项2:查看拉取请求差异

PR差异易于理解,但它们只在打开PR后才起作用,而不是在推送功能分支后立即起作用。

### 选项3:查找先前提交的成功检查

这个选项由`skip-duplicate-actions`实现。
一个优点是,无论您是使用PR还是原始功能分支,它都能工作,当然它也适用于"必需"检查。
在内部,`skip-duplicate-actions`使用[Repos Commit API](https://docs.github.com/en/rest/reference/repos#get-a-commit)来执行高效的回溯算法进行路径跳过检测。

这是该算法大致的工作方式:

```mermaid
stateDiagram-v2
    检查提交: 检查提交
    [*] --> 检查提交: 当前提交

    state 路径被忽略 <<choice>>
    检查提交 --> 路径被忽略: 所有更改的文件是否都匹配"paths_ignore"?
    忽略_是: 是
    忽略_否: 否
    路径被忽略 --> 忽略_是
    路径被忽略 --> 忽略_否

    state 路径被跳过 <<choice>>
    忽略_否 --> 路径被跳过: 是否没有更改的文件匹配"paths"?
    跳过_是: 是
    跳过_否: 否
    路径被跳过 --> 跳过_是: 无匹配
    路径被跳过 --> 跳过_否: 有匹配

    父提交: 获取父提交
    忽略_是 --> 父提交
    跳过_是 --> 父提交

    state 成功运行 <<choice>>
    父提交 --> 成功运行: 是否有此提交的成功运行?
    运行_是: 是
    运行_否: 否
    成功运行 --> 运行_是
    成功运行 --> 运行_否

    运行_否 --> 检查提交: 父提交

    跳过: 跳过!
    运行_是 --> 跳过: (因为自此运行以来的所有更改都在被忽略或跳过的路径中)

    不跳过: 不跳过!
    跳过_否 --> 不跳过: (因为更改的文件需要"测试")

常见问题

如何对必需的矩阵作业使用跳过检查?

https://github.com/fkirc/skip-duplicate-actions/issues/44中讨论。

如果您有注册为必需状态检查的矩阵作业,并且矩阵根据跳过检查条件运行,您可能会遇到拉取请求永远处于无法合并状态的问题,因为作业根本没有执行,因此没有报告为已跳过(Expected - Waiting for status to be reported)。

有几种方法可以解决这个问题:

  • 在矩阵作业的每个步骤中定义条件(if),而不是在作业级别定义单一条件:https://github.com/fkirc/skip-duplicate-actions/issues/44

  • 如果您希望只有在矩阵中的所有作业都成功时才将检查视为成功,可以添加一个后续作业,其唯一任务是报告矩阵的最终状态。然后,您可以将此最终作业注册为必需状态检查:

    result:
      name: 结果
      if: needs.pre_job.outputs.should_skip != 'true' && always()
      runs-on: ubuntu-latest
      needs:
        - pre_job
        - example-matrix-job
      steps:
        - name: 标记结果为失败
          if: needs.example-matrix-job.result != 'success'
          run: exit 1
    
  • 定义一个相反的工作流,如GitHub官方建议:处理跳过但必需的检查

维护者

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号