Creación de un servidor de estado de PR con Node.js

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

El flujo de trabajo de PR proporciona a los desarrolladores una oportunidad para obtener comentarios sobre su código de homólogos, así como de herramientas automatizadas. Las herramientas y servicios de terceros pueden participar en el flujo de trabajo de PR mediante la API de estado de la PR. Este artículo le guía por el proceso de creación de un servidor de estado para validar PR en un repositorio de Git de Azure DevOps Services. Para obtener más información sobre el estado de la PR, vea Personalización y extensión de flujos de trabajo de PR con el estado de la PR.

Requisitos previos

  • Una organización en Azure DevOps con un repositorio de Git. Si no tiene una organización, regístrese para cargar y compartir código en repositorios ilimitados de Git privados y gratuitos.
  • Instale VS Code u otro editor de código que prefiera. Las instrucciones de esta guía usan VS Code, pero los pasos de otros editores de código son similares.

Instalación de Node.js

A fin de instalar Node.js, descargue la versión LTS adecuada para la plataforma. La descarga contiene un instalador, que puede ejecutar para instalar el runtime de Node.js en el equipo local. Al instalar Node.js, asegúrese de mantener la parte del administrador de paquetes npm de la instalación, que está seleccionada de forma predeterminada.

Creación de un servidor web básico mediante Express

Los pasos de esta sección usan Express, que es un marco web ligero para Node.js que proporciona una serie de métodos de utilidad HTTP que simplifican la creación de un servidor web. Este marco proporciona las funciones básicas necesarias para escuchar eventos de PR.

  1. En la línea de comandos, cree una carpeta de proyecto para el servidor web.

    mkdir pr-server
    cd pr-server
    
  2. Use el comando npm init a fin de crear un archivo package.json para el proyecto.

    npm init
    

    Presione Entrar para aceptar los valores predeterminados de todas las opciones, excepto el punto de entrada. Cámbiela a app.js.

    entry point: (index.js) app.js
    
  3. Instale Express en el directorio pr-server mediante el comando siguiente. Esta acción instala Express y lo guarda en la lista de dependencias.

    npm install express
    
  4. Cree una aplicación Express sencilla en la que se basará el servidor de estado de PR. Los pasos siguientes se basan en el ejemplo Hola mundo de Express. Abra la carpeta del proyecto en VS Code ejecutando el siguiente comando desde la carpeta pr-server.

    code .
    
  5. Cree un archivo (Ctrl + N) y pegue el código de ejemplo siguiente.

    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!')
    })
    
  6. Guarde el archivo como app.js.

  7. Ejecute el servidor web básico mediante el siguiente comando:

    node app.js
    

    Compruebe que el servidor se está ejecutando; para ello, vaya a http://localhost:3000/.

Escucha de solicitudes HTTP POST

El servidor web va a recibir solicitudes POST de Azure DevOps Services, por lo que debe controlar esas solicitudes en el servidor.

  1. Al final del archivo app.js, agregue el código siguiente y guárdelo.

    app.post('/', function (req, res) {
        res.send('Received the POST')
    })
    
  2. Vuelva a ejecutar el servidor web mediante el siguiente comando:

    node app.js
    

Configuración de un enlace de servicio para eventos de PR

Los enlaces de servicio son una característica de Azure DevOps Services que puede avisar a servicios externos cuando se producen determinados eventos. Para este ejemplo, querrá configurar dos enlaces de servicio para eventos de PR, así que se puede notificar al servidor de estado. El primero será para el evento de Solicitud de incorporación de cambios creada y el segundo será para el evento de Solicitud de incorporación de cambios actualizada.

