Artículos

Gulp y hooks de commits (gilp)

Este post forma parte de la serie sobre herramientas para garantizar la calidad del código.

Al crear un flujo de validación para los archivos preparados para un commit, no hay muchas opciones y generalmente se termina con un enorme script de Bash lleno de funciones para cada linter, regla o estándar que se quiera automatizar.

Este post presenta gilp, un plugin de gulp que se encarga de instalar los hooks pre-commit, pre-push y commit-msg y ejecutar tareas de gulp.

Flujo de validación

Así como gulp ofrece gulp.src, gilp ofrece gilp.srcFromStaged, una función similar que excluye los archivos no preparados para el commit y devuelve un flujo de objetos File de vinyl. Gilp también ofrece gilp.srcFromCommit, que recibe el hash de una revisión.

Este ejemplo incluye gulp-eslint para validar JavaScript.

gilp.hook('pre-commit', ['check-eslint'], () =>
  gilp.srcFromStaged(['**/*'.js])
  .pipe(eslint())
  .pipe(eslint.format())
  .pipe(eslint.failAfterError())

gilp.hook se comporta de manera similar a gulp.task, pero se registra en ./git/hooks y envuelve la tarea original de gulp.task.

Veamos ahora un ejemplo mínimo funcional.

Ejemplo

Normalmente empezamos separando nuestras comprobaciones en distintas funciones.

const filter = require('gulp-filter');
const combiner = require('stream-combiner2').obj;
const print = require('gulp-print');
const flake8 = require('gulp-flake8');
const gulpIsort = require('gulp-isort');
const checkGrep = require('gulp-check-grep');

function py() {
  const src = filter([
    '**/*.py',
  ], {restore: true});
  return combiner(
    src,
    print(),
    flake8('.flake8'),
    flake8.failOnError(),
    gulpIsort(),
    gulpIsort.failOnError(),
    checkGrep(/print\+$/gm, {pass: (line, n, f) => line.endswith('# noqa')}),
    checkGrep.failOnError(),
    src.restore
  );
}

Aquí usamos stream-combiner2 para que nuestra función py se comporte como un único flujo, y gulp-filter para seleccionar solo los archivos de Python.

const filter = require('gulp-filter');
const combiner = require('stream-combiner2').obj;
const print = require('gulp-print');
const lintFilepath = require('gulp-lint-filepath');

function html() {
  const src = filter(['**/*.html'], {restore: true});
  return combiner(
    src,
    print(),
    lintFilepath({'file-name': [/(^|\/)[a-z0-9_]+\.html$/]}),
    lintFilepath.reporter(),
    src.restore
  );
}

Esto hace más o menos lo mismo, pero utiliza un validador de nombres de archivo de gulp para archivos HTML.

const gilp = require('gilp');

gilp.hook('pre-commit', () =>
  gilp.srcFromStaged(['**/*'])
  .pipe(py())
  .pipe(html())
);

Aquí queda definido el hook de gilp: ejecutar gulp gilp-install colocará estas tareas en el archivo de hooks pre-commit.

“Gulp y hooks de commits (gilp)” de Rodrigo Lopez está bajo la licencia CC BY SA. Los ejemplos de código fuente están bajo la licencia MIT.

Foto de Tommy Lisbin en Unsplash.

Clasificado en Investigación y aprendizaje.

Lecturas relacionadas