Menu Docs
Página inicial do Docs
/ /
Serviços Atlas App

Tutorial: Crie um rastreador de contribuições do GitHub sem servidor usando gatilhos, funções e valores

Tempo estimado para conclusão: 30 minutos

Neste tutorial, você usará o Atlas App Services para criar uma aplicação sem servidor que monitora repositórios do Github e rastreia contribuições.

O App Services App que você construir terá várias funcionalidades:

  • Acompanhe os usuários que contribuíram para o seu projeto em uma collection do MongoDB Atlas.

  • Deixe um comentário que dão as boas-vindas a novos colaboradores quando eles abrem uma pull query ou arquivam um problema.

  • Gere e envie um relatório semanal que resume as contribuições para seu repositório.

Após concluir este tutorial, você saberá como realizar as seguintes tarefas:

  • Escreva e execute funções sem servidor que lidam com a lógica do seu aplicativo.

  • Automatize tarefas agendadas e responda às alterações de dados com o Realm trigger.

  • Armazene e acesse dados estáticos, como chaves de API, em Valores.

  • Conecte-se a um serviço externo por meio de uma API

Você precisa do seguinte antes de iniciar este tutorial:

  • Um repositório do Github. O aplicativo que você construir rastreará as contribuições para esse repositório. Você pode criar um novo repositório para este tutorial ou usar um repositório existente ao qual você tem acesso de administrador.

  • Um cluster MongoDB Atlas . Se você ainda não tiver um cluster, inscreva-se no MongoDB Atlas e crie um gratuitamente.

Observe também que este tutorial não utiliza o fluxo de trabalho esquema de implantação . Um esquema de implantação é uma collection de alterações de aplicativos que você pode implantar ou descartar como uma única unidade. A menos que você tenha desativado o esquema de implantação, talvez seja necessário salvar as alterações em um esquema e, em seguida, implementá-los manualmente.

Primeiro, você precisa criar um aplicativo no App Services.

Para criar o aplicativo:

  1. Abra seu projeto Atlas em cloud.mongodb.com.

  2. Na navegação superior, clique em App Services.

  3. Clique em Create a New App.

  4. Dê um nome ao aplicativo github-tracker-tutorial.

  5. Selecione seu cluster para vinculá-lo à nova aplicação.

  6. Clique em Create App Service.

Conectaremos o aplicativo ao seu repositório do Github usando um webhook de repositório do Github. Os webhooks avisam seu aplicativo sempre que algum evento, como uma nova solicitação de commit ou pull, acontece em seu repositório. Cada evento executa uma função sem servidor onde você pode fazer algo em resposta.

Para este tutorial, usaremos a API REST do Github para enviar uma mensagem de boas-vindas aos colaboradores sempre que eles abrirem sua primeira solicitação pull ou problema em um repositório.

Os webhooks funcionam enviando uma solicitação sobre o evento para uma URL que sua aplicação controla. Em sua aplicação, você precisará expor um ponto de conexão personalizado com uma URL exclusiva para receber e lidar com as solicitações de webhook.

Para criar o ponto de conexão:

  1. No menu de navegação esquerdo, clique em HTTPS Endpoints.

  2. Clique em Add An Endpoint.

  3. Nomeie a rota do ponto de conexão /greetNewContributors.

  4. Em Operation Type, copie a URL da chamada de resposta do endpoint. Você precisará dele para configurar o webhook do GitHub mais tarde.

  5. Deixe o método HTTP definido como POST.

  6. Para autorização, escolha Require a Secret.

  7. Insira um novo nome de segredo e clique em Create para criar um novo segredo. Em seguida, insira tutorial como o valor secreto. Isso exige que todas as solicitações recebidas incluam o parâmetro de query secret=tutorial na URL da solicitação.

  8. Crie uma nova Função de Realm para o ponto final e nomeie-a endpoints/greetNewContributors.

  9. Por enquanto, configure um manipulador básico que responda apenas às chamadas recebidas sem fazer outros trabalhos. Copie o seguinte código no corpo da Função:

    exports = async function greetNewContributors(request, response) {
    return response
    .setStatusCode(200)
    .setBody("Successfully received a GitHub webhook event")
    }
  10. Clique Save e implemente o endpoint.

Agora que você criou o endpoint em seu aplicativo, é necessário alterar as configurações de autenticação da função do endpoint para que o webhook do Github seja aceito.

Para atualizar as configurações de autenticação da sua função:

  1. No menu de navegação esquerdo, clique em Functions.

  2. Encontre sua função de endpoint e selecione-a.

  3. Clique em Settings.

  4. Em Authentication, altere o método de autenticação para System.

  5. Clique em Save para implantar a função.

Com sua função de endpoint pronta para Go, você precisa configurar um webhook em seu repositório GitHub que envie evento para o endpoint.

