Docs Menu
Docs Home
/ /
Servicios de aplicaciones Atlas

Tutorial: Compile un rastreador de contribuciones de GitHub sin servidor mediante Activadores, Functions y Values

Tiempo estimado para completar: 30 minutos

En este tutorial, utilizará Atlas App Services para crear una aplicación sin servidor que monitoree los repositorios de GitHub y haga un seguimiento de las contribuciones.

La aplicación de servicios de aplicaciones que cree tendrá varias características:

  • Realice un seguimiento de los usuarios que han contribuido a su proyecto en una colección de MongoDB Atlas.

  • Deje un comentario que dé la bienvenida a los nuevos colaboradores cuando abran una solicitud de extracción o presenten un problema.

  • Genere y envíe un informe semanal que resuma las contribuciones a su repositorio.

Después de completar este tutorial, sabrá cómo realizar las siguientes tareas:

  • Escriba y ejecute funciones sin servidor que manejen la lógica de su aplicación.

  • Automatice las tareas programadas y responda a los datos cambiantes con Atlas Triggers.

  • Almacena y accede a datos estáticos, como claves API, en Valores.

  • Conectarse a un servicio externo a través de una API

Necesitará lo siguiente antes de poder comenzar este tutorial:

  • A GitHub repository. The App you build will track contributions to this repository. You can create a new repository for this tutorial or use an existing repo that you have admin access to.

  • Un clúster de MongoDB Atlas. Si aún no tienes un clúster, regístrate en MongoDB Atlas y crea uno gratis.

Tenga en cuenta también que este tutorial no utiliza el flujo de trabajo de borrador de implementación. Un borrador de implementación es un conjunto de cambios en la aplicación que puede implementar o descartar como una sola unidad. A menos que haya desactivado los borradores de implementación, es posible que deba guardar los cambios en un borrador y luego implementarlos manualmente.

Primero, debes crear una aplicación en App Services.

Para crear la aplicación:

  1. Abra su proyecto Atlas en cloud.mongodb.com.

  2. In the top navigation, click App Services.

  3. Haga clic en Create a New App.

  4. Name the App github-tracker-tutorial.

  5. Seleccione su clúster para vincularlo a la nueva aplicación.

  6. Haga clic en Create App Service.

Conectaremos la aplicación a tu repositorio de GitHub mediante un webhook. Los webhooks informan a tu aplicación de cualquier evento, como una nueva confirmación o una solicitud de extracción, en tu repositorio. Cada evento ejecuta una función sin servidor que te permite responder a una acción.

Para este tutorial, usaremos la API REST de GitHub para enviar un mensaje de bienvenida a los colaboradores cada vez que abran su primera solicitud de extracción o problema en un repositorio.

Los webhooks funcionan enviando una solicitud sobre el evento a una URL controlada por tu aplicación. En tu aplicación, deberás exponer un punto final personalizado con una URL única para recibir y gestionar las solicitudes de webhooks.

Para crear el punto final:

  1. En el menú de navegación de la izquierda, haga clic en HTTPS Endpoints.

  2. Haga clic en Add An Endpoint.

  3. Nombre la ruta del punto final /greetNewContributors.

  4. En Operation Type, copia la URL de devolución de llamada del punto final. La necesitarás para configurar el webhook de GitHub más adelante.

  5. Deje el método HTTP establecido en POST.

  6. Para la autorización, seleccione Require a Secret.

  7. Introduzca un nuevo nombre de secreto y haga clic en Create para crearlo. A continuación, introduzca tutorial como valor del secreto. Esto requiere que todas las solicitudes entrantes incluyan el parámetro de consulta secret=tutorial en la URL de la solicitud.

  8. Cree una nueva función Atlas para el punto final y endpoints/greetNewContributors llámela.

  9. Por ahora, configure un controlador básico que solo responda a las llamadas entrantes sin realizar ninguna otra tarea. Copie el siguiente código en el cuerpo de la función:

    exports = async function greetNewContributors(request, response) {
    return response
    .setStatusCode(200)
    .setBody("Successfully received a GitHub webhook event")
    }
  10. Haga clic en Save e implemente el punto final.

