Använda Azure Functions för att skapa anpassade grenprinciper

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

Arbetsflödet för pull-begäran (PR) ger utvecklare möjlighet att få feedback om sin kod från peer-datorer samt från automatiserade verktyg. Verktyg och tjänster från tredje part kan delta i PR-arbetsflödet med hjälp av API:et FÖR PR-status. Den här artikeln vägleder dig genom processen att skapa en anpassad grenprincip med hjälp av Azure Functions för att validera pr:er på en Azure DevOps Services Git-lagringsplats. Med Azure Functions behöver du inte bekymra dig om etablering och underhåll av servrar, särskilt när din arbetsbelastning växer. Azure Functions tillhandahåller en fullständigt hanterad beräkningsplattform med hög tillförlitlighet och säkerhet.

Mer information om PR-status finns i Anpassa och utöka arbetsflöden för pull-begäranden med pull-begärandestatus.

Förutsättningar

En organisation i Azure DevOps med en Git-lagringsplats. Om du inte har en organisation kan du registrera dig för att ladda upp och dela kod i kostnadsfria obegränsade privata Git-lagringsplatser.

Skapa en grundläggande Azure-funktion för att lyssna på Azure Repos-händelser

Följ dokumentationen för att skapa din första Azure-funktion för att skapa en enkel funktion. Ändra koden i exemplet så här:

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

Konfigurera en tjänstkrok för PR-händelser

Tjänstkrokar är en Azure DevOps Services-funktion som kan varna externa tjänster när vissa händelser inträffar. I det här exemplet vill du konfigurera en tjänstkrok för PR-händelser. Azure-funktionen meddelas när en pull-begäran ändras. För att kunna ta emot POST begäranden när pull-begäranden ändras måste du tillhandahålla tjänstkroken med Azure-funktions-URL:en.

För det här exemplet måste du konfigurera 2 tjänstkrokar. Den första kommer att vara för händelsen pull-begäran som skapats och den andra kommer att vara för den uppdaterade händelsen pull-begäran.

  1. Hämta funktions-URL:en från Azure-portalen genom att klicka på hämta funktions-URL:en i Azure-funktionsvyn och kopiera URL:en.

    Hämta funktions-URL

    Url för kopieringsfunktionen

  2. Bläddra till projektet i Azure DevOps, t.ex. https://dev.azure.com/<your organization>/<your project name>

  3. Hovra över kugghjulet på navigeringsmenyn och välj Service Hooks.

    Välj Tjänstkrokar på administratörsmenyn

  4. Om det här är din första tjänstkrok väljer du + Skapa prenumeration.

    Välj Skapa en ny prenumeration i verktygsfältet

    Om du redan har konfigurerat andra tjänstkrokar väljer du det gröna plustecknet (+) för att skapa en ny prenumeration på tjänstkroken.

    Välj det gröna plustecknet för att skapa en ny tjänsthookprenumeration.

  5. Välj Web Hooks i listan över tjänster i dialogrutan New Service Hooks Subscription (Ny tjänst hooks-prenumeration) och välj sedan Nästa.

    Välj webbkrokar i listan över tjänster

  6. Välj Pull-begäran som skapats i listan över händelseutlösare och välj sedan Nästa.

    Välj pull-begäran som skapats i listan över händelseutlösare

  7. På sidan Åtgärd anger du den URL som du kopierade i steg 1 i RUTAN URL . Välj Test för att skicka en testhändelse till servern.

    Ange URL:en och välj Testa för att testa tjänstkroken

    I fönstret Azure-funktionslogg visas en inkommande POST som returnerade en 200 OK, som anger att din funktion tog emot service hook-händelsen.

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

    I fönstret Testmeddelande väljer du fliken Svar för att se information om svaret från servern. Du bör se svaret från servern.

    Välj svarsfliken för att se resultatet av testet

  8. Stäng fönstret Testmeddelande och välj Slutför för att skapa tjänstkroken.

Gå igenom steg 2–8 igen, men den här gången konfigurerar du den uppdaterade händelsen pull-begäran.

Viktigt!

Se till att gå igenom föregående steg två gånger och skapa tjänstkrokar för både pull-begäran som skapats och uppdaterade händelser för pull-begäran.

Skapa en pull-begäran för att kontrollera att azure-funktionen tar emot meddelanden.

Publicera status till PRs

Nu när servern kan ta emot tjänstkrokhändelser när nya pr-begärandena skapas uppdaterar du den för att publicera bakåtstatus till PR. Du kan använda JSON-nyttolasten som publicerats av tjänstkroken för att avgöra vilken status som ska anges för din PR.

Uppdatera koden för din Azure-funktion så att den ser ut som i följande exempel.

Se till att uppdatera koden med ditt organisationsnamn, projektnamn, lagringsplatsnamn och PAT-token. För att få behörighet att ändra PR-status kräver PAT vso.code_status omfång som du kan bevilja genom att välja kodomfånget (status)sidan Skapa en personlig åtkomsttoken .

Viktigt!

Den här exempelkoden lagrar PAT i koden för att förenkla exemplet. Vi rekommenderar att du lagrar hemligheter i KeyVault och hämtar dem därifrån.

Det här exemplet inspekterar PR-titeln för att se om användaren har angett om PR är ett pågående arbete genom att lägga till WIP i rubriken. I så fall ändrar exempelkoden statusen som publiceras tillbaka till PR. Ersätt koden i Din Azure-funktion med följande kod för att implementera uppdatering av statusen som publiceras tillbaka till PR.

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

Skapa en ny PR för att testa statusservern

Nu när servern körs och lyssnar efter service hook-meddelanden skapar du en pull-begäran för att testa den.

  1. Starta i filvyn. Redigera readme.md filen på lagringsplatsen (eller någon annan fil om du inte har en readme.md).

    Välj Redigera på snabbmenyn

  2. Gör en redigering och checka in ändringarna på lagringsplatsen.

    Redigera filen och välj Checka in i verktygsfältet

  3. Se till att checka in ändringarna i en ny gren så att du kan skapa en pr i nästa steg.

    Ange ett nytt grennamn och välj Checka in

  4. Välj länken Skapa en pull-begäran.

    Välj Skapa en pull-begäran från förslagsfältet

  5. Lägg till WIP i rubriken för att testa appens funktioner. Välj Skapa för att skapa PR.

    Lägg till WIP i standard-PR-rubriken

  6. När pr har skapats visas statusavsnittet med posten Arbete pågår som länkar till url:en som anges i nyttolasten.

    Statusavsnitt med posten Arbete pågår.

  7. Uppdatera PR-rubriken och ta bort WIP-texten och observera att statusen ändras från Arbete pågår till Klar för granskning.

Nästa steg

  • I den här artikeln har du lärt dig grunderna i hur du skapar en serverlös Azure-funktion som lyssnar efter PR-händelser via tjänstkrokar och kan publicera statusmeddelanden med hjälp av status-API:et. Mer information om status-API:et för pull-begäran finns i REST API-dokumentationen.
  • Konfigurera en grenprincip för en extern tjänst.