Freigeben über


Verwenden von Azure Functions zum Erstellen benutzerdefinierter Branchrichtlinien

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

Der Pull-Anforderungsworkflow (PR) ermöglicht Entwicklern, Feedback zu ihrem Code von Peers und automatisierten Tools zu erhalten. Nicht-Microsoft-Tools und -Dienste können auch mithilfe der PR-Status-API am PR-Workflow teilnehmen. Dieser Artikel führt Sie durch das Erstellen einer benutzerdefinierten Verzweigungsrichtlinie mithilfe von Azure Functions zum Überprüfen von PRs in einem Azure DevOps Git-Repository. Azure Functions beseitigt die Notwendigkeit, Server bereitzustellen und zu verwalten, auch wenn Ihre Arbeitsauslastung wächst. Sie bieten eine vollständig verwaltete Computeplattform mit hoher Zuverlässigkeit und Sicherheit.

Weitere Informationen zu PR-Status finden Sie unter Anpassen und Erweitern von Pull Request-Workflows mit Pull Request-Status.

Voraussetzungen

Kategorie Anforderungen
Organisation Eine Organisation in Azure DevOps mit einem Git-Repository.
Azure-Funktion Eine Azure-Funktion, die eine serverlose, ereignisgesteuerte Lösung implementiert, die in Azure DevOps integriert wird, um benutzerdefinierte Verzweigungsrichtlinien zu erstellen und die PR-Validierung zu automatisieren.
Dienst-Hooks Konfigurieren Sie Service-Hooks für PR-Ereignisse, um Ihre Azure-Funktion zu benachrichtigen, wenn sich eine Pullanforderung ändert.
Authentifizierung Microsoft Entra ID Token mit dem Code (Status) Bereich, um die Berechtigung zur Änderung des PR-Status zu erhalten. Weitere Informationen finden Sie unter Microsoft Entra-Authentifizierung.

Erstellen einer einfachen Azure-Funktion zum Überwachen von Azure Repos-Ereignissen

Erstellen Sie Ihre erste Azure-Funktion. Ändern Sie dann den Code im Beispiel so, dass er wie der folgende Code aussieht:

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    try
    {
        log.Info("Service Hook Received.");

        // Get request body
        dynamic data = await req.Content.ReadAsAsync<object>();

        log.Info("Data Received: " + data.ToString());

        // Get the pull request object from the service hooks payload
        dynamic jObject = JsonConvert.DeserializeObject(data.ToString());

        // Get the pull request id
        int pullRequestId;
        if (!Int32.TryParse(jObject.resource.pullRequestId.ToString(), out pullRequestId))
        {
            log.Info("Failed to parse the pull request id from the service hooks payload.");
        };

        // Get the pull request title
        string pullRequestTitle = jObject.resource.title;

        log.Info("Service Hook Received for PR: " + pullRequestId + " " + pullRequestTitle);

        return req.CreateResponse(HttpStatusCode.OK);
    }
    catch (Exception ex)
    {
        log.Info(ex.ToString());
        return req.CreateResponse(HttpStatusCode.InternalServerError);
    }
}

Konfigurieren eines Diensthakens für PR-Ereignisse

Dienst-Hooks sind ein Azure DevOps-Feature, das externe Dienste benachrichtigen kann, wenn bestimmte Ereignisse auftreten. Richten Sie für dieses Beispiel einen Dienst-Hook für PR-Ereignisse ein, wird Ihre Azure-Funktion benachrichtigt, wenn sich eine Pullanforderung ändert. Um POST-Anfragen zu erhalten, wenn sich Pull-Requests ändern, geben Sie den Dienst-Hook mit der Azure Function URL an.

