Condividi tramite


Creare un server di stato della richiesta pull con Node.js

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

Il flusso di lavoro della richiesta pull offre agli sviluppatori l'opportunità di ottenere commenti e suggerimenti sul codice dai peer e dagli strumenti automatizzati. Gli strumenti e i servizi non Microsoft possono partecipare al flusso di lavoro delle richieste pull usando l'API di stato della richiesta pull. Questo articolo illustra il processo di creazione di un server di stato per convalidare le pull request in un repository Git di Azure DevOps Services. 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.
Strumenti - Visual Studio Code o un altro editor di codice preferito.
- Node.js. Il download contiene un programma di installazione, che è possibile eseguire per installare il runtime Node.js nel computer locale. Quando si installa Node.js, assicurarsi di mantenere la parte di installazione per il gestore di pacchetti npm , che è selezionata per impostazione predefinita.
Autenticazione Token ID Microsoft Entra con ambito di Codice (stato) per ottenere i permessi per modificare lo stato della Richiesta Pull. Per altre informazioni, vedere Autenticazione di Microsoft Entra.

Creare un server Web di base con Express

I passaggi di questa sezione usano Express, che è un framework Web leggero per Node.js che fornisce molti metodi di utilità HTTP che semplificano la creazione di un server Web. Questo framework fornisce le funzionalità di base necessarie per ascoltare gli eventi di pull request.

  1. Dalla riga di comando creare una nuova cartella di progetto per il server Web.

    mkdir pr-server
    cd pr-server
    
  2. Usare il comando npm init per creare un nuovo file di package.json per il progetto.

    npm init
    

    Selezionare Immettere per accettare le impostazioni predefinite per tutte le opzioni, ad eccezione del punto di ingresso. Modificarlo in app.js

    entry point: (index.js) app.js
    
  3. Installare Express nella directory pr-server usando il comando seguente. Viene installato Express e salvato nell'elenco delle dipendenze.

    npm install express
    
  4. Creare un'app Express come base per il server di stato di avanzamento della PR. I passaggi seguenti si basano sull'esempio express Hello world.

    a) Aprire la cartella del progetto in Visual Studio Code eseguendo il comando seguente dalla pr-server cartella .

    code .
    

    b. Creare un nuovo file (Ctrl + N) e incollare il codice di esempio seguente per creare un server Express di base.

    const express = require('express')
    const app = express()
    
    app.get('/', function (req, res) {
    res.send('Hello World!')
    })
    
    app.listen(3000, function () {
    console.log('Example app listening on port 3000!')
    })
    

    c. Salvare il file come app.js.

  5. Eseguire il server Web di base usando il comando seguente:

    node app.js
    

    Verificare che il server sia in esecuzione navigando su http://localhost:3000/.

Ascolto delle richieste HTTP POST

Il server Web riceverà POST richieste da Azure DevOps Services, quindi è necessario gestire tali richieste nel server.

  1. Alla fine del file app.js aggiungere il codice seguente e salvare il file.

    app.post('/', function (req, res) {
        res.send('Received the POST')
    })
    
  2. Riavviare il server web usando il comando seguente:

    node app.js
    

Configura un hook di servizio per eventi PR

Gli hook del servizio sono una funzionalità di Azure DevOps Services che può avvisare i servizi esterni quando si verificano determinati eventi. Per questo esempio, configurare due ganci di servizio per gli eventi di pull request, in modo che il server di stato possa ricevere una notifica. Il primo è per l'evento creato della richiesta pull e il secondo è per l'evento aggiornato della richiesta pull .

Per ricevere le notifiche dei service hook, esporre una porta su Internet pubblica. L'utilità ngrok è utile per farlo in un ambiente di sviluppo.

  1. Scaricare e decomprimere la versione ngrok appropriata per la piattaforma.

  2. Usare ngrok per avviare l'ascolto sulla stessa porta del server di esempio- porta 3000. Eseguire il comando seguente in una nuova finestra di comando.

    ngrok http 3000
    

    Ngrok crea un URL pubblico che viene inoltrato a localhost:3000. Prendere nota dell'URL, come necessario nel passaggio successivo. L'esempio seguente è simile al seguente:

    http://c3c1bffa.ngrok.io
    
  3. Passa al tuo progetto in Azure DevOps. Ecco un esempio: https://dev.azure.com/<your account>/<your project name>

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

    Lo screenshot mostra

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

    Screenshot mostra come selezionare 'Crea una nuova sottoscrizione' dalla barra degli strumenti.

    Se hai già configurato altri hook di servizio, seleziona il segno più (+) per creare una nuova sottoscrizione per gli hook di servizio.

    Screenshot mostra selezionato il segno più per creare una nuova sottoscrizione di hook del servizio.

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

    Screenshot mostra i webhook selezionati nell'elenco dei servizi.

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

    Lo screenshot mostra la pull request selezionata, creata dall'elenco dei trigger di evento.

  8. Nella pagina Azione, immettere l'URL da ngrok nella casella URL. Selezionare Test per inviare un evento di test al server.

    Screenshot mostra l'URL immesso e il test selezionato per testare l'hook del servizio.

    Nella finestra della console di ngrok un POST ricevuto restituisce un 200 OK, indicando che il server ha ricevuto l'evento del service hook.

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

    Nella finestra Notifica test selezionare la scheda Risposta per visualizzare i dettagli della risposta dal server. Dovrebbe essere visualizzata una lunghezza del contenuto pari a 17 che corrisponde alla lunghezza della stringa del gestore POST, ad esempio "Received the POST".

    Screenshot mostra la scheda risposta selezionata per i risultati del test.

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

