2018/12/31

Hello Jenkins: Como root

En el post Hello Jenkins, exploré cómo podría automatizar el deploy de un site estático simple con ayuda de Jenkins.

Este site estático está alojado en mi directorio web personal ~/public_html. Para que Jenkins pudiera hacer pull allí, fue necesario que tuviera derechos sobre los archivos de ese directorio, así que opté por agregarlo a mi grupo de usuario.

Ahora exploro cómo sería si quisiera que Jenkins pudiera hacer pull en el directorio web /var/www.

En mi Jenkins, proyecto hello-jenkins, Configuration, Source Code Management:

  • En Aditional Behaviours, pruebo agregar:
    • Chek out to a sub-directory
      • Local sub-directory for repo:
        /var/www/html/demos/hello-jenkins/
Una prueba muestra un error de acceso al directorio. Probé agregar jenkins al grupo sudo y tambien visudo, pero no pude solucionarlo.

Opto por agregar el siguiente script en Build:
  • echo "hello-jenkins build"
  • cd /var/www/html/demos/hello-jenkins
  • sudo git pull
Hago la prueba y funciona como se espera. Se hace pull al hello-jenkins en mi directorio personal public_html/ y tambien en el directorio web /var/www/.


2018/12/30

Hello Jenkins


En días recientes estuve viendo un poco de Continuous Integration / Continuous Deployment (CI/CD), con Jenkins.

La idea que he captado es que Jenkins corre en el servidor donde normalmente ejecutamos a mano los pasos para deployar un proyecto. Luego configuramos las cosas para que Jenkins las haga por nosotros.

Por ejemplo, puedo tener en mi hosting un site estático hello-jenkins, cuyo repositorio está en GitHub. Luego que hago push en el repo desde mi máquina local debo entrar a la consola de mi hosting y hacer pull. Quizás alguna cosa más, como bower o npm, dependiendo de la complejidad del proyecto.

Empezaré con un simple site estático llamado hello-jenkins.

Ahora, haré un cambio y un deploy manual.
  • En mi local, agrego un title, commit y push
  • En mi hosting, hago pull
    • Lo pesado de esta tarea es cuando no estoy logueado a la consola. Es necesario hacer ssh, ubicar la carpeta y hacer pull.
    • Si Jenkins vive en este servidor, podría hacerlo por mi ante una señal. Por ejemplo, cuando se hace un push en GitHub.
  • https://rulokoba.me/~rulo/demos/hello-jenkins/
En el hosting, tengo instalado Jenkins siguiendo la guía de:
En mi Jenkins, creo el job hello-jenkins:
  • Elijo create new jobs
  • Enter an item name: hello-jenkins
  • Elijo Freestyle project
  • OK
  • En la sección de consiguración:
    • Source Code Management
      • Git
        • Repository URL: https://github.com/akobashikawa/hello-jenkins.git
        • Credentials: none
        • Additional Behaviours
          • Check out to a sub-directory
            • Local sub-directory for repo:
              /home/rulo/public_html/demos/hello-jenkins/
            • Para que jenkins pueda escribir en este directorio se le puede agregar al grupo del usuario y reiniciar jenkins:
              • $ sudo usermod -a -G rulo jenkins
              • $ sudo systemctl stop jenkins
              • $ sudo systemctl start jenkins
    • Build Triggers
      • GitHub hook trigger for GITScm polling
    • Build (opcional)
      • Execute shell
        • Command
          • echo "hello-jenkins build"
En el repo de GitHub, Settings:
  • Webhooks
    • Add webhook
      • Payload URL: http://myjenkins_url/github-webhook/
        • Es importante el trailing / al final
      • Content type: application/json
      • Which events would you like to trigger this webhook?
        • [x] Let me select individual events.
          • [x] Pushes
            • [x] Pull requests
      • [x] Active
      • Add webhook
      • Es importante que GitHub pueda encontrar a Jenkins ya configurado
Para probar, manualmente:
  • En mi Jenkins, en el projecto hello-jenkins, wlijo Build Now
  • En Build History aparecerá un nuevo item numerado, y le hago click.
  • Elijo Console Output para ver la salida
Para probar el build automático:
  • En mi local, hago un cambio, commit y push al repo
  • En Build History aparecerá un nuevo item numerado, y le hago click.
  • Elijo Console Output para ver la salida