Para recibir las notificaciones del enlace de servicio, deberá exponer un puerto a la red pública de Internet. La utilidad ngrok es muy útil para hacerlo en un entorno de desarrollo.

  1. Descargue y descomprima la versión de ngrok adecuada para su plataforma.

  2. Use ngrok para empezar a escuchar en el mismo puerto que el servidor de ejemplo: puerto 3000. Ejecute el siguiente comando en una nueva ventana de comandos.

    ngrok http 3000
    

    Ngrok creará una dirección URL pública que reenvía a localhost:3000. Anote la dirección URL, ya que la necesitará en el paso siguiente. Tendrá un aspecto similar al siguiente:

    http://c3c1bffa.ngrok.io
    
  3. Vaya al proyecto en Azure DevOps, por ejemplo, https://dev.azure.com/<your account>/<your project name>.

  4. En el menú de navegación, mantenga el puntero sobre el engranaje y seleccione Enlaces de servicio.

    Selección de Enlaces de servicio en el menú de administración

  5. Si este es el primer enlace de servicio, seleccione + Crear suscripción.

    Selección de la opción Crear una suscripción en la barra de herramientas

    Si ya tiene configurados otros enlaces de servicio, seleccione el signo verde más (+) para crear una suscripción de enlace de servicio.

    Selección del signo verde más para crear una suscripción de enlace de servicio.

  6. En el cuadro de diálogo Nueva suscripción de enlaces de servicio, seleccione Enlaces web en la lista de servicios y, después, seleccione Siguiente.

    Selección de enlaces web en la lista de servicios

  7. Seleccione Solicitud de incorporación de cambios creada en la lista de desencadenadores de eventos y, después, seleccione Siguiente.

    Selección de la opción Solicitud de incorporación de cambios creada en la lista de desencadenadores de eventos

  8. En la página Acción, escriba la dirección URL de ngrok en el cuadro URL. Seleccione Probar para enviar un evento de prueba al servidor.

    Introducción de la dirección URL y selección de Probar para probar el enlace de servicio.

    En la ventana de la consola ngrok, verá un elemento POST entrante que ha devuelto un elemento 200 OK, que indica que el servidor ha recibido el evento de enlace de servicio.

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

    En la ventana Notificación de prueba, seleccione la pestaña Respuesta para ver los detalles de la respuesta del servidor. Debería ver una longitud del contenido de 17 que coincida con la longitud de la cadena del controlador POST (es decir, "Recibido el POST").

    Selección de la pestaña respuesta para ver los resultados de la prueba.

  9. Cierre la ventana Notificación de prueba y seleccione Finalizar para crear el enlace de servicio.

Vuelva a seguir los pasos del 3 al 9, pero esta vez configure el evento Solicitud de incorporación de cambios actualizada.

Importante

Asegúrese de seguir los pasos anteriores dos veces y crear enlaces de servicio para los eventos de Solicitud de incorporación de cambios creada y Solicitud de incorporación de cambios actualizada.

Publicación del estado en PR