Eseguire nuovamente i passaggi da 3 a 9, ma questa volta configurare l'evento pull request aggiornata.

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 .

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.

  1. Le richieste di hook del servizio includono un payload JSON che descrive l'evento. Per analizzare il JSON restituito dall'hook del servizio, installare il pacchetto body-parser .

    npm install body-parser
    
  2. Aggiorna app.js per usare body-parser per analizzare application/json.

    var bodyParser = require('body-parser')
    
    app.use(bodyParser.json())
    
  3. Per semplificare l'esecuzione di chiamate API REST ad Azure Repos, installare il pacchetto azure-devops-node-api.

    npm install azure-devops-node-api 
    
  4. Aggiornare app.js per usare il pacchetto azure-devops-node-api, configurare i dettagli per una connessione all'account e ottenere un'istanza dell'API Git.

    const vsts = require("azure-devops-node-api")
    
    const collectionURL = process.env.COLLECTIONURL    
    const token = process.env.TOKEN
    
    var authHandler = vsts.getBearerHandler(token)
    var connection = new vsts.WebApi(collectionURL, authHandler)
    var vstsGit = connection.getGitApi()
    
  5. Creare una variabile di ambiente per l'URL della raccolta, sostituendo <your account> con il nome dell'organizzazione Azure DevOps.

    setx COLLECTIONURL "https://dev.azure.com/<your account>"
    
  6. Ottieni un token ID Microsoft Entra da usare per la tua app. I token ID Microsoft Entra sono il metodo di autenticazione consigliato per le API REST di Azure DevOps. È possibile ottenere questi token nei modi seguenti:

    • Opzione 1: Interfaccia della riga di comando di Azure (per lo sviluppo/test)
      az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query "accessToken" --output tsv
      
    • Opzione 2: Principale del servizio (per l'ambiente di produzione)
      1. Registrare un'applicazione in Microsoft Entra ID
      2. Creare un segreto client per l'applicazione
      3. Concedere all'applicazione le autorizzazioni appropriate in Azure DevOps
      4. Usare le credenziali dell'entità servizio per ottenere i token programmaticamente

    Per altre informazioni, vedere Autenticazione di Microsoft Entra.

  7. Creare una variabile di ambiente per il token ID Microsoft Entra.

    setx TOKEN "your-entra-id-token-here"
    

Per le applicazioni di produzione, è necessario ottenere i token ID Di Microsoft Entra a livello di codice anziché usare token statici. Ecco come implementare questa operazione usando Microsoft Authentication Library (MSAL) per Node.js:

  1. Installare il pacchetto del nodo MSAL:

    npm install @azure/msal-node
    
  2. Creare un modulo del fornitore di token (tokenProvider.js)

    const { ConfidentialClientApplication } = require('@azure/msal-node');
    
    const clientConfig = {
        auth: {
            clientId: process.env.CLIENT_ID,
            clientSecret: process.env.CLIENT_SECRET,
            authority: `https://login.microsoftonline.com/${process.env.TENANT_ID}`
        }
    };
    
    const cca = new ConfidentialClientApplication(clientConfig);
    
    async function getAccessToken() {
        const clientCredentialRequest = {
            scopes: ['499b84ac-1321-427f-aa17-267ca6975798/.default']
        };
    
        try {
            const response = await cca.acquireTokenByClientCredential(clientCredentialRequest);
            return response.accessToken;
        } catch (error) {
            console.error('Error acquiring token:', error);
            throw error;
        }
    }
    
    module.exports = { getAccessToken };
    
  3. Aggiorna app.js per usare il provider di token.

    const { getAccessToken } = require('./tokenProvider');
    
    // Instead of using a static token, get a fresh token
    app.post("/", async function (req, res) {
        try {
            const token = await getAccessToken();
            var authHandler = vsts.getBearerHandler(token);
            var connection = new vsts.WebApi(collectionURL, authHandler);
    
            // ... rest of your POST handler code
        } catch (error) {
            console.error('Authentication error:', error);
            res.status(500).send('Authentication failed');
        }
    });
    
  4. Aggiornare la funzione post() per leggere i dettagli del PR dal payload dell'hook del servizio. Sono necessari questi valori per il ripristino dello stato.

    var repoId = req.body.resource.repository.id
    var pullRequestId = req.body.resource.pullRequestId
    var title = req.body.resource.title
    
  5. Costruire l'oggetto stato da pubblicare nella pull request.

    State è un'enumerazione di tipo GitStatusState. Usare succeeded per indicare che la pull request ha superato l'ispezione dello stato ed è pronta per essere unita.

    Il description è un valore stringa che viene visualizzato all'utente nella sezione Stato e nel flusso di attività nella visualizzazione dei dettagli della PR.

    Il targetUrl è un URL usato per creare un collegamento per il testo della descrizione nella sezione Stato e nel feed attività, dove gli utenti possono accedere per ottenere altre informazioni sullo stato, ad esempio un report di compilazione o un'esecuzione di test. Se non viene specificato alcun URL, la descrizione viene visualizzata come testo senza collegamento.

    Il contesto name e genre vengono usati per classificare lo stato e distinguerlo dallo stato di registrazione di altri servizi.

        var prStatus = {
            "state": "succeeded",
            "description": "Ready for review",
            "targetUrl": "https://visualstudio.microsoft.com",
            "context": {
                "name": "wip-checker",
                "genre": "continuous-integration"
            }
        }
    
  6. Invece di pubblicare immediatamente lo stato di succeeded, controlla il titolo della pull request per verificare se l'utente ha indicato che la pull request è un lavoro in progresso aggiungendo WIP al titolo. In tal caso, modificare lo stato inviato nuovamente alla richiesta pull.

        if (title.includes("WIP")) {
            prStatus.state = "pending"
            prStatus.description = "Work in progress"
        }
    
  7. Infine, pubblicare lo stato usando il metodo createPullRequestStatus(). Richiede l'oggetto di stato, l'ID del repository e l'ID della pull request. Restituire la risposta alla console del nodo in modo da visualizzare il risultato del post.

    vstsGit.createPullRequestStatus(prStatus, repoId, pullRequestId).then( result => {
        console.log(result)
    })
    
  8. Il metodo risultante dovrebbe essere simile al seguente:

    app.post("/", async function (req, res) {
        try {
            // Get the details about the PR from the service hook payload
            var repoId = req.body.resource.repository.id
            var pullRequestId = req.body.resource.pullRequestId
            var title = req.body.resource.title
    
            // Build the status object that we want to post.
            // Assume that the PR is ready for review...
            var prStatus = {
                "state": "succeeded",
                "description": "Ready for review",
                "targetUrl": "https://visualstudio.microsoft.com",
                "context": {
                    "name": "wip-checker",
                    "genre": "continuous-integration"
                }
            }
    
            // Check the title to see if there is "WIP" in the title.
            if (title.includes("WIP")) {
                // If so, change the status to pending and change the description.
                prStatus.state = "pending"
                prStatus.description = "Work in progress"
            }
    
            // Get the Git API instance and post the status to the PR
            const gitApi = await vstsGit
            const result = await gitApi.createPullRequestStatus(prStatus, repoId, pullRequestId)
            console.log(result)
    
            res.send("Received the POST")
        } catch (error) {
            console.error('Error processing PR status:', error)
            res.status(500).send('Error processing request')
        }
    })
    
  9. Salvare app.js e riavviare l'app node.

    node app.js
    

Crea una nuova pull request per 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).

    Screenshot mostra il pulsante Modifica selezionato dal menu di scelta rapida.

  2. Apportare una modifica e fare il commit nel repository.

    Screenshot mostra la modifica del file e il pulsante Commit selezionato 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.

    Screenshot mostra il nome del nuovo ramo immesso e il pulsante Commit selezionato.

  4. Seleziona il collegamento Crea un pull request.

    Lo screenshot mostra l'opzione selezionata

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

    Screenshot mostra l'aggiunta di WIP al titolo predefinito della pull request.

  6. Una volta che la richiesta pull è stata creata, la sezione dello stato viene visualizzata con la voce Lavoro in corso che collega all'URL specificato nel payload.

    Screenshot mostra la sezione relativa allo 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.