¿Cómo empezar a usar Runnerty?
Tags: workflow, node, javascript, webdev
Published: 2021-02-11 19:32:21

Runnerty es una tecnología "low code" que permite integrar y automatizar aplicaciones online & offline, infraestructura de sistemas y servicios con terceros de manera simple, rápida y segura, creando flujos de trabajo y ofreciendo una nueva forma de desarrollar.

Si quieres saber un poco más acerca de por qué deberías ~~probarlo~~ usarlo, aquí te dejo este [post](https://dev.to/runnerty/por-que-usar-runnerty-3ce1) 👀. 

En este artículo vamos a ver algunos conceptos básicos de Runnerty, como crear nuestro primer proyecto y cómo conectarnos con "[_Runnerty Platform_](https://app.runnerty.io)". 

1. Algunos conceptos básicos
2. Crear nuestro primer proyecto Runnerty
3. Estructura del proyecto
4. Conectar con Runnerty Platform 🚀
5. Lanzar nuestro primer proceso
6. Extra ball: Añadir un segundo proceso y visualizarlo en la plataforma. 

## 1. Conceptos básicos 📕

### Cadenas o workflows
Son una agrupación de procesos que tienen sentido en un determinado contexto. Esto puede ser tan amplio como que puedes crear una cadena para comprobar que tu web está online, crear una cadena para recoger los pedidos de tu e-commerce y comunicarlos al proveedor que corresponda o crear cadenas de ETL para tu Data Warehouse. Runnerty nos brinda muchas funcionalidades que harán que definir estos **workflows** sea súper ágil y totalmente escalable, definir dependencias entre complejos, pasar valores de unos a otros o incluso evaluarlos para decidir qué “camino seguir” son solo algunas de sus posibilidades.

### 🔨 Ejecutores
Cada uno de los procesos de nuestra cadena, ejecutará una acción específica a través de estos módulos. Podemos usar ejecutores muy genéricos, como el de Shell, que te permite ejecutar cualquier comando por consola u otros muy específicos que nos permiten realizar acciones muy concretas, como por ejemplo comunicarnos con una empresa de reparto como MRW o Fedex.

### 📢 Notificadores
Como su propio nombre indica, nos van a mantener informados en todo momento, cuando empieza o acaba una cadena o un proceso concreto, si se está reintentando o si ha fallado. Podemos mandar un correo, un sms o mensaje por Telegram o conectarlo directamente con nuestro sistema de incidencias. 

### 🏁 Triggers
Estos módulos se encargan de lanzar nuestros workflows. Puede ser algo planificado, puede ser cuando se reciba un archivo en un ftp ...

**Nota** 🔎: Ejecutores, notificadores y triggers son módulos, puedes desarrollar los tuyos muy fácilmente para que puedas llevar el potencial de Runnerty a donde quieras. 


## 2. No te lo cuento, te lo enseño 👩‍💻👨‍💻

Lo único que necesitamos antes de empezar es tener instalada la versión LTS de NodeJS (V 14+). Si no la tienes, puedes descargártela [aquí](https://nodejs.org/es/download/).

### Runnerty
Lo primero, es instalar Runnerty como paquete global

```bash
npm install -g runnerty
```

Una vez instalado, podemos crear nuestro primer proyecto Runnerty

```bash
runnerty new my-awesome-project
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f7nwooqclp2q6m38qm4k.png)

🎉 ¡Ya tenemos nuestro primer proyecto Runnerty!


## 3. Estructura de nuestro proyecto 🔎

Es un proyecto muy sencillo, vamos a centrarnos en los 2 archivos básicos de Runnerty:
- config.json
- plan.json

### Config 

En el **config.json** vamos a tener 3 secciones donde iremos añadiendo las configuraciones de nuestros 3 tipos de módulos (triggers, notificadores y ejecutores). Los que ves en el ejemplo son solo un identificador y un nombre para usarlo en nuestros workflows, en caso de que el módulo necesitara algún dato más, aquí sería donde se lo indicaríamos, como por ejemplo una cuenta de correo, un usuario y contraseña, etc.

```json
{
  "triggers": [
    {
      "id": "schedule_default",
      "type": "@runnerty-trigger-schedule"
    }
  ],
  "executors": [
    {
      "id": "shell_default",
      "type": "@runnerty-executor-shell"
    }
  ],
  "notifiers": [
    {
      "id": "console_default",
      "type": "@runnerty-notifier-console"
    }
  ]
}

```

### Plan 
En el plan es donde definimos nuestros workflows 😎
Podemos ver varias secciones: 

```json
{
  "chains": [
    {
      "id": "CHAIN_ONE",
      "name": "Chain one sample",
      "triggers": [
        ...
      ],
      "notifications": {
        ...
      },
      "defaults_processes": {
        ...
      },
      "processes": [
        ...
      ]
    }
  ]
}

```

#### Cadenas (chains)
Dentro de cada cadena, además de un nombre y una identificación, tendremos 4 secciones

1 - **Triggers**, lo que dispara nuestro workflow, en este caso hemos usado el plugin planificador y hemos configurado  que se ejecute el proceso cada minuto.
```json
...
"triggers": [
  {
    "id": "schedule_default",
    "schedule_interval": "*/1 * * * *"
  }
],
...
```
**Nota** 🔎: Este módulo usa nomenclatura cron estándar.

2 - **Notificadores**, Las notificaciones propias de nuestra workflow, en este caso vemos que nos va a avisar cuando empiece la cadena, cuando termine y si falla.

```json
...
"notifications": {
  "on_start": [
    {
      "id": "console_default",
      "message": "@GETDATE('YYYY-MM-DD HH:mm:ss') START OF THE CHAIN: @GV(CHAIN_ID)"
    }
  ],
  "on_end": [
    {
      "id": "console_default",
      "message": "@GETDATE('YYYY-MM-DD HH:mm:ss') END OF THE CHAIN: @GV(CHAIN_ID)"
    }
  ],
  "on_fail": [
    {
      "id": "console_default",
      "message": "@GETDATE('YYYY-MM-DD HH:mm:ss') FAIL OF THE CHAIN: @GV(CHAIN_ID)",
      "mode": "error"
    }
  ]
},
...
```
**Nota** 🔎: Ya podemos ver algunas funciones propias de Runnerty, como `GETDATE()` que nos va a devolver la fecha con la máscara que definamos o la de `GV (get value)` que en este caso nos va a devolver el identificador de la cadena. Hay muchos más, aquí te dejo enlace a la [documentación](https://docs.runnerty.io/values).

3 - **Defaults** (opcional). Muchas veces es muy útil definir unos valores por defecto para todos los procesos, para eso tenemos esta sección. Todos los procesos por defecto tendrán estas notificaciones configuradas, aunque siempre podemos sobrescribirlas dentro del propio proceso.
```json 
"defaults_processes": {
  "notifications": {
    "on_start": [
      {
        "id": "console_default",
        "message": "@GETDATE('YYYY-MM-DD HH:mm:ss') START: PROCESS @GV(PROCESS_ID)"
      }
    ],
    "on_fail": [
      {
        "id": "console_default",
        "message": "@GETDATE('YYYY-MM-DD HH:mm:ss') ERROR: PROCESS @GV(PROCESS_ID): @GV(PROCESS_EXEC_ERR_OUTPUT)",
        "mode": "error"
      }
    ],
    "on_end": [
      {
        "id": "console_default",
        "message": "@GETDATE('YYYY-MM-DD HH:mm:ss') END: PROCESS @GV(PROCESS_ID)"
      }
    ]
  }
},
```
4 - Procesos

La propiedades más comunes que podemos ver dentro de un proceso (además de su nombre y su identificador), son las siguientes propiedades:
- exec 
- output

```json
...
"processes": [
  {
    "id": "PROCESS_ONE",
    "name": "Process One",
    "exec": {
      ...
    },
    "output": [
      ...
    ]
  },
  ...
]
...
```

4.1 - La propiedad **exec** donde vamos a indicar qué ejecutor de nuestro config.json queremos usar y donde vamos a indicarle los valores necesarios  para que se ejecute. En este caso, como vamos a usar el ejecutor de Shell, solo necesitamos indicarle el comando que queremos que ejecute.

```json 
...
{
  "id": "PROCESS_ONE",
  "name": "Process One",
  "exec": {
    "id": "shell_default",
    "command": "echo Runnerty: hello world!"
  },
  "output": [
    ...
  ]
},
...
```

4.2 - La propiedad **output**, donde tratamos la salida del proceso. En este ejemplo vamos a escribir en un fichero de log el resultado de la ejecución. 

```json
{
  "id": "PROCESS_ONE",
  "name": "Process One",
  "exec": {
    ...
  },
  "output": [
    {
      "file_name": "./@GETVALUE(PROCESS_ID).log",
      "write": [
        "EXECUTION @GV(PROCESS_ID) - AT @GETDATE('YYYY-MM-DD HH:mm:ss')\n @GV(PROCESS_EXEC_ERR_OUTPUT) @GV(PROCESS_EXEC_MSG_OUTPUT)"
      ],
      "concat": true,
      "maxsize": "10mb"
    }
  ]
},
```
**Nota** 🔎: Es interesante saber que puedes definir el tamaño máximo de tu archivo de log y evitar así problemas de espacio.

4.3 - Como comentamos antes, también podemos configurarle notificaciones concretas para este proceso, por ahora vamos a dejar esta propiedad vacía porque tenemos las notificaciones por defecto configuradas.

## 4. Conectar con [Runnerty Platform](https://app.runnerty.io) 🚀

Vamos a conectar nuestro proyecto con Runnerty Platform para que sea más sencilla la visualización y podamos sacarle el máximo rendimiento a Runnerty. Este paso es opcional, pero te lo recomiendo, vas a disfrutar Runnerty mucho más 😊🔥.

1. [Nos logeamos en la plataforma](https://app.runnerty.io)
2. Creamos el proyecto, seleccionando la opción `Nuevo proyecto`
3. Simplemente añadimos el `API Key` generado a nuestro archivo config.json
```json 
{
  "general": {
    "runnerty.io": {
      "apikey": "NUESTRO_TOKEN"
    }
  },
  "triggers": [...],
  "executors": [...],
  "notifiers": [...]
}

```

So simple 😊! 

## 5. ¡Echar a andar nuestra cadena!
Ahora solo nos falta echar a andar nuestra cadena y ver qué sucede. Tan sencillo como ejecutar el siguiente comando:

```bash
runnerty
```

Si todo está correcto, ¿por qué no iba a estarlo?, veremos el siguiente mensaje en nuestra consola:

```bash
> runnerty

info: RUNNERTY v3.0.0 RUNNING - TIME...: Thu Jan 14 2021 10:29:23 GMT+0100 (hora estándar de Europa central)
info: Successful access to runnerty.io (websockets)
```

En este proyecto base, tenemos configurado que cada minuto se ejecute nuestro workflow, que en este caso solo muestra un mensaje por consola, y podremos ver como se han ido sustituyendo los valores. 

```
info: 2021-01-14 10:30:00 START OF THE CHAIN: CHAIN_ONE
info: 2021-01-14 10:30:00 START: PROCESS PROCESS_ONE
info: 2021-01-14 10:30:00 END: PROCESS PROCESS_ONE
```

Pero, vamos a verlo en la plataforma, se acabaron los logs interminables

![Vista ejecución de cadenas en Runnerty Platform](https://dev-to-uploads.s3.amazonaws.com/i/xirlm5m21cv3z9yszwak.png)

Iremos viendo cada una de las ejecuciones de nuestro **workflow**. Tenemos muchas opciones interesantes que ya explicaremos en otra ocasión, como **relanzar nuestro workflow** desde la plataforma en cualquier momento o ver el **detalle de la ejecución**.

## 6. Extra ball: Añadir un segundo proceso y visualizarlo en la plataforma. 

Creamos un segundo proceso (copiamos el primero y le cambiamos el `id` y en `name` y le añadimos la propiedad `depends_process` para indicarle que depende del proceso anterior. Así de fácil... 
```json 
...
"processes": [
  {
    "id": "PROCESS_ONE",
    "name": "Process One",
    "exec": {...},
    "output": [...]
  },
  {
    "id": "PROCESS_TWO",
    "name": "Process 2",
    "depends_process": ["PROCESS_ONE"],
    "exec": {
      "id": "shell_default",
      "command": "echo Runnerty: Process 2 depends on process 1!"
    },
    "output": [...]
  }
]
...
```

🎉 ¡Hemos creado nuestro primer workflow con dependencia entre procesos!

Ahora, si le echas un vistazo a la visualización de la cadena en la plataforma, verás esa dependencia 
![Vista diseño de una cadena de Runnerty](https://dev-to-uploads.s3.amazonaws.com/i/s82soiptu0me7qf0d37x.png)

Obviamente, no estamos exprimiendo el potencial de Runnerty en este ejemplo tan básico, pero podemos hacer flujos de trabajo tan complejos como seas capaz de diseñar.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/52vh2qz1tpvoe8xdsiw2.png)

Empieza a delegar en Runnerty procesos de tu ecosistema y hazlo escalable y seguro 🔥.

Te animo a que le eches un ojo y si te parece interesante puedes apoyarnos en [Github](https://github.com/runnerty/runnerty) ⭐️ o mandarnos un mensaje por [Twitter](https://twitter.com/runnerty_io).