Última actualización: Jueves, 06 de febrero de 2025

Jira BI Custom Reports - Gonzalo A. Arenas Flores

Aplicación web basada en BaP Framework para el desarrollo de una prueba de concepto que nos permita probar la API REST de Atlassian Jira y poder generar diversos reportes personalizados.

GonzaloArenasF - Jira BI Custom Reports - Gonzalo A. Arenas Flores

Investigación y desarrollo

En realidad esto fue relativamente sencillo. Para el momento en que escribo este artículo, desde la compañía para la que trabajo se fomentaba fuertemente el uso de la inteligencia artificial, por lo que me apoyé mucho en eso. Además, siempre había sentido curiosidad por el uso de la API de Jira para realizar análisis de datos con reportes diferentes a los que ofrecen en su set pre definido. En este caso, lo que busco es poder realizar inteligencia de negocio y poder analizar diferentes casuisticas.

Dentro de la búsqueda me encontré con diferentes herraminentas, como EazyBI donde pueden realizar reportes personalizados. Sin embargo, buscaba algo que pudiese usar con total libertad. Esto me motivó a explorar un poco más y verlo como una oportunidad de indagar en otras formas de obtener la información (Todo legal. No se asuten). Actualmente me creé una cuenta de Attlasian, que dura unos 30 días, y sobre esas posibilidades empecé a operar.

Preparando el agente de IA y el entorno de trabajo

Como dije anteriormente, me apoyé en una versión de Chat GPT de la compañía para la que trabajo y empecé definiendo el rol del agente para que solo actúe como me serviría mejor:

Prompt para definir el rol

From this moment you are an atlassian jira expert and also a business inteligence expert. You always find alternatives to recover information from jira database so you can export to other platforms in order to process the data and create custom reports.

Inmediatamente me ofreció diferentes alternativas para poder recuperar información desde la base de datos de Jira, listando las siguientes opciones como posibilidades:

La primera opción es la elegida, por lo que le pregunté qué debo hacer para consultar la API, dándome los pasos para realizar consultas rápidas

Preparar el entorno de trabajo

GonzaloArenasF - Jira BI Custom Reports - Gonzalo A. Arenas Flores - Jira API Tokens
  1. Credenciales de acceso: Esto fue lo primero que validé. Para poder llegar a consultar vía API es necesario contar con un token de seguridad que se genera mediante las configuración de tu cuenta en Jira: https://id.atlassian.com/manage-profile/security/api-tokens.
  2. Herramientas: Para las pruebas de la API usaré Insomnia importando el swagger desde la documentación oficial de la API de Jira. Finalmente, trabajaré los reportes desde la aplicación basada en BaP Framework que construiré.

Autenticarse

No había mucho que decir aqui. La cuenta trabaja sobre Jira versión Cloud, por lo que está descartada la autenticación vía usuario/password, así que validé si era posible realizar la conexión solo usando el email y el token de seguridad, por lo que usé el siguiente CURL desde Insomnia, y como lo sospechaba, me retornó todos los proyectos.
curl -u your_email@example.com:your_api_token -X GET -H "Content-Type: application/json" https://your-domain.atlassian.net/rest/api/3/project

Revisar API de Jira

Ahora viene un trabajo de evaluar posibilidades de acuerdo a lo que esta API pudiese ofrecerme. Tendría que realizar una especie de diagrama de entidades y relaciones con una pequeña ingeniería inversa para ver qué puedo cruzar con qué. Afortunadamente, la API de jira está muy vien documentada en https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/, por lo que debiese ser relativamente sencillo este paso.

Son decenas de endpoints que, si tienes los permisos, te permitirían crear tu propia version de Jira, lo cuál me hace imaginar un montón de posibilidades. Por ahora me centraré en crear algo sencillo que me permita escalarlo sin mayores problemas.

Preparar proyecto web