Ahora que has creado el endpoint en tu aplicación, necesitas cambiar la configuración de autenticación de la función del endpoint para que se acepte el webhook de GitHub.

Para actualizar la configuración de autenticación de su función:

  1. En el menú de navegación de la izquierda, haga clic en Functions.

  2. Encuentra tu Function endpoint y selecciónalo.

  3. Haga clic en Settings.

  4. En Authentication, cambie el método de autenticación a System.

  5. Haga clic en Save para implementar la función.

Con tu Function para endpoint lista para usarse, necesitas configurar un webhook en tu repositorio de GitHub que envíe eventos al endpoint.

Para crear el webhook en su repositorio:

  1. Abra la configuración del repositorio y seleccione Webhooks en el menú de navegación izquierdo.

  2. Agregar un webhook nuevo y establecer el Payload URL en la URL del endpoint que acabas de crear, además de un parámetro query secret establecido en el valor secreto, como: ?secret=tutorial. La URL de la carga útil tendrá un aspecto similar al siguiente, con algunas diferencias que dependerán del modelo de implementación de la aplicación. Tenga en cuenta el ?secret=tutorial añadido al final de la URL:

    https://us-west-2.aws.data.mongodb-api.com/app/<App ID>/endpoint/greetNewContributors?secret=tutorial
  3. Establezca el tipo de contenido del webhook como application/json.

  4. Deje Secret vacío. El punto final HTTPS ignora cualquier valor introducido aquí, por lo que añadimos el secreto como parámetro de consulta en la URL de carga útil en los pasos anteriores.

  5. Elija seleccionar eventos individuales y configure el webhook para enviar solo eventos para Issues y Pull requests.

  6. Haga clic en Add webhook para guardar el nuevo webhook.

Para confirmar que el webhook llama correctamente a tu endpoint, revisa los registros de tu aplicación en App Services para ver si hay entradas de Endpoint tipo. Puedes acceder a ellas haciendo clic Logs en en el menú de navegación izquierdo.

También puedes consultar los registros de solicitudes del webhook en GitHub, en Recent Deliveries la sección de la página de configuración del webhook. Cada solicitud exitosa tiene una marca de verificación verde junto a ella.

A log entry in GitHub that shows the custom endpoint's response to a ping event. The response has a status code of 200 and the response body says "Successfully received a GitHub webhook event".

El webhook ya está configurado para enviar eventos desde GitHub a tu endpoint. Sin embargo, para responder a los eventos en el endpoint con la API de GitHub, necesitarás un token de acceso. Este tutorial utiliza tokens de acceso personales, pero también puedes configurar una aplicación de GitHub y usar ese token.

Para crear un token de acceso personal:

  1. Abra la configuración de usuario de GitHub (no la configuración de su repositorio) y seleccione Developer settings en el menú de navegación izquierdo.

  2. En el menú de navegación de la izquierda, seleccione Personal access tokens y luego haga clic en Generate new token.

  3. Configure el token con un nombre descriptivo y un tiempo de expiración razonable. Dado que este es un tutorial, considere expirar el token después de 7 días.

  4. Seleccione el alcance repo.

  5. Haga clic en Generate token.

  6. Copia el token en un lugar seguro donde puedas acceder de nuevo. GitHub nunca volverá a mostrarte el token después de este punto.

De vuelta en tu aplicación, agrega un nuevo valor para almacenar el token de acceso personal que acabas de generar. Podrás referenciarlo desde tu punto final sin tener que codificar el token en tus funciones.

Para crear el Valor:

  1. En el menú de navegación de la izquierda, haga clic en Values.

  2. Haga clic en Create New Value.

  3. Nombra el valor GitHubAccessToken.

  4. Deje el tipo establecido en Value.

  5. Pegue el token de acceso personal en la entrada del valor. El valor debe ser un JSON válido, así que asegúrese de incluirlo entre comillas.

  6. Haga clic en Save.

El punto final interactuará con la API REST de GitHub para dejar comentarios. Puedes escribir y enviar solicitudes HTTP directamente a la API usando el context.http cliente integrado o una biblioteca externa. Sin embargo, en este tutorial usamos Octokit, la biblioteca oficial de Node.js de GitHub, que encapsula la API. Una vez instalada, podrás importar la biblioteca desde cualquier función de tu aplicación.

