Lego IT guy por bnilsen

Cómo construir un bot de GitHub con PhantomJS, React y Framework sin servidor

Este tutorial trata sobre la construcción de un bot simple sin servidor que devuelve un gráfico con los principales contribuyentes del repositorio de GitHub durante un período seleccionado. Es relevante para aquellos que tienen alguna experiencia con React, JavaScript, TypeScript, Node.js, Amazon Web Services (AWS) y el framework Serverless.

Puedes consultar el código en Github.

Servicios y herramientas que usaremos

Antes de saltar a la codificación, hagamos un resumen rápido de los servicios y herramientas de AWS que usaremos.

Para recuperar los principales contribuyentes del repositorio, utilizaremos la API de estadísticas de GitHub, el increíble Nivo para mostrar datos, Storybook para verificar cómo se ve y se siente nuestro gráfico, PhantomJS para convertir HTML en una imagen y el marco Serverless para interactuar con AWS.

Empecemos

Usaré TypeScript. Si prefiere ES6, deberá configurar Babel.

Primero, debe crear tsconfig.json en la raíz de su repositorio. Las opciones para prestar atención incluyen:

"module": "commonjs",
"target": "es5",
"lib": ["es6", "esnext.asynciterable"],
"moduleResolution": "nodo",
"jsx": "reaccionar"

Luego, crearemos una API simple para consultar estadísticas desde GitHub. Puede seguir la estructura de archivos desde el repositorio de GitHub o usar la suya propia. Por ejemplo:

Para acceder a la API de GitHub, deberá crear un token de acceso personal.

Este módulo simplemente envía la solicitud con el token proporcionado y recupera los datos.

Mostrar los gráficos

Para mostrar los datos, usaremos Nivo y Storybook. Un componente simple puede verse así:

Primero, configure Storybooks ejecutando el siguiente comando en la carpeta raíz:

npm i -g @ storybook / cli
getstorybook

Copie la carpeta .storybook en el repositorio raíz y reemplace todos los archivos existentes. Contiene la configuración de Webpack y Storybook. Cree una carpeta de historias y ponga una historia de muestra para su componente:

Ejecute npm run storybook y abra localhost en el navegador. Debería ver el siguiente resultado:

Intenta jugar con las opciones y los datos de prueba. Storybook cambiará el aspecto de inmediato.

Convertir HTML en PNG

Por lo general, los sistemas de chat como Facebook Messenger y Slack no permiten a los usuarios insertar tarjetas HTML en el cuadro de diálogo, por lo que el siguiente paso será crear un asistente que represente HTML en una imagen PNG.

Usando un script simple con la biblioteca jsdom, podemos imitar el comportamiento del navegador y serializar HTML, de esta manera:

createDomForChart devuelve una nueva instancia de jsdom, y la función de gráfico simplemente llama a dom.serialize () cuando se realiza la representación del componente.

Con PhantomJS, podemos convertir el marcado en una imagen usando este simple script:

Pasamos screenshot.js a la ruta ejecutable de phantomjs, junto con una cadena HTML, ancho y alto, y recuperamos el búfer con la imagen renderizada.

Puede notar que he estado usando dos binarios PhantomJS (para OS X y Linux). Necesitaremos la versión de Linux aún más en un entorno de AWS. Puede descargarlos de PhantomJS.org o usar archivos del repositorio.

Atar todo

Ahora, creemos lambda para manejar las solicitudes. Recomiendo poner la lógica de renderizado PNG en un servicio separado. Debido a que el binario PhantomJS tiene un tamaño aproximado de 50 mb, ralentiza la implementación si cambia algo en la API. Además, puede reutilizar esta lambda para otros fines.

Comenzaremos creando webpack.config.ts (para agrupar el código fuente) y serverless.base.js (para definir la configuración básica sin servidor) en la carpeta raíz.

Si desea obtener más información sobre casos de uso de configuraciones de JavaScript sin servidor, puede leerlo en mi artículo anterior.

Tendrá que cambiar la implementación y los nombres de los depósitos de imágenes, de esta manera:

implementaciónBucket: {
    nombre: 'com.github-stats .... deploys'
},
ambiente: {
    CUBO: 'com.github-stats .... images',
    GITHUB_TOKEN: '$ {env: GITHUB_TOKEN}',
    SLACK_TOKEN: '$ {env: SLACK_TOKEN},
    ETAPA: '$ {self: provider.stage}'
},

Esto se debe a que el nombre del depósito debe ser globalmente único.

Convertir HTML a servicio PNG

En primer lugar, crearemos un controlador que devolverá una URL de la imagen generada. El controlador debe validar y procesar el cuerpo de la solicitud:

... y si todo está bien, debería generar la imagen y ponerla en un cubo S3.

Creemos webpack.config.ts para agrupar archivos de origen. Utilizaremos copy-webpack-plugin y webpack-permissions-plugin para incluir los binarios PhantomJS en un paquete y otorgar permisos para su ejecución. Esto requerirá que ejecutemos el comando de implementación con sudo, ya que Webpack no tiene permisos para modificar los derechos del sistema de archivos de manera predeterminada.