2018/09/18

Solucionando conexión de strapi a mLab



Strapi es un framework para node que facilita la creación de un cms.
  • Como base de datos puede usar mongo, mysql, postgres.
  • Como frontend puede usar vue, react, angular.
  • El panel de administración luce bastante similar al de wordpress.
  • Tiene un plugin para servir los datos con graphql.
  • El idioma se puede configurar a español.
mLab es un servicio que provee acceso a bases de datos mongo.
  • Tiene una capa de uso gratuita (via AWS de Amazon)

Instalación simple

  • Para usarlo con mongo, debe estar iniciado el servicio localmente
  • $ node --version
    • Se requiere al menos la versión 9
  • $ npm install -g strapi@alpha
    • Por alguna razón, recomiendan que trabajemos con la versión más fresca
  • $ strapi --version
    • Actualmente 3.0.0-alpha.14.1.1
  • $ strapi new myapp
    • Creará la estructura de directorios.
    • Hay que elegir como base de datos a mongo e indicar los parámetros
      • Esta data se guarda en myapp/config/environments/development/database.json
      • La base de datos aún no se crea en este punto
  • $ cd myapp
  • $ strapi start

Problema con mongo externo

Por alguna razón, cuando se indica que se conecte a una base de datos mongo externa para development, strapi devuelve un error.

Encuentro que en la configuración para production hay una propiedad extra uri.

Cuando se usa esta propiedad uri en la configuración para development, ya es posible conectarse a una base de datos mongo externa, como mlab, por ejemplo.

Solución

  • $ strapi new myapp
    • Crear la aplicación indicando una base de datos mongo local
    • Esto aún no creará ninguna base de datos
  • Editar myapp/config/environments/development/database.json y agregar la propiedad uri:
  • $ cd myapp
  • $ strapi start
La configuración sería similar a:
{
  "defaultConnection": "default",
  "connections": {
    "default": {
      "connector": "strapi-hook-mongoose",
      "settings": {
        "client": "mongo",
        "uri": "mongodb://username:password@hostname.mlab.com:12345/dbname",
        "host": "hostname.mlab.com",
        "srv": false,
        "port": "12345",
        "database": "dbname",
        "username": "username",
        "password": "password"
      },
      "options": {
        "authenticationDatabase": "",
        "ssl": false
      }
    }
  }
}

2017/12/13

Test de internet con ping en NodeJS


En estos días he tenido intermitencias en el servicio de internet.

Mi forma de comprobarlo es entrar en una consola y hacer ping a un host, como google.com, y ver si está ok o no.

$ ping google.com -t


El -t permite que el ping se haga indefinidamente, hasta que se presione CTR + C.

Sin embargo, quería una forma de mostrar los cambios de estado, a qué hora ocurrían y cuánto duraban.

Programé esta solución usando nodejs:

GitHub Gist: Internet test with ping in NodeJS

const ping = require('ping');

let host = '8.8.8.8';

if (process.argv[2]) {
  host = process.argv[2];
} else {
  console.log("Syntax: \nnode ping-test-ifchanges-host host");
}

console.log("Testing host: " + host);

let isAlivePrev = false;
let nowPrev = new Date();

function doPing() {
  ping.sys.probe(host, isAlive => {
    if (isAlive !== isAlivePrev) {
      let now = new Date();
      let diff = (now.getTime() - nowPrev.getTime())/1000;
      let timestamp = now.toISOString() + ' after: ' + diff + ' s';
      console.log("\n" 
        + host + ': ' 
        + (isAlive ? ' OK' : ' KO') 
        + ' ' + timestamp);
      isAlivePrev = isAlive;
      nowPrev = now;
    } else {
      process.stdout.write('.');
    }
  });
}

setInterval(doPing, 1000);

Para correrlo en consola:

$ node ping-test-ifchanges-host google.com

Idea

setInterval() establece un llamado, cada 1000 ms, a doPing(), que hace un ping al host que se haya indicado y revisa si hay un cambio de estado.

Si hay un cambio de estado, anota el tiempo y muestra las diferencias respecto al tiempo anterior.

Si no hay cambio de estado, imprime simplemente un punto.