Para agregar la biblioteca Octokit a su aplicación:

  1. En el menú de navegación de la izquierda, haga clic en Functions.

  2. Seleccione la pestaña Dependencies.

  3. Haga clic en Add Dependency.

  4. Introduzca el nombre del paquete: @octokit/request.

  5. Haga clic en Add.

  6. Espere a que App Services instale el paquete. La instalación debería completarse en unos segundos, pero podría tardar hasta un minuto.

Ahora que tiene un token de acceso e instaló Octokit, puede actualizar la función del punto final para que realice una acción al recibir eventos. En concreto, la función debe:

  • Analizar el evento webhook entrante

  • Registrar la contribución en MongoDB

  • Añade un comentario a través de la API de GitHub

  • Envíe una respuesta informativa a GitHub

Para actualizar la función:

  1. En el menú de navegación de la izquierda, haga clic en Functions.

  2. Haga clic en endpoints/greetNewContributors para abrir el editor de funciones del punto final.

  3. Reemplace la función básica con el siguiente código:

    funciones/puntos finales/greetNewContributors.js
    exports = async function greetNewContributors(request, response) {
    // Parse the webhook event from the incoming request.
    const event = JSON.parse(request.body.text());
    // Don't do anything unless this is a new issue or pull request
    if (event.action !== "opened") {
    return response.setStatusCode(200);
    }
    // Get data from the GitHub webhook event.
    // Based on the webhook configuration the event will be one of the following:
    // - issues: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issues
    // - pull_request: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#pull_request
    const sender = event.sender;
    const repo = event.repository;
    const contribution = event.issue || event.pull_request;
    const contribution_url = event.issue
    ? event.issue.url
    : event.pull_request.issue_url;
    const issue_number = contribution.number;
    // Record this contribution in the user's contributor document.
    // If this user hasn't contributed to the repo before, create a document for them.
    const atlas = context.services.get("mongodb-atlas");
    const contributors = atlas.db("community").collection("contributors");
    const contributor = await contributors.findOneAndUpdate(
    // Look up the user by their GitHub login
    { login: sender.login },
    // Add this issue or pull request to their list of contributions
    {
    $push: {
    contributions: {
    date: new Date(),
    type: event.issue ? "issue" : "pull_request",
    url: contribution_url,
    },
    },
    },
    // If they haven't contributed before, add them to the database
    { upsert: true, returnNewDocument: true }
    );
    // Send a welcome message to first time contributors on their issue or pull request
    const isFirstTimeContributor = contributor.contributions.length === 1;
    if (isFirstTimeContributor) {
    const octokit = require("@octokit/request");
    await octokit.request(
    "POST /repos/{owner}/{repo}/issues/{issue_number}/comments",
    {
    headers: {
    authorization: `token ${context.values.get("GitHubAccessToken")}`,
    },
    owner: repo.owner.login,
    repo: repo.name,
    issue_number: issue_number,
    body: `Hi there ${sender.login} 👋 Thanks for your first contribution!`,
    }
    );
    }
    // Configure the HTTP response sent back to GitHub
    return response
    .setStatusCode(200)
    .setHeader("Content-Type", "application/json")
    .setBody(
    isFirstTimeContributor
    ? `This is ${sender.login}'s first contribution!`
    : `${sender.login} has contributed before.`
    );
    };
  4. Haga clic en Save e implemente el punto final.

El punto final del mensaje de bienvenida ya debería estar completamente configurado. Para comprobar su correcto funcionamiento, abra una nueva incidencia o solicitud de incorporación de cambios en el repositorio. El punto final añadirá un nuevo comentario al hilo la primera vez que lo haga, pero no añadirá un mensaje de bienvenida en los intentos posteriores.

An example of the welcome comment in GitHub added by the endpoint.

GitHub registra las solicitudes de webhook del repositorio, por lo que también puedes consultar la entrada de registro en GitHub para confirmar que todo funciona correctamente. Cada registro de solicitud incluye un mensaje de respuesta del endpoint.

A log entry in GitHub that shows the custom endpoint's response for a first-time contributor

Tip