Konfigurieren Sie für dieses Beispiel zwei Diensthaken. Der erste ist für das Pull Request erstellt-Ereignis und der zweite für das Pull Request aktualisiert-Ereignis.

  1. Rufen Sie die Funktions-URL aus dem Azure-Portal ab, indem Sie in der Azure-Funktionsansicht auf die URL "Funktion abrufen " klicken und die URL kopieren.

    Url der Funktion abrufen

    Url der Funktion kopieren

  2. Navigieren Sie zu Ihrem Projekt in Azure DevOps, z. B. https://dev.azure.com/<your organization>/<your project name>

  3. Zeigen Sie im Navigationsmenü mit dem Mauszeiger auf das Zahnrad, und wählen Sie Service Hooks aus.

    Auswählen von Dienst-Hooks aus dem Menü

  4. Wenn es sich um Ihren ersten Diensthaken handelt, wählen Sie +Abonnement erstellen.

    Wählen Sie auf der Symbolleiste

    Wenn Sie bereits andere Diensthaken konfiguriert haben, wählen Sie das grüne Plus aus (+) , um ein neues Service hook-Abonnement zu erstellen.

    Wählen Sie das grüne Pluszeichen aus, um ein neues Service hook-Abonnement zu erstellen.

  5. Wählen Sie im Dialogfeld "Neues Service Hooks-Abonnement" Web Hooks aus der Liste der Dienste aus, und wählen Sie dann Weiteraus.

    Auswählen von Web-Hooks aus der Liste der Dienste

  6. Wählen Sie in der Liste der Ereignistrigger Pull Request erstellt aus, und wählen Sie dann Weiter aus.

    Auswählen der aus der Liste der Ereignistrigger erstellten Pullanforderung

  7. Geben Sie auf der Seite "Aktion" die URL ein, die Sie in Schritt 1 im URL-Feld kopiert haben. Wählen Sie Test- aus, um ein Testereignis an Ihren Server zu senden.

    Geben Sie die URL ein, und wählen Sie

    Im Azure-Funktionsprotokollfenster sehen Sie, dass eine eingehende POST ein 200 OK zurückgegeben hat, was darauf hinweist, dass Ihre Funktion das Diensthakenereignis empfangen hat.

    HTTP Requests
    -------------
    
    POST /                         200 OK
    

    Wählen Sie im Fenster "Testbenachrichtigung" die Registerkarte "Antwort" aus, um die Details der Antwort vom Server anzuzeigen. Sie sollten die Antwort von Ihrem Server sehen.

    Wählen Sie die Registerkarte

  8. Schließen Sie das Fenster „Testbenachrichtigung“, und wählen Sie Fertig stellen aus, um den Service Hook zu erstellen.

Führen Sie die Schritte 2 bis 8 erneut durch, aber dieses Mal konfigurieren Sie das Ereignis Pull-Anforderung aktualisiert.

Von Bedeutung

Stellen Sie sicher, dass Sie die vorherigen Schritte zweimal ausführen, und Service Hooks sowohl für das Pull Request erstellt-Ereignis als auch für das Pull Request aktualisiert-Ereignis erstellen.

Erstellen Sie eine Pull-Anforderung, um zu überprüfen, ob Ihre Azure-Funktion Benachrichtigungen empfängt.

Bereitstellen des Status in PRs

Nachdem Ihr Server nun Service Hook-Ereignisse empfangen kann, wenn neue PRs erstellt werden, aktualisieren Sie ihn so, dass er den Status an den PR zurückpostet. Sie können die JSON-Nutzlast verwenden, die vom Dienst-Hook bereitgestellt wird, um zu bestimmen, welcher Status für Ihre PR festgelegt werden soll.

Aktualisieren Sie den Code Ihrer Azure-Funktion, ähnlich dem folgenden Beispiel.

Aktualisieren Sie den Code mit dem Namen Ihrer Organisation, dem Projektnamen, dem Repositorynamen und dem Microsoft Entra ID-Token. Um über die Berechtigung zum Ändern des PR-Status zu verfügen, erfordert das Token vso.code_status Bereich, den Sie über die Microsoft Entra-Authentifizierung abrufen können.

Von Bedeutung

Dieser Beispielcode speichert das Token im Code und vereinfacht das Beispiel. Es wird empfohlen, geheime Schlüssel in Azure Key Vault zu speichern und von dort aus mithilfe der verwalteten Identität für erhöhte Sicherheit abzurufen.

In diesem Beispiel wird der PR-Titel überprüft, um festzustellen, ob der Benutzer angegeben hat, ob es sich bei der PR um eine laufende Arbeit handelt, indem WIP zum Titel hinzugefügt wird. Wenn ja, ändert der Beispielcode Den an den PR zurückgeposteten Status. Ersetzen Sie den Code in Ihrer Azure Function durch den folgenden Code, der den an den PR zurück geposteten Status aktualisiert.

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;

