Udostępnij za pośrednictwem


Programowe tworzenie subskrypcji wpięcia usługi

Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019

Za pomocą interfejsów API REST subskrypcji można programowo utworzyć subskrypcję, która wykonuje akcję w usłudze zewnętrznej/konsumenckiej, gdy określone zdarzenie występuje w projekcie usługi Azure DevOps. Możesz na przykład utworzyć subskrypcję, aby powiadamiać usługę o niepowodzeniach kompilacji.

Obsługiwane zdarzenia:

  • Zakończenie kompilowania
  • Wypchnięcie kodu (w przypadku projektów Git)
  • Utworzenie lub zaktualizowanie żądania ściągnięcia (w przypadku projektów Git)
  • Zaewidencjonowanie kodu (projekty TFVC)
  • Utworzenie, zaktualizowanie, usunięcie, przywrócenie lub skomentowanie elementu roboczego

W subskrypcjach można skonfigurować filtry, aby kontrolować, które zdarzenia wyzwalają akcję. Można na przykład filtrować zdarzenia ukończenia kompilacji na podstawie stanu kompilacji. Pełny zestaw obsługiwanych zdarzeń i opcji filtrowania można znaleźć w dokumentacji zdarzeń.

Pełny zestaw obsługiwanych akcji i usług konsumenckich można znaleźć w dokumentacji konsumenckiej.

Wymagania wstępne

Aby utworzyć subskrypcję, wymagane są następujące dane:

  • Identyfikator projektu. Użyj interfejsu API REST projektu, aby uzyskać identyfikator projektu.
  • Identyfikator zdarzenia i ustawienia. Zobacz odwołanie do zdarzenia.
  • Identyfikatory i ustawienia użytkownika i akcji. Zapoznaj się z dokumentacją konsumenta.

Tworzenie żądania

Skonstruuj treść żądania HTTP POST, aby utworzyć subskrypcję na podstawie identyfikatora projektu, zdarzenia, odbiorcy i akcji.

Zobacz następujące przykładowe żądanie utworzenia subskrypcji, która powoduje wystąpienie zdarzenia kompilacji POST w https://myservice/event przypadku niepowodzenia kompilacji WebSite.CI .

Zażądaj

{
    "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"
    },
}

Zdecydowanie zalecamy używanie bezpiecznych adresów URL HTTPS w celu zabezpieczenia danych prywatnych w obiekcie JSON.

Odpowiedź Zobacz następującą odpowiedź na żądanie utworzenia subskrypcji:

{
    "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"
    }
}

Jeśli żądanie subskrypcji nie powiedzie się, otrzymasz kod odpowiedzi HTTP 400 z komunikatem zawierającym dalsze szczegóły.

Co się stanie po wystąpieniu zdarzenia?

W przypadku wystąpienia zdarzenia wszystkie włączone subskrypcje w projekcie są oceniane, a akcja konsumenta jest wykonywana dla wszystkich pasujących subskrypcji.

Wersje zasobów (zaawansowane)

Przechowywanie wersji zasobów ma zastosowanie, gdy interfejs API jest w wersji zapoznawczej. W większości scenariuszy określenie 1.0 wersji zasobu jest najbezpieczniejszą trasą.

Ładunek zdarzenia wysyłany do niektórych odbiorców, takich jak elementy webhook, usługa Azure Service Bus i usługa Azure Storage, zawiera reprezentację zasobu tematu w formacie JSON (na przykład kompilację lub element roboczy). Reprezentacja tego zasobu może mieć różne formularze lub wersje.

Możesz określić wersję zasobu, który ma zostać wysłany do usługi konsumenta za pośrednictwem resourceVersion pola w subskrypcji. Wersja zasobu jest taka sama jak wersja interfejsu API. Nie określono wersji zasobu oznacza "najnowszą wersję". Zawsze należy określić wersję zasobu, która zapewnia spójny ładunek zdarzeń w czasie.

Często zadawane pytania

Pyt.: Czy istnieją usługi, które mogę subskrybować ręcznie?

Odpowiedź: Tak. Aby uzyskać więcej informacji na temat usług, które można subskrybować na stronie administracyjnej projektu, zobacz Omówienie.

Pyt.: Czy istnieją biblioteki języka C#, których mogę użyć do tworzenia subskrypcji?

Ach: Nie, ale oto przykład, który pomoże Ci rozpocząć pracę.

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; }
    }
}