Si quieres reiniciar la prueba, elimina el documento con tu nombre de usuario de GitHub de community.contributions. Esto permite que la aplicación olvide que ya has contribuido y te dé la bienvenida en tu próxima contribución.

Tu aplicación está conectada a GitHub, almacena información sobre las contribuciones y da la bienvenida a nuevos colaboradores. Ahora la ampliaremos para que analice y genere informes automáticamente para tu repositorio.

Tu aplicación necesita saber qué repositorios generar informes cada semana. En este tutorial, codificaremos la lista en un valor.

Crea un nuevo valor llamado GitHubProjects que contenga una matriz de objetos. Cada objeto especifica el nombre owner y repo de un repositorio de GitHub. Asegúrate de incluir una entrada para tu repositorio.

valores/proyectos.json
[
{ "owner": "<GitHub Username>", "repo": "<Repository Name>" }
]

Un informe es un documento que resume las contribuciones a un repositorio durante un período de tiempo. Utilizaremos una Function para crear informes on-demand para un repositorio.

Crea una nueva función llamada generateCommunityReport y agrega el siguiente código:

funciones/generateCommunityReport.js
exports = async function generateCommunityReport({ owner, repo, startDate }) {
// Look up issues and pull requests that had activity
const octokit = require("@octokit/request");
const { data: issuesWithActivity } = await octokit.request(
"GET /repos/{owner}/{repo}/issues",
{
headers: {
authorization: `token ${context.values.get("GitHubAccessToken")}`,
},
owner: owner,
repo: repo,
since: startDate,
}
);
// Look up users that contributed to the repo
const atlas = context.services.get("mongodb-atlas");
const contributors = atlas.db("community").collection("contributors");
const allContributors = await contributors
.find({
contributions: {
$elemMatch: {
date: { $gt: new Date(startDate) },
owner: owner,
repo: repo,
},
},
})
.toArray();
// Keep track of users who made their first contribution
const newContributors = allContributors.filter((c) => {
new Date(c.contributions[0].date) > new Date(startDate);
});
// Return a report with the data
return {
owner,
repo,
startDate,
issuesWithActivity,
allContributors,
newContributors,
};
};

La función que acaba de crear genera un informe para un repositorio bajo demanda. Sin embargo, en este momento, ningún elemento la llama y los informes generados no se guardan en ningún lugar. Para usarla, crearemos un disparador Atlas programado que llame a la función una vez por semana y guarde los informes generados en su clúster vinculado.

Para crear el disparador:

  1. En el menú de navegación de la izquierda, haga clic en Triggers.

  2. Haga clic en Add a Trigger.

  3. Seleccione Scheduled para el tipo de disparador.

  4. Name the Trigger generateAndSaveCommunityReports

  5. Elija el tipo de programación Advanced

  6. Introduzca la siguiente programación cron para que se ejecute una vez a la semana los lunes a las 5 AM UTC:

    0 5 * * 1
  7. Crea una nueva función para el disparador y llámala triggers/generateAndSaveCommunityReports.

  8. Haga clic en Add Dependency e instale moment, que usamos para trabajar con fechas en la Función.

  9. Copie el siguiente código en el cuerpo de la función:

    funciones/desencadenadores/generateAndSaveCommunityReports.js
    exports = async function generateAndSaveCommunityReports() {
    const projects = context.values.get("GitHubProjects");
    const lastMonday = getLastMonday(); // e.g. "2022-02-21T05:00:00.000Z"
    // Generate a report for every tracked repo
    const reportsForLastWeek = await Promise.all(
    // Call the `generateCommunityReport` function for each project
    projects.map(async (project) => {
    return context.functions.execute("generateCommunityReport", {
    owner: project.owner,
    repo: project.repo,
    startDate: lastMonday,
    });
    })
    );
    // Save the generated reports in Atlas
    const atlas = context.services.get("mongodb-atlas");
    const reports = atlas.db("community").collection("reports");
    return await reports.insertMany(reportsForLastWeek);
    };
    // Get an ISO string for last Monday at 5AM UTC
    function getLastMonday() {
    const moment = require("moment");
    return moment(new Date().setUTCHours(5, 0, 0, 0))
    .utc()
    .day(1 - 7)
    .toISOString();
    }
  10. Haga clic en Save.

  11. Actualice la configuración de autenticación de su nueva función para que coincida con la función del nuevo punto final mencionada anteriormente en este tutorial.

