共用方式為


以程式方式建立服務鉤子訂閱

Azure DevOps 服務 |Azure DevOps Server |Azure DevOps Server 2022

當 Azure DevOps 專案中發生特定事件時,您可以使用訂用帳戶對外部或取用者服務執行動作。 例如,訂用帳戶可以在組建失敗時通知您的服務。

若要以程序設計方式建立訂用帳戶,您可以使用訂用帳戶 REST API。 本文提供建立訂用帳戶的範例要求和範例程序代碼。

先決條件

類別 要求
專案存取 Project 成員
數據 - 項目識別碼。 使用 專案 REST API 來取得專案標識碼。
- 事件識別碼和設定。 請參閱 服務攔截事件
- 取用者和動作識別碼和設定。 請參閱 服務掛勾使用者

支援的事件

Azure DevOps 支援許多觸發事件。 範例包括下列事件:

  • 建置已完成
  • 推送的程式代碼(適用於 Git 專案)
  • 已建立或更新提取要求(針對 Git 專案)
  • 提交的程式代碼(適用於 Team Foundation 版本控制專案)
  • 已建立、更新、刪除、還原或批注的工作專案

若要控制哪些事件觸發動作,您可以在訂用帳戶上設定篩選。 例如,您可以根據組建狀態篩選組建已完成事件。

建立請求

當您建立訂用帳戶時,您可以使用 HTTP POST 要求的本文來指定專案識別碼、事件、取用者、動作和相關設定。

您可以使用下列請求來為組建完成事件建立訂閱。 在這個範例中,當 WebSite.CI 建置失敗時,訂閱會將POST要求傳送至 https://myservice/event

要求

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

強烈建議針對 JSON 物件中私人數據的安全性使用安全的 HTTPS URL。

回應

建立訂用帳戶的要求會產生類似下列回應的回應:

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

如果訂用帳戶要求失敗,您會收到 HTTP 回應碼 400,其中包含具有進一步詳細數據的訊息。

事件發生時會發生什麼事?

事件發生時,會評估專案中所有已啟用的訂用帳戶。 然後,針對所有匹配的訂用帳戶執行消費者操作。

資源版本 (進階)

當 API 處於預覽狀態時,適用資源版本設定。 在大部分情況下,將 1.0 指定為資源版本是最安全的路由。

傳送給特定消費者的事件有效負載包含主體資源的 JSON 表示法。 例如,傳送至 Webhook、Azure 服務總線和 Azure 記憶體的承載包含組建或工作專案的相關信息。 此資源的表示法可以有各種形式或版本。

您可以透過訂閱中的resourceVersion欄位,指定要傳送給消費者服務的資源版本。

資源版本與 API 版本相同。 如果您未指定資源版本,則會使用最新版本 latest released。 為了協助確保一段時間的事件承載一致,請一律指定資源版本。

常見問題

問:是否有服務可以手動訂閱?

答:是的。 如需您可以從專案管理頁面訂閱之服務的詳細資訊,請參閱 與服務勾點整合

問:我可以使用 C# 連結庫來建立訂用帳戶嗎?

不過,這裡有一個範例可以幫助你開始。 若要向 Azure DevOps 進行驗證,下列程式代碼會使用儲存在 Azure Key Vault 中的個人存取令牌 (PAT)。 在生產環境中,使用更安全的驗證方法。 如需詳細資訊,請參閱 選擇正確的驗證機制

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}.");
        }
    }
}