El último paso será usar el archivo serverless.js para vincular nuestro controlador con un evento API Gateway.

Ahora, debemos realizar los mismos pasos para el controlador de estadísticas, pero no tenemos que hacer ningún cambio en webpack.config.ts.

La única diferencia es un permiso adicional para invocar lambda:

iamRoleStatements: [... baseConfig.provider.iamRoleStatements,
{
    Efecto: 'Permitir',
    Acción: ['lambda: InvokeFunction'],
    Recurso: ['*']
}]

Configurar el bot de Slack

El último paso será crear un servicio que maneje los eventos de mensajes para el bot. Para simplificarlo, solo trataremos los eventos de mención. Vamos a configurar el controlador de eventos básico.

Tenemos que manejar un evento de verificación de Slack y responder con 200 parámetros de estado y desafío:

devolución de llamada (nulo, {
   cuerpo: JSON.stringify ({
     desafío: (slackEvent como VerificationEvent) .challenge
   }),
   statusCode: 200
});

Para manejar adecuadamente un evento de Slack, el punto final debe responder dentro de 3000 milisegundos (3 segundos), por lo que tendremos que responder de inmediato y enviar un mensaje de seguimiento de forma asincrónica utilizando la API postMessage.

En el código anterior, analizamos el texto del mensaje para extraer un nombre de repositorio y llamamos a lambda de estadísticas de imagen para recuperar una URL de imagen y enviar un mensaje a Slack. Puede encontrar el código completo del controlador aquí.

El código para las configuraciones de serverless.js y Webpack sería similar al servicio de estadísticas, por lo que si tiene problemas para configurarlo, eche un vistazo al código fuente completo.

Crear una aplicación de Slack

Ahora creemos una nueva aplicación Slack. Vaya a la API de Slack, cree una nueva cuenta (si aún no lo ha hecho), cree una nueva aplicación y agregue el alcance del bot en la sección de ámbitos.

Vaya a la sección "OAuth y permisos" en la barra lateral.

Agregue el alcance del usuario bot.

Luego, podrá instalar la aplicación en su organización y obtener acceso a los tokens.

Desplegando los servicios

Deberá instalar una versión de marco sin servidor superior a 1.26 porque las versiones anteriores no admiten archivos de configuración de JavaScript. Y recomiendo instalar slx para simplificar la implementación de múltiples servicios.

npm install -g sin servidor
npm install -g sin servicio

Copie los tokens de bot GitHub y Slack, y configúrelos en las variables de entorno GITHUB_TOKEN y SLACK_TOKEN en consecuencia. Ejecute el siguiente comando en la terminal:

sudo GITHUB_TOKEN =  SLACK_TOKEN =  slx despliega todo

Como se mencionó anteriormente, necesitamos sudo para establecer permisos de ejecución para los binarios PhantomJS.

¡Se paciente! La implementación puede llevar un tiempo. Al final, debería ver una salida similar:

Implementación completada con éxito
[app / html-to-png] [completado]:
Servicio de información
servicio: html-to-png
etapa: dev
región: us-east-1
pila: html-to-png-dev
claves de la API:
   Ninguna
puntos finales:
   Ninguna
funciones:
   renderToPng: html-to-png-dev-renderToPng
Sin servidor: Eliminando versiones antiguas de servicio ...
[aplicación / holgura] [completado]:
Servicio de información
servicio: git-stats-slack
etapa: dev
región: us-east-1
pila: git-stats-slack-dev
claves de la API:
   Ninguna
puntos finales:
   POST - https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/stats/slack/event-handler
funciones:
   eventHandler: git-stats-slack-dev-eventHandler
Sin servidor: Eliminando versiones antiguas de servicio ...
[aplicación / estadísticas] [completado]:
Servicio de información
servicio: git-stats
etapa: dev
región: us-east-1
pila: git-stats-dev
claves de la API:
   Ninguna
puntos finales:
   GET - https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/stats/contributors/{owner}/{repo}
funciones:
   getContributorStatsImage: git-stats-dev-getContributorStatsImage
Sin servidor: Eliminando versiones antiguas de servicio ...

El último paso será suscribir nuestro punto final a los eventos de mención de bot.

Seleccione la sección "Suscripción al evento" en la navegación de Slack API.

Luego pegue la URL del controlador de eventos que puede encontrar en la salida del comando de implementación.

¡Es hora de jugar un poco! Aquí hay algunos ejemplos de imágenes renderizadas:

sin servidor / sin servidor

facebook / reaccionar

plouc / nivo

¡Eso es!

Espero que hayas encontrado útil este artículo. Me encantaría ver en los comentarios otros tipos de estadísticas que le gustaría ver en el servicio.

¡Aplauda si le ha gustado el artículo! Y si desea chatear o conectarse, puede encontrarme en Twitter, GitHub y Linkedin.