Para criar o webhook em seu repositório:

  1. Abra as configurações do repositório e selecione Webhooks no menu de navegação esquerdo.

  2. Adicione um novo webhook e defina o Payload URL para a URL do ponto de conexão que você acabou de criar, além de um parâmetro de query secret definido para o valor secreto, como: ?secret=tutorial. Seu URL de carga útil será semelhante ao seguinte, com algumas diferenças dependendo do modelo de sistema do seu aplicativo. Observe o ?secret=tutorial anexado ao final da URL:

    https://us-west-2.aws.data.mongodb-api.com/app/<App ID>/endpoint/greetNewContributors?secret=tutorial
  3. Defina o tipo de conteúdo do webhook como application/json.

  4. Deixe o Secret vazio. Qualquer valor inserido aqui é ignorado pelo ponto de conexão HTTPS, e é por isso que anexamos o segredo como um parâmetro de query na URL de carga nas etapas anteriores.

  5. Escolha selecionar eventos individuais e configurar o webhook para enviar apenas eventos para Issues e Pull requests.

  6. Clique em Add webhook para salvar o novo webhook.

Para confirmar se o webhook chama seu endpoint com êxito, verifique se há entradas com o tipo Endpoint nos aplicação do aplicativo no App Services. Você pode acessá-la clicando em Logs no menu de navegação esquerdo.

Você também pode verificar os registros de solicitações do webhook no Github em Recent Deliveries na página de configurações do webhook. Cada solicitação bem-sucedida tem uma marca de seleção verde ao lado.

Uma entrada de registro no Github que mostra a resposta do endpoint personalizado a um evento de ping. A resposta tem um código de status 200 e o corpo da resposta diz "Recebeu com sucesso um evento de webhook do Github".

O webhook agora está configurado para enviar evento do Github para o seu endpoint. No entanto, para responder aos eventos no endpoint com a API do GitHub, você precisará de um token de acesso. Este tutorial usa tokens de acesso pessoal, mas você também pode configurar um aplicativo GitHub e usar esse token.

Para criar um token de acesso pessoal:

  1. Abra suas configurações de usuário do Github (não as configurações do repositório) e selecione Developer settings no menu de navegação esquerdo.

  2. No menu de navegação esquerdo, selecione Personal access tokens e clique em Generate new token.

  3. Configure o token com um nome descritivo e um tempo de expiração razoável. Como este é um tutorial, considere expirar o token após 7 dias.

  4. Selecione o escopo repo .

  5. Clique em Generate token.

  6. Copie o token em algum lugar seguro onde você possa acessá-lo novamente. O Github nunca mais mostrará o token a você após esse ponto.

De volta à sua aplicação, adicione um novo valor para manter o token de acesso pessoal que você acabou de gerar. Você poderá referenciar o valor a partir do seu endpoint sem codificar o token em suas funções.

Para criar o valor:

  1. No menu de navegação esquerdo, clique em Values.

  2. Clique em Create New Value.

  3. Nomeie o valor GitHubAccessToken.

  4. Deixe o tipo definido como Value.

  5. Cole o token de acesso pessoal na entrada do Valor. O valor deve ser JSON válido, portanto, certifique-se de ter aspas.

  6. Clique em Save.

O endpoint interagirá com a API REST do Github para deixar comentários. Você pode escrever e enviar solicitações HTTP diretamente para a API usando o cliente context.http integrado ou uma biblioteca externa. No entanto, neste tutorial usamos a biblioteca oficial do Node.js do Github chamada Octokit que envolve a API. Depois de instalada, você poderá importar a biblioteca de qualquer função em seu aplicativo.

Para adicionar a biblioteca OctoKit ao seu aplicativo:

  1. No menu de navegação esquerdo, clique em Functions.

  2. Selecione a guia Dependencies.

  3. Clique em Add Dependency.

  4. Insira o nome do pacote: @octokit/request.

  5. Clique em Add.

  6. Aguarde até que o App Services instale o pacote. A instalação deve ser concluída em alguns segundos, mas pode levar até um minuto.

Agora que você tem um token de acesso e instalou o OctoKit, pode atualizar a função do endpoint para fazer algo quando ele receber eventos. Especificamente, a função deve:

  • Analisar o evento de webhook recebido

  • Registrar a contribuição no MongoDB

  • Adicionar um comentário por meio da API do GitHub

  • Envie uma resposta informativa de volta ao GitHub

Para atualizar a função:

  1. No menu de navegação esquerdo, clique em Functions.

  2. Clique em endpoints/greetNewContributors para abrir o editor de função do endpoint.

  3. Substitua a função básica pelo seguinte código:

    functions/endpoints/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. Clique Save e implemente o endpoint.

O endpoint da mensagem de boas-vindas agora deve estar totalmente configurado. Para testar se funciona corretamente, abra um novo issue ou pull query no repositório. O endpoint adicionará um novo comentário ao thread na primeira vez que você fizer isso, mas não adicionará uma mensagem de boas-vindas nas tentativas subsequentes.

Um exemplo do comentário de boas-vindas no Github adicionado pelo endpoint.

Github registra as solicitações de webhook do repositório, então você também pode verificar a entrada de registro no Github para confirmar se tudo está funcionando corretamente. Cada registro de solicitação inclui uma mensagem de resposta do endpoint.

Uma entrada de registro no Github que mostra a resposta do endpoint personalizado para um colaborador iniciante

Dica

