Condividi tramite


Usare Funzioni di Azure per creare criteri ramo personalizzati

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

Il flusso di lavoro della richiesta pull consente agli sviluppatori di ricevere commenti e suggerimenti sul codice dai peer e dagli strumenti automatizzati. Gli strumenti e i servizi non Microsoft possono partecipare anche al flusso di lavoro delle pull request usando l'API Stato PR. Questo articolo illustra come creare una policy del branch personalizzata usando Funzioni di Azure per convalidare le pull request in un repository Git di Azure DevOps. Funzioni di Azure elimina la necessità di effettuare il provisioning e gestire i server, anche quando il carico di lavoro aumenta. Offrono una piattaforma di calcolo completamente gestita con affidabilità e sicurezza elevate.

Per ulteriori informazioni sullo stato delle richieste di pull, consultare Personalizzare ed estendere i flussi di lavoro delle richieste di pull con lo stato delle richieste di pull.

Prerequisiti

Categoria Requisiti
Azienda Un'organizzazione in Azure DevOps con un repository Git.
Funzione di Azure Una Funzione di Azure implementa una soluzione serverless basata su eventi che si integra con Azure DevOps per creare politiche di diramazione personalizzate e automatizzare la convalida delle richieste di pull.
Agganci di servizio Configurare gli hook del servizio per gli eventi della richiesta pull per inviare una notifica alla funzione di Azure quando viene modificata una richiesta pull.
token di accesso personale (PAT) Creare un token di accesso personale con l'ambito Code (status) per ottenere l'autorizzazione a modificare lo stato della pull request. Per altre informazioni, vedere Usa i PAT per autenticarti.

Creare una funzione di Azure di base per ascoltare gli eventi di Azure Repos

Creare la prima funzione di Azure. Modificare quindi il codice nell'esempio in modo che sia simile al codice seguente:

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

Configura un hook di servizio per eventi PR

Gli hook del servizio sono una funzionalità di Azure DevOps che può avvisare i servizi esterni quando si verificano determinati eventi. Per questo esempio, configura un hook del servizio per gli eventi di PR e la tua funzione di Azure riceve una notifica quando viene modificata una pull request. Per ricevere POST richieste quando le richieste pull cambiano, fornire l'hook del servizio con l'URL della funzione di Azure.

Per questo esempio, configurare due hook di servizio. Il primo è per l'evento creato della richiesta pull e il secondo è per l'evento aggiornato della richiesta pull .

  1. Ottenere l'URL della funzione dal portale di Azure facendo clic su Ottieni l'URL della funzione nella visualizzazione funzioni di Azure e copiando l'URL.

    Ottenere l'URL della funzione

    Copiare l'URL della funzione

  2. Passa al tuo progetto in Azure DevOps. Ecco un esempio: https://dev.azure.com/<your organization>/<your project name>

  3. Dal menu di navigazione, passare il puntatore del mouse sull'icona dell'ingranaggio e selezionare Service Hooks.

    Scegliere hook di servizio dal menu di amministrazione

  4. Se si tratta del primo hook del servizio, selezionare + Crea sottoscrizione.

    Selezionare Crea una nuova sottoscrizione dalla barra degli strumenti

    Se hai già configurato altri hook di servizio, seleziona il segno più verde (+) per creare un nuovo abbonamento di hook di servizio.

    Selezionare il segno più verde per creare una nuova sottoscrizione hook del servizio.

  5. Nella finestra di dialogo Nuova sottoscrizione hook del servizio selezionare Web Hooks dall'elenco dei servizi, quindi selezionare Avanti.

    Selezionare web hook dall'elenco dei servizi

  6. Selezionare richiesta pull creata dall'elenco dei trigger di eventi e quindi selezionare Avanti.

    Selezionare la richiesta pull creata dall'elenco dei trigger di evento

  7. Nella pagina Azione immettere l'URL copiato nel passaggio 1 nella casella URL . Selezionare Test per inviare un evento di test al server.

    Immettere l'URL e selezionare Test per testare l'hook del servizio

    Nella finestra del log delle funzioni di Azure, viene visualizzato un oggetto in ingresso POST che ha restituito un 200 OK oggetto, indicando che la funzione ha ricevuto l'evento hook del servizio.

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

    Nella finestra Notifica test selezionare la scheda Risposta per visualizzare i dettagli della risposta dal server. Verrà visualizzata la risposta dal server.

    Selezionare la scheda risposta per visualizzare i risultati del test

  8. Chiudere la finestra della notifica di test e selezionare Fine per creare l'hook di servizio.

Eseguire di nuovo i passaggi da 2 a 8, ma questa volta configurare l'evento aggiornato della richiesta pull .

Importante

Assicurarsi di eseguire due volte i passaggi precedenti e creare hook del servizio per gli eventi di creazione della richiesta pull e aggiornamento della richiesta pull .

Creare una richiesta pull per verificare che la funzione di Azure riceva le notifiche.

Aggiornare lo stato delle PR

Ora che il server può ricevere eventi di hook del servizio quando vengono create nuove richieste pull, aggiorna il server per inviare indietro lo stato alla richiesta pull. È possibile utilizzare il payload JSON pubblicato dall'hook del servizio per determinare quale stato impostare sulla pull request.

Aggiornare il codice della funzione di Azure, simile all'esempio seguente.

Assicurarsi di aggiornare il codice con il nome dell'organizzazione, il nome del progetto, il nome del repository e il token PAT. Per avere l'autorizzazione per modificare lo stato della PR, il PAT richiede l'ambito vso.code_status, che è possibile concedere selezionando l'ambito Code (status) nella pagina Crea un token di accesso personale.

Importante

Questo codice di esempio archivia il pat nel codice, semplificando l'esempio. È consigliabile archiviare i segreti in KeyVault e recuperarli da questa posizione.

Questo esempio esamina il titolo della richiesta pull per verificare se l'utente ha indicato se la richiesta pull è un lavoro in corso aggiungendo WIP al titolo. In tal caso, il codice di esempio modifica lo stato inviato alla richiesta pull (pull request). Sostituire il codice nella funzione di Azure con il codice seguente che aggiorna lo stato inviato indietro alla richiesta di pull.

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

Creare una nuova richiesta pull e testare il server di stato

Ora che il server è in esecuzione e in ascolto delle notifiche di hook di servizio, effettua una pull request per verificarlo.

  1. Inizia nella vista file. Modificare il file readme.md nel repository (o qualsiasi altro file se non si dispone di un readme.md).

    Selezionare Modifica dal menu di scelta rapida

  2. Effettua una modifica e conferma le modifiche nel repository.

    Modificare il file e selezionare Commit dalla barra degli strumenti

  3. Assicurati di eseguire il commit delle modifiche in un nuovo branch in modo da poter creare una PR nel passaggio successivo.

    Immettere un nuovo nome di ramo e selezionare Commit

  4. Seleziona il collegamento Crea un pull request.

    Selezionare Crea una richiesta pull dalla barra dei suggerimenti

  5. Aggiungere WIP nel titolo per verificare la funzionalità dell'app. Selezionare Crea per creare il PR.

    Aggiungere WIP al titolo predefinito della richiesta pull

  6. Dopo aver creato la richiesta pull, viene visualizzata la sezione relativa allo stato, con la voce Lavoro in corso che collega all'URL specificato nel payload.

    Sezione stato con la voce lavoro in corso.

  7. Aggiornare il titolo del pull request e rimuovere il testo WIP e notare che lo stato cambia da In lavorazione a Pronto per la revisione.

Passaggi successivi