Créer un abonnement de hook de service par programmation

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

À l’aide des API REST Abonnements, vous pouvez créer par programme un abonnement qui effectue une action sur un service externe/consommateur lorsqu’un événement spécifique se produit dans un projet Azure DevOps. Par exemple, vous pouvez créer un abonnement pour notifier votre service en cas d’échec d’une build.

Événements pris en charge :

  • Build terminée
  • Code poussé (pour les projets Git)
  • Création ou mise à jour d’une demande de tirage (pour les projets Git)
  • Code archivé (projets TFVC)
  • Élément de travail créé, mis à jour, supprimé, restauré ou commenté

Vous pouvez configurer des filtres sur vos abonnements pour contrôler les événements qui déclenchent une action. Par exemple, vous pouvez filtrer l’événement de build terminé en fonction de l’état de build. Pour obtenir un ensemble complet d’événements pris en charge et d’options de filtre, consultez la référence sur les événements.

Pour obtenir un ensemble complet d’actions et de services consommateur pris en charge, consultez la référence du consommateur.

Prérequis

Pour créer un abonnement, les données suivantes sont requises :

  • ID de projet. Utilisez l’API REST Project pour obtenir l’ID de projet.
  • ID d’événement et paramètres. Consultez la référence de l’événement.
  • ID de consommateur et d’action et paramètres. Consultez la référence du consommateur.

Créer la requête

Construisez le corps de la requête HTTP POST pour créer l’abonnement en fonction de l’ID de projet, de l’événement, du consommateur et de l’action.

Consultez l’exemple de demande suivant de création d’un abonnement qui provoque l’échec d’un événement de génération vers POST https://myservice/event lors de l’échec de la génération WebSite.CI .

Requête

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

Nous vous recommandons vivement d’utiliser des URL HTTPS sécurisées pour la sécurité des données privées dans l’objet JSON.

Réponse Consultez la réponse suivante à la demande de création de l’abonnement :

{
    "id": "74aeeed0-bf5d-48dc-893f-f862b80987e9",
    "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/hooks/subscriptions/74aeeed0-bf5d-48dc-893f-f862b80987e9",
    "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"
    }
}

Si la demande d’abonnement échoue, vous obtenez un code de réponse HTTP de 400 avec un message contenant des détails supplémentaires.

Que se passe-t-il lorsque l’événement se produit ?

Lorsqu’un événement se produit, tous les abonnements activés dans le projet sont évalués et l’action du consommateur est effectuée pour tous les abonnements correspondants.

Versions de ressources (avancées)

Le contrôle de version des ressources s’applique lorsqu’une API est en préversion. Pour la plupart des scénarios, la spécification 1.0 en tant que version de ressource est l’itinéraire le plus sûr.

La charge utile d’événement envoyée à certains consommateurs, tels que les Webhooks, Azure Service Bus et Stockage Azure, inclut une représentation JSON de la ressource d’objet (par exemple, une build ou un élément de travail). La représentation de cette ressource peut avoir différentes formes ou versions.

Vous pouvez spécifier la version de la ressource que vous souhaitez envoyer au service consommateur via le resourceVersion champ de l’abonnement. La version de ressource est identique à la version de l’API. Ne pas spécifier de version de ressource signifie « dernière version publiée ». Vous devez toujours spécifier une version de ressource, ce qui garantit une charge utile d’événement cohérente au fil du temps.

FAQ

Q : Existe-t-il des services auxquels je peux m’abonner manuellement ?

A : Oui. Pour plus d’informations sur les services auxquels vous pouvez vous abonner à partir de la page d’administration d’un projet, consultez la vue d’ensemble.

Q : Existe-t-il des bibliothèques C# que je peux utiliser pour créer des abonnements ?

R : Non, mais voici un exemple pour vous aider à commencer.

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