如何运行 github-actions 步骤,即使上一步失败,但仍使作业失败

Posted

技术标签:

【中文标题】如何运行 github-actions 步骤,即使上一步失败,但仍使作业失败【英文标题】:How to run a github-actions step, even if the previous step fails, while still failing the job 【发布时间】:2020-03-10 12:13:16 【问题描述】:

我正在尝试按照 Github 的示例使用 github 操作测试我的构建,然后压缩测试结果并将它们作为工件上传。 https://help.github.com/en/actions/automating-your-workflow-with-github-actions/persisting-workflow-data-using-artifacts#uploading-build-and-test-artifacts

但是,当我的测试失败时,我不知道该怎么做。这是我的行动。当我的测试通过时一切正常,我的结果被压缩并导出为工件,但如果我的测试失败,它会停止工作中的其余步骤,所以我的结果永远不会被发布。 我尝试添加 continue-on-error: true https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepscontinue-on-error 这使它在失败后继续并上传我的测试结果。但是即使我的测试步骤失败了,该作业也被标记为通过。有没有办法让它上传我的工件,即使一个步骤失败,同时仍然将整个作业标记为失败?

name: CI
on:
  pull_request:
    branches:
    - master
  push:
    branches:
      - master

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1    
    - name: Test App
      run: ./gradlew test

    - name: Archive Rest Results
      uses: actions/upload-artifact@v1
      with:
        name: test-results
        path: app/build/reports/tests

【问题讨论】:

您可能还想查看continue-on-error。我对此没有太多经验,但是如果您不想担心特定jobstep 中的错误,您可以使用continue-on-error: true 来允许失败而不标记整个@987654330 @/workflow 为失败。 【参考方案1】:

你可以添加

if: always()

即使上一步失败,也可以运行它 https://help.github.com/en/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#job-status-check-functions

所以对于一个步骤,它看起来像这样:

steps:
- name: Build App
  run: ./build.sh

- name: Archive Test Results
  if: always()
  uses: actions/upload-artifact@v1
  with:
    name: test-results
    path: app/build

或者您可以将其添加到作业中:

jobs:
job1:
  job2:
    needs: job1
  job3:
    if: always()
    needs: [job1, job2]

【讨论】:

请注意,除非您指定 always()failure(),否则似乎总是隐含 if: success() - 即使您设置了例如if: true。这意味着(也许令人惊讶)if: xif: always() && x 的不同之处在于,如果前面的步骤失败或作业被取消,第一个将不会运行。 文档中的一条注释:“当您在 if 条件中使用表达式时,您可以省略表达式语法 ($ ),因为 GitHub 会自动将 if 条件评估为表达式。”换句话说,可以简单地使用:if: always(). 我向 GitHub 文档提交了 PR 以澄清这一点:github.com/github/docs/pull/8411 请注意,这会产生您无法再手动取消工作流程的副作用:docs.github.com/en/actions/managing-workflow-runs/… if: always()相反,if: success() || failure() 保留了取消构建的能力,同时仍然实现了 OPs 目标。【参考方案2】:

其他方式,您可以添加continue-on-error: true。 看起来像

- name: Job fail
  continue-on-error: true
  run |
    exit 1
- name: Next job
  run |
    echo Hello

在here阅读更多内容。

【讨论】:

我在原始问题中描述了该解决方案,但这在我的情况下不起作用,因为使用 continue-on-error,失败的任务仍然会导致整个构建通过。而且我仍然希望将失败的构建标记为失败,同时仍然运行此任务,而不管以前的任务如何。如果您不关心整体构建状态,则此解决方案将起作用。 @TomerShemesh 这是我在谷歌上搜索的解决方案! @TomerShemesh 我有完全相同的问题,但if: alwayscontinue-on-error: true 都对我不起作用。如果测试失败,您是否在每个跳过的步骤中都使用了if: always @Rsaleh 是的,我添加了 if:always 到我需要运行的每一步,即使出现故障。【参考方案3】:

插件:如果您有以下情况。 2个步骤,即build > deploy,在某些情况下,即workflow_dispatch,带有输入参数,您可能想跳过build并继续deploy。同时,当build 失败时,您可能希望跳过deploy。 从逻辑上讲,这将类似于 skipped or not failed 作为 deploy 条件。if: always() 将不起作用,因为它总是会触发 deploy,即使 build 失败。 解决方法很简单:if: $ !failure() 注意if:中取反时不能跳过括号,否则会报语法错误。

【讨论】:

【参考方案4】:

你可以添加||忠于你的命令。 示例:

 jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1    
    - name: Test App
      run: ./gradlew test || true

【讨论】:

这不是一个很好的解决方案,因为测试的步骤将始终被标记为通过,即使测试失败。这不是人们通常想要的结果。您仍然希望步骤本身失败并将构建本身标记为失败,但仍希望运行诸如归档和发布测试结果之类的任务。无论测试步骤本身是否通过,您都想要执行此操作。执行您的建议将导致所有构建始终通过,无论测试是否失败。

以上是关于如何运行 github-actions 步骤,即使上一步失败,但仍使作业失败的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Github-actions 在 Docker 上使用 Mysql 运行 Prisma 迁移

vue-cli3携手rollup、github-actions打造自动部署的vue组件模板(使用篇)

[,foreach和github-actions中的其他循环

利用GitHub-Actions将Hugo博客自动发布到GitHub和Gitee Pages

如何使用Pytest进行自动化测试

仅当有人打开 PR 时才运行 GitHub Action