Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dotherightthing/edc8a492365cba31b55ee9fe63de0c8d to your computer and use it in GitHub Desktop.
Save dotherightthing/edc8a492365cba31b55ee9fe63de0c8d to your computer and use it in GitHub Desktop.
[Migrating Gulp build tasks to NPM scripts] #npm #gulp #testing #shell

Migrating Gulp build tasks to NPM scripts

My Gulp build script does various things including linting code and packaging releases.

I'd like to extend this script, so that it can be reused by all of my different repos. This necessitates adding unit tests, so that I can be sure that the expected environment and config result in the right files being generated into the correct locations.

This testing is proving very difficult, as, when running shell commands from Node using execa, both Gulp and Mocha are adding layers of abstraction. These make it hard to see when tests are failing and why.

The solution seems to be to remove the abstraction by using raw shell commands in my npm scripts. So now I'm migrating my build script from Gulp to NPM.

Sharing one set of NPM scripts between multiple projects

Example

This simple example prints the contents of a directory.

  1. When a first npm list script is run from wpdtrt-dbth/package.json
  2. It calls a second npm list script in wpdtrt-dbth/node_modules/wpdtrt-npm-scripts/package.json
  3. This runs the shell ls command, printing out the contents of the wpdtrt-dbth directory.

The prefix flag allows scripts in dependency B to be called by dependency A, by replacing the implicit script path (CWD) with another path.

This is the location where global items are installed, which by default is the install location of npm itself. If prefix is set on the command line, then non-global commands are forced to run in the given folder. The Ultimate Guide to Configuring NPM

It's a similar idea to running a binary at ./node_modules/.bin/name, where ./node_modules/.bin/ is the prefix.

// ./test/fixtures/dotherightthing/wpdtrt-dbth/package.json
{
  "name" : "wpdtrt-dbth",
  "config": {
    "wpdtrt_npm_scripts": "./node_modules/wpdtrt-npm-scripts"
  },
  "scripts" {
    "list": "npm run list --prefix $npm_package_config_wpdtrt_npm_scripts"
  }
}

The second script traverses back to the wpdtrt-dbth directory, and runs the ls command, printing the contents of the wpdtrt-dbth directory to the screen.

Here the config is redundant, as $INIT_CWD stores the path to the directory where the script was originally run.

// ./test/fixtures/dotherightthing/wpdtrt-dbth/node_modules/wpdtrt-npm-scripts/package.json
{
  "name": "wpdtrt-npm-scripts",
  "scripts": {
    "list": "cd $INIT_CWD && ls"
  }
}

This approach allows the mechanics of the various build tasks to be updated in wpdtrt-npm-scripts, independently of wpdtrt-dbth, wpdtrt, wpdtrt-gallery and so on.

Testing

During the development of wpdtrt-npm-scripts, it might not be loaded as an NPM dependency yet.

If this is the case, running npm run ls in the wpdtrt-dbth directory will generate an error:

npm ERR! enoent ENOENT: no such file or directory, open '/Website/test/fixtures/dotherightthing/wpdtrt-dbth/node_modules/wpdtrt-npm-scripts/package.json'

To correct this, we need to change the path to wpdtrt-npm-scripts, but only for the test.

Luckily the path is controlled by the config object in wpdtrt-dbth/package.json, so we can override it on the command line:

// old relative path points to ./test/fixtures/dotherightthing/wpdtrt-dbth/node_modules/wpdtrt-npm-scripts/package.json
// new relative path points to ./package.json

npm config set wpdtrt-dbth:wpdtrt_npm_scripts ../../../../

That's it.

npm run list now runs the ls command in the wpdtrt-dbth directory.

Links


Writing an environmental variable to a file

If the $CI variable exists (CI=true), CI is output, otherwise WP is used instead.

The output is then piped (|) to another function which converts it to lowercase.

Finally, the output is used to populate a new file.

{
  "scripts": {
    "compile:scss_import": "cd $INIT_CWD && echo '@import \"wpdtrt/dependencies-'${CI:-WP}'\";' | tr -s '[:upper:]' '[:lower:]' > scss/_wpdtrt-import.scss"
  }
}
// scss/_wpdtrt-import.scss
@import "wpdtrt/dependencies-WP";

Note: It's possibly to permanently bork Node by setting a bad variable name. In this case you need to edit the .npmrc file to remove the bad entry:

nano ~/.npmrc

See: Where is NPM config file?

Or, delete an environmental variable like so (note: no leading $):

unset varname

Links


More links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment