Delen via


Azure Functions gebruiken om aangepast vertakkingsbeleid te maken

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

De pull-aanvraagwerkstroom (PR) biedt ontwikkelaars de mogelijkheid om feedback te krijgen over hun code van peers en van geautomatiseerde hulpprogramma's. Hulpprogramma's en services van derden kunnen deelnemen aan de pull-werkstroom met behulp van de PR-status-API. In dit artikel wordt u begeleid bij het maken van een aangepast vertakkingsbeleid met behulp van Azure Functions om PULL's te valideren in een Git-opslagplaats van Azure DevOps Services. Met Azure Functions hoeft u zich geen zorgen te maken over het inrichten en onderhouden van servers, met name wanneer uw workload groeit. Azure Functions biedt een volledig beheerd rekenplatform met hoge betrouwbaarheid en beveiliging.

Zie Werkstromen voor pull-aanvragen aanpassen en uitbreiden met de status van de pull-aanvraag voor meer informatie over pr-status.

Vereisten

Een organisatie in Azure DevOps met een Git-opslagplaats. Als u geen organisatie hebt, meldt u zich aan om code te uploaden en te delen in gratis onbeperkte privé-Git-opslagplaatsen.

Een eenvoudige Azure-functie maken om te luisteren naar Gebeurtenissen van Azure-opslagplaatsen

Volg de documentatie voor het maken van uw eerste Azure-functie om een eenvoudige functie te maken. Wijzig de code in het voorbeeld om er als volgt uit te zien:

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

Een servicehook configureren voor pr-gebeurtenissen

Servicehook is een Azure DevOps Services-functie waarmee externe services kunnen worden gewaarschuwd wanneer bepaalde gebeurtenissen optreden. Voor dit voorbeeld wilt u een servicehook instellen voor pr-gebeurtenissen. Uw Azure-functie wordt op de hoogte gesteld wanneer een pull-aanvraag wordt gewijzigd. Als u aanvragen wilt ontvangen POST wanneer pull-aanvragen worden gewijzigd, moet u de servicehook opgeven met de URL van de Azure-functie.

Voor dit voorbeeld moet u twee servicehook configureren. De eerste is voor de gebeurtenis voor het maken van de pull-aanvraag en de tweede voor de bijgewerkte gebeurtenis van de pull-aanvraag.

  1. Haal de functie-URL op uit de Azure-portal door te klikken op de functie-URL Ophalen in de Azure-functieweergave en de URL te kopiëren.

    Functie-URL ophalen

    Functie-URL kopiëren

  2. Blader naar uw project in Azure DevOps, bijvoorbeeld https://dev.azure.com/<your organization>/<your project name>

  3. Beweeg in het navigatiemenu de muisaanwijzer over het tandwiel en selecteer Service Hooks.

    Servicehook kiezen in het beheermenu

  4. Als dit uw eerste servicehook is, selecteert u + Abonnement maken.

    Selecteer Een nieuw abonnement maken op de werkbalk

    Als u al andere servicehookhook hebt geconfigureerd, selecteert u het groene plusteken (+) om een nieuw servicehookabonnement te maken.

    Selecteer het groene plusteken om een nieuw servicehookabonnement te maken.

  5. Selecteer in het dialoogvenster Nieuw servicehookabonnement webhook in de lijst met services en selecteer vervolgens Volgende.

    Webhook selecteren in de lijst met services

  6. Selecteer Pull-aanvraag die is gemaakt in de lijst met gebeurtenistriggers en selecteer vervolgens Volgende.

    Pull-aanvraag selecteren die is gemaakt in de lijst met gebeurtenistriggers

  7. Voer op de pagina Actie de URL in die u in stap 1 in het vak URL hebt gekopieerd. Selecteer Testen om een test gebeurtenis naar uw server te verzenden.

    Voer de URL in en selecteer Testen om de servicehook te testen

    In het venster van het Azure-functielogboek ziet u een binnenkomende POST functie die een 200 OKretourneert, waarmee wordt aangegeven dat uw functie de servicehookgebeurtenis heeft ontvangen.

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

    Selecteer in het venster Testmelding het tabblad Antwoord om de details van het antwoord van uw server te bekijken. U ziet het antwoord van uw server.

    Selecteer het tabblad Antwoord om de resultaten van de test te bekijken

  8. Sluit het venster Testmelding en selecteer Voltooien om de servicehook te maken.

