Pass text file as CLI argument in NPM script in GitHub action - bash

I have very long cmd command in npm script and I try to extract some part of it into text file, and then pass its content as arguments.
"build": "npm-run-all --print-label $(< build-order.txt)",
It is working locally, but when i run this command on GitHub action nothing happens
There is not errors, just nothing.
I used https://github.com/marketplace/actions/debugging-with-tmate to try to run this command in terminal and when i just execute pnpm npm-run-all --print-label $(< build-order.txt) it is working, but when just pnpm build again nothing happens. It feels like something wrong with running npm script itself on github action.

Looks like there was some issue on GitHub actions, this helped
"build": "npm-run-all --print-label $(cat build-order.txt)",

Related

Change value of shell variables as an argument of npm run command

I am trying to accomplish the following -> Right now I use cypress to run e2e tests. It is being launched by npm command. I have several environments and different user permission. I created a shell script, where I have stored value of environment and user permission rights. What I want to do is to have opportunity to run npm command with parameters to change the value of variable from shell script. Could someone give a clue, is it even possible? The expected behaviour is to write something like:
npm run cy dev3,full
And have the opportunity to change the value of shell script variable to launch necessary environament and change value of user permissions.
package.json command:
"scripts": {
"cy": "./scripts/cypress.sh",
}
cypress.sh file content
#!/usr/bin/env bash
DEV_ENV="${DEV_ENV:-"dev3"}"
USER_TYPE="${USER_TYPE:-"full"}"
COMMAND="cypress open \
--browser chrome \
--config baseUrl=https://environment-$DEV_ENV.com \
--env DEV_ENV=https://environment-$DEV_ENV.com,USER_TYPE=$USER_TYPE
"
eval $COMMAND
Are you trying to change the environment variables seen in cypress.sh? If so, you can just execute npm run like this:
DEV_ENV=dev2 USER_TYPE=empty npm run cy
and it will change the value of DEV_ENV and USER_TYPE.
If you want to strictly run it by using the format you gave (npm run cy dev3,full), the args dev3,full are passed on to cypress.sh, so you can just parse the arguments directly in cypress.sh:
if [ ! -z "$1" ]; then
# do whatever here...
fi

Bash script behaving different than when manually executing commands into remote server

I have a remote server and I can ssh into it and when I execute npm install it works just fine. I can see that it's installed by calling which npm and i see:
/home/ubuntu/.nvm/versions/node/v15.11.0/bin/npm
Great.
However, when I do this via a bash script, it says
bash: line 1: npm: command not found
My script:
#!/bin/bash
ssh he-int 'npm install'
Why the discrepancy between the two ? It's the same commands...
Sounds like maybe npm is added to your PATH in one of the login scripts (.bashrc, .profile, etc). I especially think this is true because the npm path indicates you are using nvm to manage your npm environment. There may be a call to nvm to add npm to the path in one of those login scripts.
When you run an ssh command like your second command, it doesn't run as a login shell, so it doesn't run the login scripts. You can either:
Try and force it to run as a login shell (ssh -t maybe? not sure).
Try to initialize your npm environment inside your script, probably by calling nvm.
npm may not be in the PATH of the user you're sshing in as using the bash script.
Use this to see what's in your PATH variable:
ssh he-int 'echo $PATH'
You can also just try to use the path directly and see if it works.
#!/bin/bash
ssh he-int '/home/ubuntu/.nvm/versions/node/v15.11.0/bin/npm install'

How execute bash Command Substitution in npm script

I want to execute linter only on staged files.
For this i wrote inside package.json the command(inside scripts):
"fix-lint": "tslint $(git diff --name-only --staged) "
Execute it:
npm run fix-lint
I have an error:
error: unknown option --name-only
I tried to figure out and try simple command:
"lss": "echo $(ls)"
And again execute it:
npm run lss
The result is printing $(ls) instead of printing all files in directory.
My question is how to fix this commands/scripts?
Or maybe in general how execute bash Command Substitution in npm script.
Thanks in advance.

Run node server in background and start karma from npm script

