Criar uma assinatura de gancho de serviço programaticamente

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Usando as APIs REST de Assinaturas, você pode criar programaticamente uma assinatura que executa uma ação em um serviço externo/consumidor quando um evento específico ocorre em um projeto de DevOps do Azure. Por exemplo, você pode criar uma assinatura para notificar seu serviço quando um build falhar.

Eventos com suporte:

  • Build concluído
  • Código enviado por push (para projetos Git)
  • Criar ou atualizar solicitações de pull (para projetos Git)
  • Código verificado (projetos TFVC)
  • Item de trabalho criado, atualizado, excluído, restaurado ou comentado em

Você pode configurar filtros em suas assinaturas para controlar quais eventos disparam uma ação. Por exemplo, você pode filtrar o evento de build concluído com base no status de build. Para obter um conjunto completo de eventos com suporte e opções de filtro, consulte a Referência de evento.

Para obter um conjunto completo de serviços e ações de consumidor com suporte, consulte a Referência do consumidor.

Pré-requisitos

Para criar uma assinatura, os seguintes dados são necessários:

  • ID do Projeto. Use a API REST do projeto para obter a ID do projeto.
  • ID do evento e configurações. Consulte a referência do evento.
  • IDs e configurações de consumidor e ação. Veja a referência Consumidor.

Criar a solicitação

Construa o corpo da solicitação HTTP POST para criar a assinatura com base na ID do projeto, evento, consumidor e ação.

Consulte a solicitação de exemplo a seguir para criar uma assinatura que faz com que um evento de compilação seja POST quando https://myservice/event a compilação WebSite.CI falhar.

Solicitação

{
    "publisherId": "tfs",
    "eventType": "build.complete",
    "resourceVersion": "1.0",
    "consumerId": "webHooks",
    "consumerActionId": "httpRequest",
    "publisherInputs": {
        "buildStatus": "failed",
        "definitionName": "WebSite.CI",
        "projectId": "56479caf-1eeb-4bca-86ab-aaa6f29399d9",
    },
    "consumerInputs": {
        "url": " https://myservice/event"
    },
}

É altamente recomendável usar URLs HTTPS seguras para a segurança dos dados privados no objeto JSON.

Resposta Consulte a seguinte resposta à solicitação para criar a assinatura:

{
    "id": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
    "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/hooks/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
    "publisherId": "tfs",
    "eventType": "build.complete",
    "resourceVersion": "1.0",
    "consumerId": "webHooks",
    "consumerActionId": "httpRequest",
    "createdBy": {
        "id": "00ca946b-2fe9-4f2a-ae2f-40d5c48001bc"
    },
    "createdDate": "2014-03-28T16:10:06.523Z",
    "modifiedBy": {
        "id": "1c4978ae-7cc9-4efa-8649-5547304a8438"
    },
    "modifiedDate": "2014-04-25T18:15:26.053Z",
    "publisherInputs": {
        "buildStatus": "failed",
        "definitionName": "WebSite.CI",
        "hostId": "17f27955-99bb-4861-9550-f2c669d64fc9",
        "projectId": "56479caf-1eeb-4bca-86ab-aaa6f29399d9",
        "tfsSubscriptionId": "29cde8b4-f37e-4ef9-a6d4-d57d526d82cc"
    },
    "consumerInputs": {
        "url": "http://myservice/event"
    }
}

Se a solicitação de assinatura falhar, você receberá um código de resposta HTTP de 400 com uma mensagem com mais detalhes.

O que acontece quando o evento ocorre?

Quando ocorre um evento, todas as assinaturas habilitadas no projeto são avaliadas e a ação do consumidor é executada para todas as assinaturas correspondentes.

Versões de recursos (avançado)

O controle de versão de recursos é aplicável quando uma API está em visualização. Para a maioria dos cenários, especificar 1.0 como a versão do recurso é a rota mais segura.

A carga de evento enviada a determinados consumidores, como Webhooks, Barramento de Serviço do Azure e Armazenamento do Azure, inclui uma representação JSON do recurso de assunto (por exemplo, uma compilação ou item de trabalho). A representação desse recurso pode ter diferentes formas ou versões.

Você pode especificar a versão do recurso que deseja enviar ao serviço ao consumidor por meio do resourceVersion campo na assinatura. A versão do recurso é a mesma que a versão da API. Não especificar uma versão do recurso significa "versão mais recente". Você deve sempre especificar uma versão do recurso, o que garante uma carga de evento consistente ao longo do tempo.

Perguntas Frequentes

P: Existem serviços que posso subscrever manualmente?

A: Sim. Para obter mais informações sobre os serviços que você pode assinar na página de administração de um projeto, consulte Visão geral.

P: Existem bibliotecas C# que posso usar para criar assinaturas?

R: Não, mas aqui está um exemplo para ajudá-lo a começar.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Mvc;

namespace Microsoft.Samples.VisualStudioOnline
{
    public class ServiceHookEventController : Controller
    {

        // POST: /ServiceHookEvent/workitemcreated
        [HttpPost]
        public HttpResponseMessage WorkItemCreated(Content workItemEvent)
        {
            //Grabbing the title for the new workitem
            var value = RetrieveFieldValue("System.field", workItemEvent.Resource.Fields);

            //Acknowledge event receipt
            return new HttpResponseMessage(HttpStatusCode.OK);
        }

        /// <summary>
        /// Gets the value for a specified work item field.
        /// </summary>
        /// <param name="key">Key used to retrieve matching value</param>
        /// <param name="fields">List of fields for a work item</param>
        /// <returns></returns>
        public String RetrieveFieldValue(String key, IList<FieldInfo> fields)
        {
            if (String.IsNullOrEmpty(key))
                return String.Empty;

            var result = fields.Single(s => s.Field.RefName == key);

            return result.Value;
        }

	}

    public class Content
    {
        public String SubscriptionId { get; set; }

        public int NotificationId { get; set; }

        public String EventType { get; set; }

        public WorkItemResource Resource { get; set; }

    }

    public class WorkItemResource
    {
        public String UpdatesUrl { get; set; }

        public IList<FieldInfo> Fields { get; set;}

        public int Id { get; set; }

        public int Rev { get; set; }

        public String Url { get; set; }

        public String WebUrl { get; set; }
    }

    public class FieldInfo
    {
        public FieldDetailedInfo Field { get; set; }

        public String Value { get; set; }

    }

    public class FieldDetailedInfo
    {
        public int Id { get; set; }

        public String Name { get; set; }

        public String RefName { get; set; }
    }
}