private static string organizationName = "[Organization Name]";  // Organization name
private static string projectName      = "[Project Name]";       // Project name
private static string repositoryName   = "[Repo Name]";          // Repository name

/*
    This is here just to simplify the sample, it is recommended to store
    secrets in Azure Key Vault and retrieve them using managed identity.
*/
private static string accessToken = "[MICROSOFT_ENTRA_TOKEN]";

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    try
    {
        log.Info("Service Hook Received.");

        // Get request body
        dynamic data = await req.Content.ReadAsAsync<object>();

        log.Info("Data Received: " + data.ToString());

        // Get the pull request object from the service hooks payload
        dynamic jObject = JsonConvert.DeserializeObject(data.ToString());

        // Get the pull request id
        int pullRequestId;
        if (!Int32.TryParse(jObject.resource.pullRequestId.ToString(), out pullRequestId))
        {
            log.Info("Failed to parse the pull request id from the service hooks payload.");
        };

        // Get the pull request title
        string pullRequestTitle = jObject.resource.title;

        log.Info("Service Hook Received for PR: " + pullRequestId + " " + pullRequestTitle);

        PostStatusOnPullRequest(pullRequestId, ComputeStatus(pullRequestTitle));

        return req.CreateResponse(HttpStatusCode.OK);
    }
    catch (Exception ex)
    {
        log.Info(ex.ToString());
        return req.CreateResponse(HttpStatusCode.InternalServerError);
    }
}

private static void PostStatusOnPullRequest(int pullRequestId, string status)
{
    string Url = string.Format(
        @"https://dev.azure.com/{0}/{1}/_apis/git/repositories/{2}/pullrequests/{3}/statuses?api-version=4.1",
        organizationName,
        projectName,
        repositoryName,
        pullRequestId);

    using (HttpClient client = new HttpClient())
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        var method = new HttpMethod("POST");
        var request = new HttpRequestMessage(method, Url)
        {
            Content = new StringContent(status, Encoding.UTF8, "application/json")
        };

        using (HttpResponseMessage response = client.SendAsync(request).Result)
        {
            response.EnsureSuccessStatusCode();
        }
    }
}

private static string ComputeStatus(string pullRequestTitle)
{
    string state = "succeeded";
    string description = "Ready for review";

    if (pullRequestTitle.ToLower().Contains("wip"))
    {
        state = "pending";
        description = "Work in progress";
    }

    return JsonConvert.SerializeObject(
        new
        {
            State = state,
            Description = description,
            TargetUrl = "https://visualstudio.microsoft.com",

            Context = new
            {
                Name = "PullRequest-WIT-App",
                Genre = "pr-azure-function-ci"
            }
        });
}

Erstellen Sie einen neuen PR und testen Sie den Statusserver

Nachdem Ihr Server nun läuft und auf Servicehook-Benachrichtigungen wartet, erstellen Sie eine Pull-Anfrage, um die Funktionalität zu testen.

  1. Beginnen Sie in der Dateiansicht. Bearbeiten Sie die readme.md Datei in Ihrem Repository (oder eine andere Datei, wenn Sie keine readme.md haben).

    Wählen Sie im Kontextmenü

  2. Nehmen Sie eine Bearbeitung vor, und committen Sie die Änderungen in das Repository.

    Bearbeiten Sie die Datei, und wählen Sie

  3. Stellen Sie sicher, dass Sie die Änderungen in einen neuen Branch committen, damit Sie im nächsten Schritt einen PR erstellen können.

    Geben Sie einen neuen Branch-Namen ein und wählen Sie

  4. Wählen Sie den Link Pull Request erstellen aus.

    Wählen Sie in der Vorschlagsleiste

  5. Fügen Sie WIP- im Titel hinzu, um die Funktionalität der App zu testen. Wählen Sie Erstellen aus, um den PR zu erstellen.

    Hinzufügen von WIP zum Standardtitel für PRs

  6. Sobald der PR erstellt wird, wird der Statusabschnitt angezeigt, mit dem Eintrag In Bearbeitung, der mit der in der Nutzlast angegebenen URL verknüpft ist.

    Statusabschnitt mit Dem Eintrag

  7. Aktualisieren Sie den PR-Titel, und entfernen Sie den WIP--Text, und beachten Sie, dass sich der Status von Arbeit in Bearbeitung in Bereit zur Überprüfungändert.

Nächste Schritte