Condividi tramite


Creare una sottoscrizione hook del servizio a livello di codice

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020

È possibile usare una sottoscrizione per eseguire un'azione su un servizio esterno o consumer quando si verifica un evento specifico in un progetto Azure DevOps. Ad esempio, una sottoscrizione può inviare una notifica al servizio quando una compilazione non riesce.

Per creare una sottoscrizione a livello di codice, è possibile usare le API REST delle sottoscrizioni. Questo articolo fornisce una richiesta di esempio e un codice di esempio per la creazione di una sottoscrizione.

Prerequisiti

Categoria Requisiti
di accesso a Project membro del progetto.
Dati - Progetto ID. Usare l'API REST del progetto per ottenere l'ID del progetto.
- ID evento e impostazioni. Vedere Eventi di hook del servizio.
- ID e impostazioni del consumatore e dell'azione. Vedi Ricevitori di hook di servizio.

Eventi supportati

Azure DevOps offre supporto per numerosi eventi di trigger. Gli esempi includono gli eventi seguenti:

  • Compilazione completata
  • Codice inviato (nei progetti Git)
  • Richiesta pull creata o aggiornata (per i progetti Git)
  • Codice registrato (per i progetti di controllo della versione di Team Foundation)
  • Elemento di lavoro creato, aggiornato, eliminato, ripristinato o commentato

Per controllare quali eventi attivano un'azione, è possibile configurare i filtri per le sottoscrizioni. Ad esempio, è possibile filtrare l'evento di compilazione completato in base allo stato di compilazione.

Crea una richiesta

Quando si crea una sottoscrizione, si usa il corpo di una richiesta HTTP POST per specificare l'ID progetto, l'evento, il consumer, l'azione e le impostazioni correlate.

È possibile usare la seguente richiesta per creare un abbonamento per un evento di compilazione completato. In questo esempio, quando la WebSite.CI compilazione ha esito negativo, la sottoscrizione invia una richiesta POST a https://myservice/event.

Richiesta

{
    "publisherId": "tfs",
    "eventType": "build.complete",
    "resourceVersion": "1.0",
    "consumerId": "webHooks",
    "consumerActionId": "httpRequest",
    "publisherInputs": {
        "buildStatus": "failed",
        "definitionName": "WebSite.CI",
        "projectId": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff",
    },
    "consumerInputs": {
        "url": " https://myservice/event"
    },
}

È consigliabile usare URL HTTPS sicuri per la sicurezza dei dati privati nell'oggetto JSON.

risposta

La richiesta di creazione della sottoscrizione genera una risposta simile alla seguente:

{
    "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": "22cc22cc-dd33-ee44-ff55-66aa66aa66aa"
    },
    "createdDate": "2014-03-28T16:10:06.523Z",
    "modifiedBy": {
        "id": "22cc22cc-dd33-ee44-ff55-66aa66aa66aa"
    },
    "modifiedDate": "2014-04-25T18:15:26.053Z",
    "publisherInputs": {
        "buildStatus": "failed",
        "definitionName": "WebSite.CI",
        "hostId": "d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4",
        "projectId": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff",
        "tfsSubscriptionId": "ffff5f5f-aa6a-bb7b-cc8c-dddddd9d9d9d"
    },
    "consumerInputs": {
        "url": "http://myservice/event"
    }
}

Se la richiesta di sottoscrizione non riesce, viene visualizzato un codice di risposta HTTP pari a 400 con un messaggio con altri dettagli.

Cosa accade quando si verifica l'evento?

Quando si verifica un evento, vengono valutate tutte le sottoscrizioni abilitate nel progetto. Viene quindi eseguita l'azione del consumatore per tutte le sottoscrizioni corrispondenti.

Versioni delle risorse (avanzate)

Il controllo delle versioni delle risorse è applicabile quando un'API è in anteprima. Per la maggior parte degli scenari, specificare 1.0 come versione della risorsa è l'opzione più sicura.

Il payload dell'evento inviato a determinati consumer include una rappresentazione JSON di una risorsa oggetto. Ad esempio, il payload inviato ai webhook, al Service Bus di Azure e ad Azure Storage include informazioni su una compilazione o un elemento di lavoro. La rappresentazione di questa risorsa può avere diverse forme o versioni.