Como dije anteriormente, el propósito de esta investigación es el desarrollo de una webapp que permita la consulta de información desde las API de Jira, por lo que una vez validado que tenemos acceso a ella, y que podemos hacer consultas, el siguiente paso es iniciar el proyecto usando BaP Framework. Esto me permite tener un entorno rápido para trabajar y realizar pruebas de concepto.

  1. Creamos el repositorio en Github
  2. Lo clonamos en el computador
  3. Descargamos la última versión de BaP Framework y la incorporamos al nuevo proyecto con un simple copy/paste.
  4. Install de NPM
  5. Si bien BaP nos permite usar Google Firebase como backend, esta vez no lo necesitaremos... creo
  6. Modificamos las constantes
  7. Creamos el README.MD ... y ¡listo!

Empezamos a construir

Esta vez me saltaré el paso del diseño ya que quiero ver si puedo construir algo de valor, porque nadie destina tiempo y dinero en crear algo que nadie usará. Esa frase me la dijo un profesor del diplomado de Innovación y Emprendimiento, y se me quedó grabada. Tienen más info de eso en la portada de este sitio, en la sección de Educación y certificaciones.

La grilla

GonzaloArenasF - Jira BI Custom Reports - Gonzalo A. Arenas Flores - Grid

Así que me decantaré por una estructura muy secilla con un grid de 3x1 para todo lo que tenga que ver con la exposición de información, donde:

  • Habrá un header
  • pondré un main donde fijaré la grilla con 3 secciones
  • Y finalizará footer

Inicialmente no le daré soporte a mobile, por lo que omitiré ese tema hasta ver qué resulta. A propósito, la imagen es de la web https://cssgrid-generator.netlify.app. Hace súper fácil el definir la grilla, y para ser honesto, siempre me demora mucho hacerlo a mano... jajaja.

La idea es cosntruir una aplicación web de una sola página y que cargue su contenido de manera progresiva, y que al momento de entrar al landing page cargue de inmediato todos los reportes disponibles en la columna izquierda de la grilla en un listado simple. Como cada reporte se construirá con un Custom Component de Javascript, todos los recursos y lógica estarán unicamente en sus archivos quedando en gran parte desacoplados un reporte de otro, de esa forma los podré exportar o eliminar sin problemas. Además, el listado de reportes lo que hará es que al momento de hacer clic en uno de los accesos será cargar dicho Custom Component en la columna centrar de la grilla junto a todos sus recursos. Finalmente, la columna derecha quedará oculta como un aside de forma que podré cargar cualquier información detallada expandiéndolo cuando sea necesario.

Obtener los datos de acceso a la API de Jira

Como todos los reportes requerirán de las credenciales de Jira para consultar su API, se realizarán validaciones de la existencia de ellas en localstorage siempre que se ingrese al landing page. En el caso de no encontrarlas, se reenviará al usuario al formulario de ingreso de datos de autenticación.

Esto solo es un sencillo formulario que reacciona a lo que encuentre en el localstorage del navegador. Le solicito al usuario que ingrese 3 datos:

  • URL base del servicio de jira.
  • El nombre de usuario o email.
  • El token de seguridad.

Además se le informa al usaurio que no se almacenará esta información en otro lugar más que el localstorage de su navegador actual, y que si quiere ejecutar este servicio en otro navegador o dispositivo, se le volverán a pedir estos datos. Además, se ejecutarán valdiaciones para que después de 7 días se eliminen los datos desde el navegador. Esto sin perjuicio de que el token pueda ser invalidado por Jira antes de ese periodo.

En el caso que el usuario quiera cambiar su información antes de el periodo de expiración, solo debe entrar nuevamente a esta página y la aplicación le mostrará los datos actuales listos para ser modificados.

GonzaloArenasF - Jira BI Custom Reports - Gonzalo A. Arenas Flores - Get jira credentials page

El primer reporte y los primeros problemas

Esto es algo que debí preveer. Para cuando desarrollé esto estaba un poco oxidado y había olvidado cosas importantes. El primer reporte sería una prueba sencilla. Utilizaría el endpoint /rest/api/3/issuetype para obtener todos los tipos de issue que mi usuario tiene habilitados para manejar en Jira y simplemente mostraría un listado de cards con la información básica que se me indicara.