I'd like to run a node server in background and start karma (on win7). Writing a bash script like the following (and run it with git bash) appears to work, but it reports to a separate window instead of the WebStorm terminal:
#!/bin/bash
node test/server/index.js &
karma start karma.conf.js
package.json
"scripts": {
"test": "test.sh"
},
If I try it with git bash and bash test.sh then it reports to the same window.
I tried to do something similar in npm, but it cannot run background processes.
"scripts": {
"test": "node test/server/index.js & karma start karma.conf.js"
},
No matter how I try it can run things only in a single process, so it waits for the node server to exit, and thus the karma server never starts.
Any idea how to solve the bash reporting to WebStorm terminal or the npm parallelization?
update:
I think I have found the reason: https://github.com/npm/npm/issues/8358 This seems to be a Windows related issue. On Linux it would work properly. So it is not possible to fix the npm script. I think instead of bash I'll move the karma server and the node server to a node script and create a child process for the node server to be Windows compatible. I hope that way the karma logs will show up in the WebStorm terminal.
Cross-platform shell parallelization solution
I had a little time to search more in the topic. Actually there are parallelization tools available for npm and shell scripts, which are cross-platform:
https://github.com/mysticatea/npm-run-all
https://github.com/kimmobrunfeldt/concurrently
https://github.com/royriojas/shell-executor
There was an initiative to merge all of these projects along with others, which was more or less successful: https://github.com/mysticatea/npm-run-all/issues/10. According to one of the contributors npm-run-all is great now, on the other hand the npm-run-all repo does not seem to be that active nowadays, so probably it is better to use concurrently or shell-executor instead.
WebStorm settings / Git bash solution
I set the WebStorm terminal to git bash instead of cmd.exe:
File/Settings > Tools/Terminal > Shell path: "C:\Program Files\Git\bin\bash.exe" > Ok
And I changed the npm script to run with bash:
"scripts": {
"test": "bash -c \"node test/server/index.js & karma start karma.conf.js\""
},
Hopefully the bash commands work the same on Linux too, I have to check with Travis, but there is a very good chance.
Using the bash command for the sh file works too:
"scripts": {
"test": "bash test.sh"
},
Is npm shell configuration a possible solution?
It is interesting that without using the bash command the upper solution did not work. Probably npm started it with cmd.exe and that opened bash.exe in a new window when it checked the header and realized that it is a bash script. And yes, I checked and it uses the cmd.exe by default:
$ npm config ls -l | grep shell
shell = "C:\\Windows\\system32\\cmd.exe"
So another option might be to set the npm shell to git bash and after that I don't have to use the bash in my scripts.
npm config set shell "C:\Program Files\Git\bin\bash.exe"
Well I did exactly that, but nothing changed. I still have to use bash in my scripts and the sh file still opens in a new window. It does not make a real difference, we still need the Webstorm settings to run the script with bash, so it is not a solution.

How to set shell for npm run-scripts in Windows

I'm running npm on Windows and would like to use & style parallel operations in run-scripts
but running in parallel in cmd is kind of messy
in my package.json file I'd like to write-
scripts: { "go": "cmd1 & cmd2"}
but npm executes the script under cmd.exe which does not know about ; I could change this to
scripts: { "go": "bats/bat1.bat") where bat1.bat is a cmd bat file that uses the windows style call or start commands to run commands in parallel. which works but gives me a script that only works on Windows.
It would be a lot simpler if I could get npm to run the script under a bash clone or cygwin.
I tried
config: { "shell": "bash"}
but that still ran cmd.exe
Is there any way to tell npm to run-scripts using a specific shell (not cmd.exe)?
Since npm 5.1
npm config set script-shell "C:\\Program Files (x86)\\git\\bin\\bash.exe"
or (64bit installation)
npm config set script-shell "C:\\Program Files\\git\\bin\\bash.exe"
Note that you need to have git for windows installed.
You can revert it by running:
npm config delete script-shell
Here's one way to do it:
Create a script, such as my_script.sh, in your project bin directory.
In your package.json file, add a line to run the script using bash. For example:
"scripts": {
"boogie": "bash bin/my_script.sh"
}
Now you can run your bash script from npm by:
npm run-script boogie
Not very elegant, but it works.
If you are developing in both Windows and Linux/Unix, then at least this approach is fairly portable to both environments.
Ideally, overriding the npm shell config parameter should work, but npm (at least version 1.4.14) seems in Windows to ignore the setting and use cmd.exe instead.
Use the following command in your bash or Git Bash shell to find out the shell setting:
$ npm config ls -l | grep shell
By default, the output will be:
shell = "C:\\WINDOWS\\system32\\cmd.exe"
However, to override the default shell parameter, you can add (or edit) an npmrc file to the \Users\yourusername\AppData\Roaming\npm\etc directory. Just add the following line:
shell = "C:\\Program Files (x86)\\git\\bin\\bash.exe"
The path you use can be any valid path to bash.exe. Now, if you run the above "npm config ls -l | grep shell" command, you will see the following output, indicating that the shell parameter has been overriden:
shell = "C:\\Program Files (x86)\\git\\bin\\bash.exe"
; shell = "C:\\WINDOWS\\system32\\cmd.exe" (overridden)
One day, perhaps, a new version of npm will pay attention to the overridden shell parameter.
You can also use cross-platform powershell https://github.com/powershell/powershell#get-powershell for npm scripts.
To set for single project, run this from project root folder:
npm config set script-shell pwsh --userconfig ./.npmrc
To globally set for all node projects:
npm config set script-shell pwsh [--global]
just using CMD's way to run .bat!
.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"app": "cd build & browser-sync start --server --files 'index.html'",
"bat": "start start-browser.bat",
"starts": "start http://localhost:7777/datas/ && start http://localhost:7777/Info/"
},
.bat
start http://localhost:7777/datas/ && start http://localhost:7777/Info/
Use a specifically created node_module for this purpose. I suggest using npm-run-all, but others exists, such as parallelshell.
Parallelshell example is below for drop-in-replacement for your question.
"scripts": {
"parallelexample1": "parallelshell \"echo 1\" \"echo 2\" \"echo 3\""
},
following command:
npm run parallelexample1
works both on windows and unix(Linux/MacOS).
Interestingly npm-run-all does not support shell commands; therefore we need to put all shell commands to separate scripts like below.
"scripts": {
"parallelexample2": "npm-run-all echo*",
"echo1": "echo 1",
"echo2": "echo 2",
"echo3": "echo 3"
},
Following command:
npm run parallelexample2
works both on windows and unix(Linux/MacOS).
In my case I just needed to run npm start from inside Bash. I run cmd then I open bash by running "c:\Program Files\Git\bin\bash.exe". Under bash shell I then was able to call npm build and npm start succesfully.
You may already have bash if you are using Git. If not, you can install it.
Hope this may save someone's time.

Resources