Grunt is a very powerful task runner for automating and improving your development workflow. Even in 2017 when Webpack 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).
Setting Up Grunt
You don’t need grunt-cli
to run Grunt tasks! Use npm 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 by Stephen Harris which enables automated deployments for WordPress plugins to the official plugin repository. There is even wp-readme-to-markdown for converting plugin readme.txt
into markdown formatted readme for GitHub. The Gruntfile.js
of the Event Organiser plugin 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 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:
install-pre-commit-hook.sh
creates a symbolic link to thepre-commit
script in the project.git/hooks
directory. This can be replaced with husky which runs anything you have defined for theprecommit
script in thepackage.json
file instead.generate-markdown-readme
can be replaced with the wp-readme-to-markdown Grunt task mentioned previously which offers more flexibility over how the files are named and placed.svn-push
can be replaced with the grunt-wp-deploy task.
However, the core features are contained in the pre-commit
script which does all of this:
- Sets up environment variables 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.
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 and fixmyjs.