Voer stap 2-8 opnieuw uit, maar deze keer configureert u de bijgewerkte gebeurtenis van de pull-aanvraag.

Belangrijk

Zorg ervoor dat u de voorgaande stappen twee keer doorloopt en servicehook maakt voor zowel de gemaakte pull-aanvraag als de bijgewerkte gebeurtenissen voor pull-aanvragen.

Maak een pull-aanvraag om te controleren of uw Azure-functie meldingen ontvangt.

Status posten naar PULL's

Nu uw server servicehook-gebeurtenissen kan ontvangen wanneer er nieuwe PULL's worden gemaakt, werkt u deze bij om de status terug te plaatsen naar de pull-aanvraag. U kunt de JSON-nettolading gebruiken die door de servicehook is gepost om te bepalen welke status u voor uw pull-aanvraag wilt instellen.

Werk de code van uw Azure-functie bij zodat deze eruitziet als in het volgende voorbeeld.

Zorg ervoor dat u de code bijwerkt met de naam van uw organisatie, projectnaam, opslagplaatsnaam en PAT-token. Als u toestemming wilt hebben om de pr-status te wijzigen, vereist de PAT vso.code_status bereik, dat u kunt verlenen door het bereik Code (status) te selecteren op de pagina Een persoonlijk toegangstoken maken.

Belangrijk

In deze voorbeeldcode wordt de PAT opgeslagen in code om het voorbeeld te vereenvoudigen. Het wordt aanbevolen om geheimen op te slaan in KeyVault en ze daar op te halen.

In dit voorbeeld wordt de titel van de pull-aanvraag gecontroleerd om te zien of de gebruiker heeft aangegeven of de pull-aanvraag wordt uitgevoerd door WIP toe te voegen aan de titel. Zo ja, dan wijzigt de voorbeeldcode de status die wordt teruggezet naar de pull-aanvraag. Vervang de code in uw Azure-functie door de volgende code voor het implementeren van het bijwerken van de status die wordt teruggezet naar de pull-aanvraag.

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 KeyVault and retrieve them from there.
*/
private static string pat = "[PAT 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("Basic", Convert.ToBase64String(
                ASCIIEncoding.ASCII.GetBytes(
                string.Format("{0}:{1}", "", pat))));

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

Een nieuwe pull-aanvraag maken om de statusserver te testen

Nu uw server wordt uitgevoerd en luistert naar servicehookmeldingen, maakt u een pull-aanvraag om deze te testen.

  1. Begin in de bestandsweergave. Bewerk het readme.md bestand in uw opslagplaats (of een ander bestand als u geen readme.md hebt).

    Selecteer Bewerken in het contextmenu

  2. Breng een bewerking aan en voer de wijzigingen door in de opslagplaats.

    Bewerk het bestand en selecteer Doorvoeren op de werkbalk

  3. Zorg ervoor dat u de wijzigingen doorvoert in een nieuwe vertakking, zodat u in de volgende stap een pull-aanvraag kunt maken.

    Voer een nieuwe vertakkingsnaam in en selecteer Doorvoeren

  4. Selecteer de koppeling Een pull-aanvraag maken.

    Selecteer Een pull-aanvraag maken op de suggestiebalk

  5. Voeg WIP toe aan de titel om de functionaliteit van de app te testen. Selecteer Maken om de pull-aanvraag te maken.

    WIP toevoegen aan de standaardtitel voor pull-aanvraag

  6. Zodra de pull-aanvraag is gemaakt, ziet u de statussectie, met de vermelding Werk in uitvoering die is gekoppeld aan de URL die is opgegeven in de nettolading.

    De sectie Status met de invoer Werk wordt uitgevoerd.

  7. Werk de titel van de pull-aanvraag bij en verwijder de WIP-tekst en houd er rekening mee dat de status van Werk wordt gewijzigd in Gereed voor revisie.

Volgende stappen