Ahora que el servidor puede recibir eventos de enlace de servicio cuando se crean PR, actualícelo para publicar el estado de devolución a la PR.

  1. Las solicitudes de enlace de servicio incluyen una carga JSON que describe el evento. Para ayudar a analizar el JSON que devuelve el enlace de servicio, instale el paquete del analizador del cuerpo.

    npm install body-parser
    
  2. Actualice app.js para usar el analizador del cuerpo a fin de analizar application/json.

    var bodyParser = require('body-parser')
    
    app.use(bodyParser.json())
    
  3. Para simplificar la realización de llamadas API REST a Azure Repos, instale el paquete azure-devops-node-api.

    npm install azure-devops-node-api 
    
  4. Actualice app.js para usar el paquete azure-devops-node-api, configure los detalles de una conexión a su cuenta y obtenga una instancia de la API de Git.

    const vsts = require("azure-devops-node-api")
    
    const collectionURL = process.env.COLLECTIONURL    
    const token = process.env.TOKEN
    
    var authHandler = vsts.getPersonalAccessTokenHandler(token)
    var connection = new vsts.WebApi(collectionURL, authHandler)
    
    var vstsGit = connection.getGitApi().then( 
        vstsGit => {                                    
            vstsGit.createPullRequestStatus(prStatus, repoId, pullRequestId).then( result => {
                console.log(result);
            },
            error => {
                console.log(error);
            })
        }, 
        error => { 
            console.log(error);
        } 
    );
    
  5. Cree una variable de entorno para la dirección URL de la colección y reemplace <your account> por el nombre de la organización de Azure DevOps.

    setx COLLECTIONURL "https://dev.azure.com/<your account>"
    
  6. Cree un token de autenticación personal (PAT) para que la aplicación lo use, siguiendo estas instrucciones: Autenticación con tokens de acceso personal. Debe crear un PAT para cada servicio que use a fin de acceder a su cuenta y asignarle un nombre adecuado.

  7. Cree una variable de entorno para el PAT.

    setx TOKEN "yourtokengoeshere"
    
  8. Actualice la función post() para leer los detalles de la PR de la carga del enlace de servicio. Necesitará estos valores para publicar el estado de devolución.

    var repoId = req.body.resource.repository.id
    var pullRequestId = req.body.resource.pullRequestId
    var title = req.body.resource.title
    
  9. Compile el objeto de estado para publicarlo en la PR.

    State es una enumeración de tipo GitStatusState. Use succeeded para indicar que la PR ha superado la comprobación de estado y está lista para fusionarse mediante combinación.

    description es un valor de cadena que se mostrará al usuario en la sección Estado y la fuente de actividades en la vista de detalles de la PR.

    targetUrl es una dirección URL que se usará a fin de crear un vínculo para el texto de descripción en la sección Estado y la fuente de actividades. Este es el lugar donde los usuarios pueden ir para obtener más información sobre el estado como, por ejemplo, un informe de compilación o una ejecución de prueba. Si no se especifica ninguna dirección URL, la descripción aparecerá como texto sin vínculo.

    El contexto name y genre se usan para clasificar el estado y distinguirlo de otro estado de publicación de servicios.

        var prStatus = {
            "state": "succeeded",
            "description": "Ready for review",
            "targetUrl": "https://visualstudio.microsoft.com",
            "context": {
                "name": "wip-checker",
                "genre": "continuous-integration"
            }
        }
    
  10. En lugar de simplemente publicar el estado succeeded a ciegas, inspeccione el título de la PR para ver si el usuario ha indicado si la PR es un trabajo en curso agregando WIP al título. Si es así, cambie el estado devuelto a la PR.

        if (title.includes("WIP")) {
            prStatus.state = "pending"
            prStatus.description = "Work in progress"
        }
    
  11. Por último, publique el estado mediante el método createPullRequestStatus(). Requiere el objeto de estado, el id. del repositorio y el id. de la PR. Genera la respuesta a la consola del nodo para que pueda ver el resultado de la publicación.

    vstsGit.createPullRequestStatus(prStatus, repoId, pullRequestId).then( result => {
        console.log(result)
    })
    
  12. El método resultante debe tener un aspecto similar al siguiente:

    app.post("/", function (req, res) {
    
        // 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"
        }
    
        // Post the status to the PR
        vstsGit.createPullRequestStatus(prStatus, repoId, pullRequestId).then( result => {
            console.log(result)
        })
    
        res.send("Received the POST")
    })
    
  13. Guarde app.js y reinicie la aplicación de nodo.

    node app.js
    

Creación de una PR para probar el servidor de estado

Ahora que el servidor está en ejecución y escucha notificaciones de enlace de servicio, cree una PR para probarlo.

  1. Comience en la vista de archivos. Edite el archivo readme.md en el repositorio (o cualquier otro archivo si no tiene uno readme.md).

    Selección de Editar en el menú contextual.

  2. Realice una edición y confirme los cambios en el repositorio.

    Edición del archivo y selección de Confirmar en la barra de herramientas

  3. Asegúrese de confirmar los cambios en una nueva rama para que pueda crear una PR en el paso siguiente.

    Introducción de un nuevo nombre de rama y selección de Confirmar

  4. Seleccione el vínculo Crear una solicitud de incorporación de cambios.

    Selección de Crear una solicitud de incorporación de cambios en la barra de sugerencias

  5. Agregue WIP en el título para probar la función de la aplicación. Seleccione Crear para crear la PR.

    Incorporación de WIP al título de la PR predeterminado

  6. Una vez creada la PR, verá la sección Estado, con la entrada Trabajo en curso que vincula a la dirección URL especificada en la carga.

    Sección Estado con la entrada Trabajo en curso.

  7. Actualice el título de la PR, quite el texto WIP y observe que el estado cambia de Trabajo en curso a Listo para revisión.

Pasos siguientes