Se você quiser redefinir o teste, exclua o documento com seu nome de usuário do Github de community.contributions. Isso permite que o aplicativo "esqueça" que você contribui antes e o receberá em sua próxima contribuição.

Seu aplicativo está conectado ao Github, armazena informações sobre contribuições e recebe novos colaboradores. Agora vamos estenda-lo para analisar e gerar relatórios automaticamente para seu repositório.

Sua aplicação precisa saber quais repositórios deve gerar relatórios para cada semana. Para este tutorial, codificaremos a lista em um valor.

Crie um novo valor chamado GitHubProjects que contenha uma array de objetos. Cada objeto especifica o nome owner e repo de um repositório Github. Certifique-se de incluir uma entrada para o seu repositório.

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

Um relatório é um documento que resume as contribuições para um repositório por algum período de tempo. Usaremos uma função para criar relatórios sob demanda para um repositório.

Crie uma nova função denominada generateCommunityReport e adicione o seguinte código:

functions/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,
};
};

A função que você acabou de criar cria um relatório para um repositório sob demanda. No entanto, neste ponto, nada chama a função e os relatórios gerados não são salvos em nenhum lugar. Para realmente usá-lo, criaremos um Realm trigger agendado que chama a função uma vez por semana e salva os relatórios gerados no cluster vinculado.

Para criar o trigger:

  1. No menu de navegação esquerdo, clique em Triggers.

  2. Clique em Add a Trigger.

  3. Escolha Scheduled para o tipo de trigger.

  4. Nomear o trigger generateAndSaveCommunityReports

  5. Escolha o tipo de agendamento Advanced

  6. Insira a seguinte programação cron para executar uma vez por semana na segunda-feira às 5h UTC:

    0 5 * * 1
  7. Crie uma nova função para o trigger e nomeie-a triggers/generateAndSaveCommunityReports.

  8. Clique em Add Dependency e instale moment, que usamos para trabalhar com datas na função.

  9. Copie o seguinte código no corpo da função:

    functions/triggers/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. Clique em Save.

  11. Atualize as configurações de autenticação da sua nova função para corresponder à função do novo endpoint como mostrado anteriormente neste tutorial.

Sua aplicação agora gerará e salvará relatórios automaticamente toda semana. No entanto, os relatórios não serão muito úteis se alguém os ver. Criaremos um Database Tools que escuta novos relatórios e cria uma mensagem formatada que você pode enviar aos usuários finais.

Para configurar as mensagens:

  1. No menu de navegação esquerdo, clique em Triggers.

  2. Clique em Add a Trigger.

  3. Deixe o tipo de trigger definido como Database.

  4. Nomeie o gatilho como sendCommunityReport.

  5. Adicione o trigger à collection community.reports e escute evento Insert .

  6. Habilite Full Document para incluir cada novo documento de relatório nos eventos de alteração enviados para a função de gatilho.

  7. Crie uma nova função para o trigger e nomeie-a triggers/sendCommunityReport.

  8. Copie o seguinte código no corpo da função:

    functions/triggers/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. Clique Save e implante o trigger.

Sua aplicação está configurada para gerar, salvar e enviar relatórios automaticamente toda semana. Para garantir que tudo funcione, você pode executar esse fluxo de relatórios manualmente.

Abra o editor de função do seu trigger agendado, triggers/generateAndSaveCommunityReports, e clique no botão Run . Isso deve gerar e salvar relatórios on-demand para cada repositório que você listou no Valor GitHubProjects .

Para confirmar:

  1. Verifique community.reports para os novos documentos do relatório.

  2. Verifique os registros de Database Tools do reconhecimento de data center do seu aplicativo para encontrar a mensagem formatada para cada relatório

Parabéns! Você configurou com sucesso um rastreador de contribuição do Github sem servidor e chegou ao final deste tutorial.

Se você quiser continuar desenvolvendo, pode tentar adicionar alguns novos recursos ao rastreador. Por exemplo, você pode:

  • Atualize o endpoint para lidar com mais tipos de evento de webhook, como emitir_comment ou pull_request_review.

  • Atualize os relatórios semanais para incluir mais informações da API do Github.

  • Conecte-se a um serviço externo como Twilio ou SendGrid para enviar o relatório por e-mail ou SMS, em vez de apenas registrá-lo.

O App Services inclui muitos serviços que podem melhorar seu aplicativo. Confira o restante da documentação para saber mais sobre esses serviços e como você pode usá-los.

Estamos sempre trabalhando para melhorar nossos Docs e tutoriais. Se você tiver uma sugestão ou tiver problemas com este tutorial, clique em Give Feedback na parte inferior desta página para avaliar o tutorial e enviar-nos um comentário.

Para perguntas, discussões ou suporte técnico geral, visite as comunidades MongoDB no Reddit ou no Stack Overflow. Essas plataformas são ótimos lugares para se conectar com outros usuários MongoDB , fazer perguntas e obter respostas.

Para mostrar seus projetos do MongoDB, compartilhar conteúdo, saber mais sobre nossos programas de comunidade, obter feedback de pares e conectar-se com outros desenvolvedores, visite a MongoDB Community Federation.

Próximo

O que são os Serviços de Aplicativo Atlas?