const credentials = btoa(`${params.authorization.username} : ${params.authorization.token}`);

fetch(item, {
 method: "GET",
 headers: {
  Authorization: `Basic ${credentials}`,
  Accept: "application/json",
 },
})
 .then((response) => response.json())
 .then((data) => callbackOnSuccess(data))
 .catch((error) => {
  callBackOnFail ? callBackOnFail(error) : console.error(error);
 });

El problema se prensentó cuando realicé el primer fetch al de llamada al servicio apareción el nunca bien ponderado CORS bloqueándome toda entrada a la API de Jira.

Esto era fácilmente anticipable desde la primera investigación pero lo había olvidado completamente. En fin... las soluciones que conocía eran 3:

  • Server side proxy
  • Backend for frontend
  • Reverse proxy

Las 2 últimas opciones demandan mucho trabajo así que lo intentaré con la primera.

Esto no lo expondremos en producción por ahora, así que crearé una subproyecto dentro ese mismo que tenga el proxy listo para ejecutar. Para esto me guiaré con el paso a paso que me dio la IA que estoy consultando, ya que, y como dije, esto oxidado, y para eso fueron creadas estas cosas.

Se definió un directorio llamado jira-proxy donde se inició NPM, y posteriormente se instalaron las dependencias de:

  • Express
  • Request
  • y Cors ... porque esto no me vuelve a pasar
mkdir jira-proxy
cd jira-proxy
npm init -y
npm install express request cors

Y finalmente levantamos el servidor proxy con el código a continuación, el cual recibe mediante headers: Jira URL, el email, y el token de seguridad; y mediante query params, el endpoint a consiltar de la API de Jira, quedando de la siguiente forma:

const express = require("express");
const request = require("request");
const cors = require("cors");
const app = express();

app.use(cors()); // Enable CORS for all routes
app.use(express.json());


// Proxy endpoint
app.get("/api/jira", (req, res) => {
 const { endpoint } = req.query;
 const jiraDomain = req.headers["x-jira-domain"];
 const email = req.headers["x-email"];
 const apiToken = req.headers["x-api-token"];

 if (!jiraDomain) return res.status(400).send("jiraDomain is missing");
 if (!email) return res.status(400).send("email is missing");
 if (!apiToken) return res.status(400).send("apiToken is missing");
 if (!endpoint) return res.status(400).send("endpoint is missing");

 const url = `${jiraDomain}${endpoint}`;

 const options = {
  url: url,
  headers: {
   Authorization: "Basic " + Buffer.from(`${email}:${apiToken}`).toString("base64"),
   Accept: "application/json",
  },
 };

 request(options, (error, response, body) => {
  if (error) {
   res.status(500).send(error);
  } else {
   res.status(response.statusCode).send(body);
  }
 });
});

// Start the server
const PORT = 3000;
app.listen(PORT, () => {
 console.log(`Proxy server listening on port ${PORT}`);
});

Y por fin el primer reporte

Ahora que el proxy funcionó perfectamente, siempre en modo local, puedo con un único servicio llamar a toda la API de Jira de acuerdo a los permisos que tiene mi usuario. Así que la prueba rápida fue obtener todos tipos de issue que mi usuario puede trabajar y los puse como uns card simples y listados en una grilla flex. Nada del otro mundo, lo que importa es la información.

GonzaloArenasF - Jira BI Custom Reports - Gonzalo A. Arenas Flores - First report

Para terminar... debo decir que esto me ayuda bastante a los análisis que quiero realizar y cruzar con otro tipo de información. Además, me sirvió para recordar cosas que tenía muy olvidadas de mi prime como desarrollador. Por ahora solo a sacarle probecho a esto, así que hasta aquí este artículo. Si tienes dudas al respecto, no dudes en contactarme y lo conversamos. Hay muchas cosas que son suceptibles a mejorar pero como es una prueba de concepto uno se puede tomar ciertas libertades.