Tu aplicación generará y guardará informes automáticamente cada semana. Sin embargo, estos informes no serán muy útiles si nadie los ve. Crearemos un disparador de base de datos que detecta nuevos informes y genera un mensaje con formato que puedes enviar a los usuarios finales.

Para configurar los mensajes:

  1. En el menú de navegación de la izquierda, haga clic en Triggers.

  2. Haga clic en Add a Trigger.

  3. Deje el tipo de disparador establecido en Database.

  4. Nombra el activador sendCommunityReport.

  5. Agregue el disparador a la colección community.reports y escuche Insert eventos.

  6. Habilite Full Document para incluir cada nuevo documento de informe en el evento de cambio pasado a la función de activación.

  7. Crea una nueva función para el disparador y llámala triggers/sendCommunityReport.

  8. Copie el siguiente código en el cuerpo de la función:

    funciones/desencadenadores/sendCommunityReport.js
    exports = async function sendCommunityReport(changeEvent) {
    // Pull out the report document from the database change event
    const report = changeEvent.fullDocument;
    // Format values from the report to include in the message
    const projectName = `${report.owner}/${report.repo}`;
    const moment = require("moment");
    const formattedDate = moment(report.startDate).utc().format("MMMM Do, YYYY");
    const numIssuesWithActivity = report.issuesWithActivity.length;
    const numContributors = report.allContributors.length;
    const numNewContributors = report.newContributors.length;
    // Create a message string that describes the data in the report
    const message = [
    `# Community contributions to ${projectName} since ${formattedDate}`,
    `Last week, there was activity on ${numIssuesWithActivity} issues and pull requests.`,
    `We had ${numContributors} people contribute, including ${numNewContributors} first time contributors.`,
    ].join("\n");
    // For this tutorial we'll just log the message, but you could use a
    // service to send it as an email or push notification instead.
    console.log(message);
    };
  9. Haga clic en Save e implemente el disparador.

Tu aplicación está configurada para generar, guardar y enviar informes automáticamente cada semana. Para asegurarte de que todo funcione correctamente, puedes ejecutar este flujo de informes manualmente.

Abra el editor de funciones de su disparador programado, triggers/generateAndSaveCommunityReports, y haga clic en el botón Run. Esto debería generar y guardar informes a pedido para cada repositorio que haya indicado en el valor GitHubProjects.

Para confirmar:

  1. Marque community.reports para ver los nuevos documentos del informe.

  2. Consulte los registros de activación de la base de datos de su aplicación para encontrar el mensaje formateado para cada informe

¡Felicitaciones! Has configurado correctamente un rastreador de contribuciones de GitHub sin servidor y has llegado al final de este tutorial.

Si quieres seguir desarrollando, puedes intentar añadir algunas funcionalidades nuevas al rastreador. Por ejemplo, podrías:

  • Actualice el punto final para manejar más tipos de eventos de webhook como issue_comment o pull_request_review.

  • Actualice los informes semanales para incluir más información de la API de GitHub.

  • Conéctese a un servicio externo como Twilio o SendGrid para enviar el informe por correo electrónico o SMS en lugar de simplemente registrarlo.

Los Servicios de aplicaciones incluyen muchos servicios que pueden potenciar tu aplicación. Consulta el resto de la documentación para obtener más información sobre estos servicios y cómo puedes usarlos.

Trabajamos constantemente para mejorar nuestra documentación y tutoriales. Si tienes alguna sugerencia o tuviste algún problema con este tutorial, haz clic en Give Feedback al final de esta página para calificarlo y enviarnos un comentario.

Para preguntas, debates o soporte técnico general, visite las comunidades de MongoDB en Reddit o Stack Overflow. Estas plataformas son excelentes lugares para conectar con otros usuarios de MongoDB, hacer preguntas y obtener respuestas.

Para mostrar sus proyectos MongoDB, compartir contenido, conocer nuestros programas comunitarios, recibir comentarios de sus pares y conectarse con otros desarrolladores, visite el Foro de la comunidad MongoDB.

Next

¿Qué son los servicios de aplicación Atlas?