如何在Azure DevOps YAML管道中发送构建后消息?

时间:2020-05-10 04:40:16

标签: azure-devops azure-pipelines

我试图在Azure DevOps YAML管道中完成/失败作业后发送构建后的Slack消息。但是看来我找不到合适的条件设置。

基本上,我分为三个阶段:测试,构建和通知。

我终于尝试了以下操作,但是dependencies.UnitTest.result返回了null,所以没有给我成功失败

我也尝试了很多不同的条件,但是它们没有起作用。例如,普通的succeeded()failed()没有依赖关系,或者succeeded('Test')作为阶段级别,或者succeeded('UnitTest')作为工作级别。

在大多数情况下,即使在测试阶段失败,他们也会发送成功消息,或者在succeeded()failed()中以作业名称作为参数的语法错误

发送诸如Jenkins这样的构建后消息的适当条件是什么?

stages:
- stage: Test
  jobs:
  - job: UnitTest
    steps:
    - script: echo UnitTest
    - script: exit 1

- stage: Build
  jobs:
  - job: Build
    steps:
    - script: echo Build

- stage: Notify
  dependsOn:
  - Test
  - Build

  condition: succeededOrFailed()
  jobs:
  - job: Succeed
    condition: eq(dependencies.UnitTest.result, 'Succeeded')
    steps:
    - script: echo Succeed #(slack)

  - job: Fail
    condition: eq(dependencies.UnitTest.result, 'Failed')
    steps:
    - script: echo Fail #(slack)

-编辑--
MS支持的已确认作业在多个阶段不能作为Yaml语法本身来支持。

与预期的原始流程不同,但是您可以按以下方式将成功和失败分成不同的阶段。 (如果您希望为每个作业使用不同的消息,则可能仅增加通知的阶段数。)

...

- stage: Notify_Succeeded
  condition: succeeded()

  jobs:
  - job: Succeed
    steps:
    - script: echo Succeed #(slack)

- stage: Notify_Fail
  condition: failed()
  jobs:
  - job: Fail
    steps:
    - script: echo Fail #(slack)

2 个答案:

答案 0 :(得分:1)

可以,但是您必须使用REST API。通过下面的YAML,您将获得您所描述的内容:

variables:
  orgName: 'thecodemanual'

stages:
- stage: Test
  jobs:
  - job: UnitTest
    steps:
    - script: echo UnitTest
    - script: exit 1

- stage: Build
  jobs:
  - job: Build
    steps:
    - script: echo Build

- stage: Notify
  dependsOn:
  - Test
  - Build

  condition: succeededOrFailed()
  jobs:
  - job: InitialJob
    condition: always()
    steps:
    - pwsh: |
        $url = "https://dev.azure.com/$(orgName)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1"
        $timeline = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
        Write-Host "Pipeline = $($timeline | ConvertTo-Json -Depth 100)"

        $test = $timeline.records | where { $_.identifier -eq "Test.UnitTest" }

        $result = $test.result

        Write-Host "##vso[task.setvariable variable=testResult;isOutput=true]$result"
      name: initial
      env:
        SYSTEM_ACCESSTOKEN: $(system.accesstoken)

  - job: Succeed
    dependsOn: InitialJob
    condition: eq(dependencies.InitialJob.outputs['initial.testResult'], 'succeeded')
    steps:
    - script: echo Succeed #(slack)

  - job: Fail
    dependsOn: InitialJob
    condition: eq(dependencies.InitialJob.outputs['initial.testResult'], 'failed')
    steps:
    - script: echo Fail #(slack)

让我解释一下我在上面所做的事情:

  • 我调用了REST API以获取上一阶段的步骤结果(因为目前无法获得任务结果)
  • 我将该步骤的状态分配给输出变量
  • 我使用此变量作为条件来运行特定作业SucceedFail

备注:在运行代码之前,请将orgName更改为您的

编辑

下面的url返回您的构建详细信息。但是您不会在其中找到有关特定任务或阶段的信息。但是您会在那里找到时间轴的网址。

https://dev.azure.com/$(orgName)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)?api-version=5.1

此REST端点将为您返回一个时间表,其中包含任务和阶段的详细信息。

https://dev.azure.com/$(orgName)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1

答案 1 :(得分:0)

您可以指定每个阶段运行的条件。默认情况下,如果某个阶段不依赖于任何其他阶段,或者该阶段所依赖的所有阶段都已完成并成功,则运行该阶段。

根据运行前一个阶段的状态运行阶段的示例:

Code for my forgot password

使用自定义条件的示例:

import React, { useState } from "react";
import { useHistory } from "react-router-dom";

import { Button, Form, Input, InputGroup, InputGroupAddon } from "reactstrap";

const ResetPassword = () => {
  const [email, setEmail] = useState("");

  const history = useHistory();

  const validateForm = () => {
    return email.length > 0;
  };

  const handleSubmit = (event) => {
    event.preventDefault();
  };

  return (

      <div className="password-reset">
        <div className="password-reset-form-container">

          <div className="content">
            <Form className="password-reset-form">
              <h3 className="form-title">Password Reset</h3>
              <InputGroup>
                <InputGroupAddon
                  className="input-group-addon"
                  addonType="prepend"
                >
                  <i className="fa fa-user"></i>
                </InputGroupAddon>
                <Input
                  autoFocus
                  type="email"
                  aria-label="Username"
                  aria-describedby="username"
                  aria-invalid="false"
                  placeholder="Email"
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                />
              </InputGroup>

              <div className="form-actions">
                <Button
                  className="pull-left"
                  block
                  bssize="small"
                  type="submit"
                  onClick={() => history.push("/")}
                >
                  Cancel
                </Button>

                <Button
                  className="pull-right"
                  block
                  bssize="small"
                  disabled={!validateForm()}
                  type="submit"
                  onSubmit={handleSubmit}
                >
                  Reset
                </Button>
              </div>
            </Form>
          </div>
        </div>

      </div>
    </div>
  );
};

export default ResetPassword;

注意:您当前无法基于前一阶段中设置的输出变量的值来指定该阶段运行。

文档:

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/stages?view=azure-devops&tabs=yaml#conditions