如何在 Github Action 中设置需要另一个作业的条件性作业

12

以下是我的 GitHub 工作流程

name: APP Build
on:
  push:
    branches:
      - feature/test

jobs:
  test-1:
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'push' && contains( github.event.head_commit.message, 'test1') }}
    steps:
      - name: test-fail
        run: echo "test1"
  test-2:
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'push' && contains( github.event.head_commit.message, 'test2') }}
    steps:
      - name: test-fail
        run: echo "test1"
  notify-slack:
    name: Slack Notification
    runs-on: ubuntu-latest
    needs: [test-1, test-2]
    steps:
      - name: Slack Notification
        uses: rtCamp/action-slack-notify@v2.2.0
        env:
          SLACK_CHANNEL: alert
          SLACK_COLOR: "${{ job.status == 'success' && 'good' || 'danger' }}"

问题:我的提交消息决定了test1test2任务的条件性, 但是通知slack需要test1test2。我不能把两者都放进去,因为如果其中一个任务跳过了,那么notify-slack也会被跳过。该如何解决这个问题?
2个回答

13

Github上有一个问题。你需要添加以下条件:

  test-1:
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'push' && contains( github.event.head_commit.message, 'test1') }}
    steps:
      - name: test-fail
        run: echo "test1"
  test-2:
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'push' && contains( github.event.head_commit.message, 'test2') }}
    steps:
      - name: test-fail
        run: echo "test1"
  notify-slack:
    name: Slack Notification
    runs-on: ubuntu-latest
    needs: [test-1, test-2]
    if: |
      always() && 
      (needs.test-1.result == 'success' || needs.test-1.result == 'skipped') && 
      (needs.test-2.result == 'success' || needs.test-2.result == 'skipped') && 
      !(needs.test-1.result == 'skipped' && needs.test-2.result == 'skipped')
    steps:
      - name: Slack Notification
        uses: rtCamp/action-slack-notify@v2.2.0
        env:
          SLACK_CHANNEL: alert
          SLACK_COLOR: "${{ job.status == 'success' && 'good' || 'danger' }}"

尝试过这个,但是出现了错误 "您的yaml语法在行上有误"if: | always() && (needs.check-environment.result == 'success' || needs.check-environment.result == 'skipped') && (needs.deploy.result == 'success' || needs.deploy.result == 'skipped') && (needs.restart-pods.result == 'success' || needs.restart-pods.result == 'skipped') && (github.event_name == 'pull_request') - Vikas Rathore
以上条件现在已经生效。前两个条件都很好地运作着。如果其中一个工作成功了,那么我们就必须进行构建,但是如果两个工作都跳过了,那么就跳过构建,但这个条件目前没有正确地运行(needs.test-1.result != 'skipped' && needs.test-2.result != 'skipped')。 - Vikas Rathore
你是对的,我改变了条件。 (needs.test-1.result == 'success' || needs.test-2.result == 'success') 所以现在它应该在其中一个是 successskipped 时触发,但当两者都不是 success 时不会触发。这是预期行为吗?或者我们也应该在两者都被跳过时触发此步骤? - Krzysztof Madej
我修改了条件,现在它可以工作了。请在你的答案中更新这个条件。 always() && (needs.test-1.result == 'success' || needs.test-1.result == 'skipped') && (needs.test-2.result == 'success' || needs.test-2.result == 'skipped') && !(needs.test-1.result == 'skipped' && needs.test-2.result == 'skipped') - Vikas Rathore
1
我更新了我的回复。很高兴你终于找到了解决问题的方法! - Krzysztof Madej
显示剩余2条评论

4
实现这种条件可以通过以下工作流逻辑来实现。
jobs:
  A:
    runs-on: ubuntu-latest
    steps:
      - run: echo "success always"
  B:
    runs-on: ubuntu-latest
    if: false
    steps:
      - run: echo "this will never run"
  C:
    runs-on: ubuntu-latest
    steps:
      - run: |
          exho "here to fail"
          exit 1

  D:
    runs-on: ubuntu-latest
    needs: [A, B, C]
    if: |
      always() &&
      !contains(needs.*.result, 'cancelled')
    # you can add conditions if needed e.g.
    # !contains(needs.*.result, 'failure')
    steps:
      - run: echo "${{ toJSON(needs) }}"

您需要修改您的SLACK_COLOR逻辑。因为job.status == 'success'将无法工作,因为对于此作业,无论依赖项是否失败,它始终为success。请使用needs进行逻辑处理,例如,作业D的输出为:
{
  A: {
    result: success,
    outputs: {}
  },
  B: {
    result: skipped,
    outputs: {}
  },
  C: {
    result: failure,
    outputs: {}
  }
}

所以你可以这样设置SLACK_COLOR

SLACK_COLOR: "${{ contains(needs.*.result, 'failure') && 'danger' || 'good' }}"

如果条件为:always() && !contains(needs.*.result, 'cancelled')那么,即使 C 失败了,它也会运行,因为我们使用了 always() 吗? - Vikas Rathore
如果您想在C或任何依赖项失败时排除执行D,请使用以下if条件:always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') - mkungla

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