È possibile specificare la versione della risorsa da inviare al servizio consumer tramite il resourceVersion campo nella sottoscrizione.

La versione della risorsa è la stessa della versione dell'API . Se non si specifica una versione della risorsa, viene usata la versione più recente, latest released, . Per garantire un payload di eventi coerente nel tempo, specificare sempre una versione della risorsa.

Domande frequenti

D: Sono disponibili servizi che è possibile sottoscrivere manualmente?

R: Sì. Per ulteriori informazioni sui servizi a cui è possibile sottoscriversi da una pagina di amministrazione del progetto, consultare Integrare con i ganci di servizio.

D: Sono disponibili librerie C# che è possibile usare per creare sottoscrizioni?

R: No, ma ecco un esempio per iniziare. Per l'autenticazione ad Azure DevOps, il codice seguente usa un token di accesso personale archiviato in Azure Key Vault. In un ambiente di produzione usare un metodo di autenticazione più sicuro. Per altre informazioni, vedere Scegliere il meccanismo di autenticazione corretto.

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.ServiceHooks.WebApi;
using Microsoft.VisualStudio.Services.WebApi;

namespace CreateServiceHookSubscription
{
    internal class Program
    {
        // Create a service hook subscription to send a message to an Azure Service Bus queue when code is pushed to a Git repository.

        static async Task Main(string[] args)
        {
            // Get the secrets from the key vault.
            string keyVaultURI = "https://<key-vault-name>.vault.azure.net/";
            var secretClient = new SecretClient(new Uri(keyVaultURI), new DefaultAzureCredential());
            string personalAccessTokenSecretName = "<personal-access-token-secret-name>";
            string serviceBusConnectionStringSecretName = "<Service-Bus-connection-string-secret-name>";
            KeyVaultSecret personalAccessTokenSecret = await secretClient.GetSecretAsync(personalAccessTokenSecretName);
            KeyVaultSecret serviceBusConnectionStringSecret = await secretClient.GetSecretAsync(serviceBusConnectionStringSecretName);

            // Set up the connection parameters for Azure DevOps.
            var azureDevOpsOrganizationURL = new Uri("https://dev.azure.com/<Azure-DevOps-organization-name>/");
            string azureDevOpsTeamProjectID = "<Azure-DevOps-team-project-ID>";
            string azureDevOpsPersonalAccessToken = personalAccessTokenSecret.Value;

            // Set up the event parameters.
            string eventPublisherID = "tfs";
            string eventID = "git.push";
            string eventDescription = "Any stage in any release";
            string resourceVersion = "1.0";

            // Set up the consumer parameters.
            string consumerID = "azureServiceBus";
            string consumerActionID = "serviceBusQueueSend";
            string serviceBusNamespace = "<Service-Bus-namespace>";
            string serviceBusQueueName = "<Service-Bus-queue-name>";
            string consumerActionDescription = $"Send a message to the Service Bus {serviceBusQueueName} queue in the {serviceBusNamespace} namespace.";
            string serviceBusConnectionString = serviceBusConnectionStringSecret.Value;

            // Configure the subscription.
            var subscription = new Subscription()
            {
                PublisherId = eventPublisherID,
                PublisherInputs = new Dictionary<string, string>
                {
                    ["projectId"] = azureDevOpsTeamProjectID
                },
                EventType = eventID,
                EventDescription = eventDescription,
                ResourceVersion = resourceVersion,
                ActionDescription = consumerActionDescription,
                ConsumerActionId = consumerActionID,
                ConsumerId = consumerID,
                ConsumerInputs = new Dictionary<string, string>
                {
                    ["connectionString"] = serviceBusConnectionString,
                    ["queueName"] = serviceBusQueueName
                }
            };

            // Connect to the Azure DevOps organization and get a service hook client.
            var azureDevOpsCredentials = new VssBasicCredential(azureDevOpsPersonalAccessToken, string.Empty);
            var azureDevOpsConnection = new VssConnection(azureDevOpsOrganizationURL, azureDevOpsCredentials);
            var serviceHookClient = azureDevOpsConnection.GetClient<ServiceHooksPublisherHttpClient>();

            // Create the subscription.
            var createdSubscription = await serviceHookClient.CreateSubscriptionAsync(subscription);
            Console.WriteLine($"A subscription was created that has ID {createdSubscription.Id}.");
        }
    }
}