---
title: Notes on Grunt
date: 2017-12-09T09:41:17+00:00
modified: 2017-12-09T09:47:01+00:00
image:: https://kaspars.net/wp-content/uploads/2017/12/grunt-cover.png
permalink: https://kaspars.net/blog/grunt-notes
post_type: post
author:
  name: Kaspars
  avatar: https://reverse.kaspars.net/gravatar/avatar/92bfcd3a8c3a21a033a6484d32c25a40b113ec6891f674336081513d5c98ef76?s=96&d=mm&r=g
category:
  - Development
---

# Notes on Grunt

[Grunt](https://gruntjs.com/) is a very powerful task runner for automating and improving your development workflow. Even in 2017 when [Webpack](https://webpack.js.org/) seems to be the cool kid on the block for concatenating and bundling static assets, there are plenty of tasks that are better handled by Grunt (or [Gulp](https://gulpjs.com/)).

## Setting Up Grunt

You don’t need `grunt-cli` to run Grunt tasks! Use [npm scripts](https://docs.npmjs.com/misc/scripts) to define all project related tasks as `npm run task-name` instead. This way you can swap out Grunt for anything else in the future without changing the name of the related task. For example, here is an excerpt of `package.json` that uses both Grunt and Webpack for separate tasks:

```
{
  "scripts": {
    "css": "grunt build:css",
    "js": "webpack --config webpack.config.js",
    "grunt": "grunt"
  }
}
```

Notice, there is also a generic `grunt` script for running individual grunt tasks via `npm run grunt task-name`.

## Grunt is Awesome

So far I’ve been using Grunt mainly for transpiling, bundling and minifying JS and CSS files but recently (four years too late) I discovered [grunt-wp-deploy](https://github.com/stephenharris/grunt-wp-deploy) by [Stephen Harris](http://stephenharris.info/) which enables automated deployments for WordPress plugins to the [official plugin repository](https://wordpress.org/plugins/). There is even [wp-readme-to-markdown](https://github.com/stephenharris/wp-readme-to-markdown) for converting [plugin `readme.txt`](https://developer.wordpress.org/plugins/wordpress-org/how-your-readme-txt-works/) into markdown formatted readme for GitHub. The [`Gruntfile.js`](https://github.com/stephenharris/Event-Organiser/blob/a23529d9c546041ebfb4ee091c5c4613640662ef/Gruntfile.js) of the [Event Organiser plugin](https://github.com/stephenharris/Event-Organiser) is a great example of what is possible.

## Grunt for wp-dev-lib

So I began to wondered if we could convert most of the [wp-dev-lib](https://github.com/xwp/wp-dev-lib) magic into Grunt tasks that are written in Javascript instead of Bash. The greatest feature of the `wp-dev-lib` is that it can report errors only for the parts of code that have changed in the particular commit or pull request. This is especially valuable when working with legacy projects that don’t adhere to any coding standards.

The following scripts are the easiest to convert:

- `<a href="https://github.com/xwp/wp-dev-lib/blob/ec27dd9f71d592a6177be98f77728badfd333fcb/install-pre-commit-hook.sh">install-pre-commit-hook.sh</a>` creates a symbolic link to the [`pre-commit`](https://github.com/xwp/wp-dev-lib/blob/0ae31b9d76cb33118cce175cbbef5724d5d99cb8/pre-commit) script in the project `.git/hooks` directory. This can be replaced with [husky](https://github.com/typicode/husky) which runs anything you have defined for the `precommit` script in the `package.json` file instead.
- `<a href="https://github.com/xwp/wp-dev-lib/blob/e718fdbf69cf71b7a5c3525ec2bbcd828dee6f73/generate-markdown-readme">generate-markdown-readme</a>` can be replaced with the [wp-readme-to-markdown](https://github.com/stephenharris/wp-readme-to-markdown) Grunt task mentioned previously which offers more flexibility over how the files are named and placed.
- `<a href="https://github.com/xwp/wp-dev-lib/blob/a044f5d279c7969a1deba48d660ef63fb5d02358/svn-push">svn-push</a>` can be replaced with the [grunt-wp-deploy](https://github.com/stephenharris/grunt-wp-deploy) task.

However, the core features are contained in the [`pre-commit`](https://github.com/xwp/wp-dev-lib/blob/0ae31b9d76cb33118cce175cbbef5724d5d99cb8/pre-commit) script which does all of this:

- Sets up [environment variables](https://github.com/xwp/wp-dev-lib/blob/dc2bbbc776ebe6c78dee9eea1163d04be03710af/check-diff.sh#L30-L354) that determine which tasks to run.
- Determines the Git diff range for which to run the checks.
- Checks for PHPCS, PHPUnit, Codeception, Vagrant, Docker, JSCS, JSHint and ESLint config files to determine which tasks to run and where.
- Creates a list of files with changes for each file type such as PHP, JS, CSS and XML.
- Installs the binaries for running the actual checks.
- Ensures that no executable files are being committed.
- Runs all the linters and tests and[ reports errors only in the current changeset](https://github.com/xwp/wp-dev-lib/blob/89fd88e629c256845f7344d263dd91555136475b/diff-tools/filter-report-for-patch-ranges.php).

The challenge here is to duplicate the patch-level linter reporting. So far I haven’t figured the best way to do that but it’s been an interesting thought experiment.

Finally, we wouldn’t actually need the patch level filtering if the whole codebase matched the coding standards required by each linter. Maybe for legacy projects it’s easier to start by running automated code fixers such as [phpcbf](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Fixing-Errors-Automatically) and [fixmyjs](https://github.com/jshint/fixmyjs).