当上一个作业被跳过时,Github action作业会被触发。

16

在设置 GitHub Action 来构建和部署我的应用程序时,我遇到了以下问题。

我想根据以下条件来部署我的 Web 应用程序。但是,每当 deploy-apideploy-sync 跳过时,deploy-web 也会被跳过。我原以为我的 if 条件语句可以捕捉这种情况并仍然运行 deploy-web,但事实并非如此。感觉好像错过了什么显而易见的东西,但却无法确定。

deploy-web:
  name: Deploy Web
  runs-on: ubuntu-latest
  needs: [build-and-publish-web, deploy-api, deploy-sync]
  if: |
    needs.build-and-publish-web.result == 'success' &&
    (needs.deploy-api.result == 'success' || needs.deploy-api.result == 'skipped') &&
    (needs.deploy-sync.result == 'success' || needs.deploy-sync.result == 'skipped')
2个回答

34

看起来你遇到了这个问题-如果"needs"属性中的作业被跳过,则"if"条件不会被正确评估

请尝试使用always表达式:

deploy-web:
  name: Deploy Web
  runs-on: ubuntu-latest
  needs: [build-and-publish-web, deploy-api, deploy-sync]
  if: |
    always() &&
    needs.build-and-publish-web.result == 'success' &&
    (needs.deploy-api.result == 'success' || needs.deploy-api.result == 'skipped') &&
    (needs.deploy-sync.result == 'success' || needs.deploy-sync.result == 'skipped')

虽然与原问题无关,但如果您只关心确保没有失败,needs.*.result提供通配符行为,可以避免手动检查每个步骤:

  if: |
    always() &&
    !contains(needs.*.result, 'failure') &&
    !contains(needs.*.result, 'cancelled')

很惊讶我之前没有看过那个讨论。感谢你提供链接。这个系统肯定需要一些优化。这个修改对我来说解决了所有问题!谢谢! - Scalahansolo
6
不错的解决方案,但问题在于依赖“deploy-web”的工作仍会被跳过,这样你最终会不得不在各处添加always() :(Translated: 好的解决方案,但问题在于依赖于“deploy-web”的工作仍然会被跳过,因此你最终需要在各处都添加always(),但这并不理想。 - rethab
5
always() 在作业中使用的另一个问题是无法取消作业 (https://docs.github.com/en/actions/managing-workflow-runs/canceling-a-workflow#steps-github-takes-to-cancel-a-workflow-run)。 - user1119279
2
我喜欢 ${{ always() && !failed() && !cancelled() }} - Chris Pfohl
1
@kgutwin 应该是 failure() - Krzysztof Madej
显示剩余2条评论

8
我更喜欢简洁的条件,但如果你的条件很复杂,你可能需要一个更复杂的解决方案,就像接受的答案中所提到的那样。
needs: [compute_version_tag, bump_version]
if: ${{ always() && !failure() && !cancelled() }} # when none of the needed jobs fail or are cancelled (skipped or successful jobs are ok).

请注意,!cancelled() 是必需的,以便能够取消在 if 条件中使用 always() 的作业。

2
${{ }}if: 表达式中不再需要,所以只需使用 if: always() && !failure() && !cancelled() - undefined
更加简洁地说:if: ${{ !(failure() || cancelled()) }} - undefined

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