Tiempo estimado de lectura:

Existen varios sistemas de este tipo: Fabric, Ant en Java, Rake en Ruby… y un largo etcétera. En todos ellos, como en Grunt, se definen una serie de acciones que procesan unos datos de entrada y producen un resultado, ya sea en un directorio local o en una ubicación remota.

Conceptos básicos de Grunt

Lo primero que debes saber es que Grunt necesita que tu sistema tenga instalado NodeJS y NPM, el gestor de módulos de NodeJS. Para ello puedes usar Homebrew:

$ brew install node

Para utilizar Grunt necesitas configurar un fichero llamado package.json, que es el formato de paquetes de Node. Básicamente describe tu proyecto como un paquete de Node y las dependencias que necesita para funcionar.

Por ejemplo:

{
  "name": "doofinder-for-woocommerce",
  "version": "0.1.1",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-clean": "^0.5.0",
    "grunt-contrib-compress": "^0.9.1",
    "grunt-contrib-copy": "^0.5.0",
    "grunt-version": "^0.3.0"
  }
}

En la documentación de NPM encontrarás más información sobre el formato de este archivo, pero básicamente representa el nombre de tu paquete, una etiqueta de versión, y un conjunto de dependencias con las versiones correspondientes. Cómo no, para usar Grunt, deberemos declararlo como dependencia.

Ejecutando:

$ npm install

dentro del directorio que contiene el fichero package.json, se creará un directorio node_modules donde se instalarán todas las dependencias del proyecto.

Una vez que tenemos instalado Grunt, necesitaremos un fichero Gruntfile.js que defina las tareas que podemos ejecutar. Podéis ver más información acerca de este fichero en la documentación de Grunt.

Entornos personalizados

El principal problema de estos sistemas de tareas es ser capaces de abstraer el entorno del desarrollador para que todos puedan ejecutar las tareas en sus equipos a su gusto.

En algunos casos basta con utilizar rutas relativas al proyecto. En otros, en cambio, nos gustaría poder adaptar las rutas donde se realizan las operaciones a las preferencias del desarrollador.

Grunt nos permite cargar un fichero JSON y guardar los valores dentro de una variable. Luego podemos utilizar sustitución de esas variables en el código como si se tratase de una plantilla para generar valores dinámicos.

module.exports = function(grunt) {
  grunt.initConfig({
    local: grunt.file.readJSON('localconfig.json'),
    copy: {
      svn: {
        files: [
          {src: 'readme.txt', dest: '< %= local.svndir %>/readme.txt'},
          {src: '*.php', dest: '< %= local.svndir %>/'},
          {src: 'includes/**', dest: '< %= local.svndir %>/'}
        ]
      },
      release: {
        files: [
          {src: 'license.txt',
           dest: '< %= local.tmpdir %>/doofinder-for-woocommerce/license.txt'},
          {src: '*.php',
           dest: '< %= local.tmpdir %>/doofinder-for-woocommerce/'},
          {src: 'includes/**',
           dest: '< %= local.tmpdir %>/doofinder-for-woocommerce/'}
        ]
      }
    },
    compress: {
      release: {
        options: {
          archive: '< %= local.releasedir %>/doofinder-for-woocommerce.zip'
        },
        files: [
          { expand: true, cwd: '< %= local.tmpdir %>/', src: '**/*' }
        ]
      }
    },
    clean: {
      options: {
        force: true
      },
      release: ['< %= local.tmpdir %>']
    },
    version: {
      options: {},
      plugin_header: {
        options: {prefix: '\\s+\\*\\s+Version:\\s+'},
        src: ['doofinder-for-woocommerce.php']
      },
      plugin_class: {
        options: {prefix: "\\s+public\\s\\$version\\s+=\\s+'"},
        src: ['doofinder-for-woocommerce.php']
      },
      php: {
        options: {prefix: '\\s+\\*\\s+@version\\s+'},
        src: [
          'doofinder-for-woocommerce.php',
          'includes/*.php',
          'includes/responses/*.php'
        ]
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-compress');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-version');
  grunt.registerTask('default', 'Usage', function(){
      grunt.log.ok("Usage: $ grunt release");
  });
  grunt.registerTask('release', [
    'version', 'copy:svn', 'copy:release',
    'compress:release', 'clean:release'
  ]);
};

He pegado tal cual un script Grunt, pero lo importante aquí es ver cómo cargamos un fichero localconfig.json y guardamos sus valores en el objeto de configuración de Grunt:

grunt.initConfig({
    local: grunt.file.readJSON('localconfig.json'),

para luego utilizarlo como sustitución en el propio script:

compress: {
    release: {
        options: {
            archive: '< %= local.releasedir %>/doofinder-for-woocommerce.zip'
        },
        files: [
            { expand: true, cwd: '< %= local.tmpdir %>/', src: '**/*' }
        ]
    }
},

En nuestros proyectos podemos incluir un fichero localconfig-sample.json que los desarrolladores personalizarían a su gusto. Podría ser algo así:

{
    "svndir": "/Users/carlos/dev/d/plugins/woocommerce-doofinder-svn",
    "tmpdir": "/tmp/doofinder-for-woocommerce",
    "releasedir": "/Users/carlos/Downloads"
}

Esta estructura me permite configurar:

  • La ruta donde tengo descargado el repositorio SVN de WordPress que contiene el plugin de Doofinder para WooCommerce.
  • El directorio temporal donde se copiarán (y de donde se borrarán) los ficheros que irán en el .zip del release que colgaré en el repositorio de Github.
  • El directorio donde pondré el fichero comprimido de salida para mayor comodidad.

Si un segundo programador quiere hacer lo mismo solamente tiene que configurar sus rutas y listo.

Espero que esto os haya servido de inspiración para algo útil.

Blog Logo

Carlos Escribano

Desarrollador Web desde hace 10 años. Me gusta resolver problemas de forma ingeniosa. Saber más.

Artículos de desarrollo web en español

nettoys.es

Volver al Inicio