3

We have a project which to ease development uses node to handle some dependencies as well as our test scripts to spin up a docker image to run tests. The goal is that the devs don't need to run bats locally and can just run npm test which'll spin up the image and run tests.

I can get it working locally in my Git Bash multiple ways - however I cannot get it working via the npm script - it's caused me a day or 2 now of spamming different SO approaches to try and tackle. Here's what I'm working with:

{
  "scripts": {
    "test": "bats test/**/*.bats",
    "test-ci": "bats --formatter junit -T test/**/*.bats",
    "test-docker": "docker run -it -v /c/source/git/devops/dotnetcore-nuget-push/:/app node:slim npm test",
    "test-docker-test": "docker run -it -v $(pwd):/app -w //app node:slim npm test",
    "test-docker-debug": "docker run -it -v /c/source/git/devops/dotnetcore-nuget-push:/app -w //app node:slim bash -c \"echo $(pwd) && ls\"",
    "test-docker2": "docker run -it -v /c/source/git/devops/dotnetcore-nuget-push/:/app -w //app node:slim npm test",
  },
}

Ideally we'll just have test in the end - just trying a few things to make sure they work the same.

Here's what works locally in Git Bash:

  • docker run -it -v /$(pwd):/app -w //app node:slim npm test
  • docker run -it -v /$(pwd):/$(pwd) -w /$(pwd) node:slim npm test
  • MSYS_NO_PATHCONV=1 docker run -it -v $(pwd):$(pwd) -w $(pwd) node:slim npm test

So I've tried adding some of those and a debugging one to my npm scripts but the only thing that works is when I hardcode the volume path -v /c/source/git/devops/dotnetcore-nuget-push/:/app. Ideally this wouldn't be hard coded but when I use $(pwd) I get errors that it can't find my package.json now.. here's it using $(pwd) instead of hard coded path - it tries to look in the workdir/app path - however the workdir IS app, it should be looking for the package.json right where the app is mounted - similar to how it is when I do the hard coded path.

app/package.json error

I've looked at the following resources - but none are using npm

Poat
  • 327
  • 1
  • 11
  • 2
    It seems you are running npm from Windows. The default shell (which will also be what evaluates your scripts when called from npm - regardless of what shell you used to start npm) for windows is cmd and not bash, and cmd doesn't use the `$()` syntax. Try `%cd%` instead. – CherryDT Sep 14 '21 at 18:05
  • @CherryDT wow that was it.. I was making a huge assumption running npm from different shells that it run under that context and in that shell.. updated that bit of code to -v %cd%:/app and it works great! – Poat Sep 14 '21 at 19:26
  • Glad to hear. Expanded it into an answer. – CherryDT Sep 14 '21 at 19:40
  • Is `bats` [this npm package](https://www.npmjs.com/package/bats)? So long as you have it listed in your `devDependencies` in your `package.json` file, `npm run test` should work fine, without developers having to do manual additional installs and without dealing with the complexities of Docker. – David Maze Sep 14 '21 at 23:05

1 Answers1

3

TL;DR

Replace $(pwd) by %cd%.

Explanation

It seems you are running npm from Windows. There is a pitfall here: Even if you use Git Bash (or whatever shell you like), the subshells spawned by npm won't necessarily use the same shell - they'll use the default shell (in Windows it's specified by the COMSPEC environment variable). In a Linux environment that will usually be bash, but in Windows it'll be cmd.exe and not Git Bash! And cmd.exe won't know what to do with $(pwd) in the command line and will forward it to docker verbatim.

That means that scripts in your package.json cannot use shell-specific features if you intend to use them cross-platform. For more complex operations it's usually easiest to have node .scripts/someScript.js there or the like, and to provide the actual logic in a JavaScript file in a platform-agnostic way.

If it will suffice for your needs to have a script that runs correctly only under Windows, then you can use %cd% instead of $(pwd) (the cmd way to reference the current working directory). It's best to then put the whole argument in double quotes though because cmd also passes the command line arguments differently to the new process.

Further reading: https://docgov.dev/posts/npm-scripts/

CherryDT
  • 25,571
  • 5
  • 49
  • 74