How can I pass 'yes' response when npm installing on Dockerfile - bash

I have a Dockerfile like below :
FROM node:latest
RUN npm install something && \
npm install something && \
npm install something
I want to pass 'yes' response for all required 'yes/no' param when npm installing.
Is there any way to do this?

I used the following to install Angular without usage statistics sharing.
RUN echo n | npm install -g --silent #angular/cli
I think echo y should work for you

There's the yes command specifically for this in linux:
RUN yes | npm install something && \
npm install something && \
yes yes | npm install something
The first line outputs a list of "y" to the first npm install command. The yes command also takes an option of what you want it to output. So if you need to output "yes" instead of a single "y" character per line, then you can run yes yes as seen in the third example.

Related

Debian: "command -v <command>" still returns path after removing the package?

I've uninstalled the stylus package on my Debian by sudo apt-get remove --purge node-stylus.
Now it says when I try to run the stylus command: stylus: command not found. So it works as it should.
But in my scripts I check whether Stylus is installed or not by:
if ! command -v sudo stylus &> /dev/null; then
echo "ERROR: Stylus is not installed!"
exit 1
fi
And for some reason command -v stylus still returns /usr/bin/stylus thus the script won't fail.
I checked /usr/bin/ and there is no stylus there.
Could someone explain to me please why does this work like this?
Bash maintains a cache for lookups; you want to do
hash -r stylus
to force it to forget the old value.
Separately, of course, don't use command -v sudo when you actually want command -v stylus, as already pointed out in a comment.

How to check if npm script exists?

I am creating a bash script which runs through each of my projects and runs npm run test if the test script exists.
I know that if I get into a project and run npm run it will give me the list of available scripts as follows:
Lifecycle scripts included in www:
start
node server.js
test
mocha --require #babel/register --require dotenv/config --watch-extensions js **/*.test.js
available via `npm run-script`:
dev
node -r dotenv/config server.js
dev:watch
nodemon -r dotenv/config server.js
build
next build
However, I have no idea how to grab that information, see if test is available and then run it.
Here is my current code:
#!/bin/bash
ROOT_PATH="$(cd "$(dirname "$0")" && pwd)"
BASE_PATH="${ROOT_PATH}/../.."
while read MYAPP; do # reads from a list of projects
PROJECT="${MYAPP}"
FOLDER="${BASE_PATH}/${PROJECT}"
cd "$FOLDER"
if [ check here if the command exists ]; then
npm run test
echo ""
fi
done < "${ROOT_PATH}/../assets/apps-manifest"
EDIT:
As mentioned by Marie and James if you only want to run the command if it exists, npm has an option for that:
npm run test --if-present
This way you can have a generic script that work with multiple projects (that may or may not have an specific task) without having the risk of receiving an error.
Source: https://docs.npmjs.com/cli/run-script
EDIT
You could do a grep to check for the word test:
npm run | grep -q test
this return true if the result in npm run contains the word test
In your script it would look like this:
#!/bin/bash
ROOT_PATH="$(cd "$(dirname "$0")" && pwd)"
BASE_PATH="${ROOT_PATH}/../.."
while read MYAPP; do # reads from a list of projects
PROJECT="${MYAPP}"
FOLDER="${BASE_PATH}/${PROJECT}"
cd "$FOLDER"
if npm run | grep -q test; then
npm run test
echo ""
fi
done < "${ROOT_PATH}/../assets/apps-manifest"
It just would be a problem if the word test is in there with another meaning
Hope it helps
The right solution is using the if-present flag:
npm run test --if-present
--if-present doesn't allow you to "check if a npm script exists", but runs the script if it exists. If you have fallback logic this won't suffice. In my case, I want to run npm run test:ci if it exists and if not check for and run, npm run test. Using --if-present would run the test:ci AND test scripts if both exists. By checking if one exists first, we can decide which to run.
Because I have both "test" and "test:ci" scripts, the npm run | grep approach wasn't sufficient. As much as I'd like to do this with strictly npm, I have jq in my environments so I decided to go that route to have precision.
To check for a script named "test:ci":
if [[ $(jq '.scripts["test:ci"]' < package.json;) != null ]]; then
// script exists
fi

How can I measure the execution time of a npm/yarn task/script?

How can I measure the execution time of a npm/yarn task on the command line without modifying the scripts.
In my special use case I want to execute an existing E2E-Test (yarn test:e2e) 100 times and take the average value.
You could use the npm package gnomon:
A command line utility, a bit like moreutils's ts, to prepend timestamp information to the standard output of another command.
Install it like this:
$ npm i -g gnomon
With this you could run:
$ yarn install | gnomon
And it might give you an output like this:
$ yarn install | gnomon
0.5327s yarn install v1.9.4
1.9652s [1/4] Resolving packages...
0.0160s success Already up-to-date.
0.0163s Done in 2.38s.
0.0003s
Total 2.5315s
Use the following command in unix
time npm run build
For windows use this command
Measure-Command { start-process npm 'run build' -wait}
If you don't want any global or even local dependencies for this, or you don't want something that only works on unixy operating systems, this is almost trivially achieved with a simple .js file and an equally simple npm script refinement:
{
...
"scripts: {
"time": "node mark.js",
"start": "npm run time && ...whatever 'start' was before... && npm run time",
},
...
}
With that mark.js file being the almost trivial following code:
const fs = require("fs"); // or import fs from "fs"; if you're working on modern JS
const timingFile = `.timing`;
if(fs.existsSync(timingFile)) {
const end = Date.now();
const start = fs.readFileSync(timingFile);
fs.unlinkSync(timingFile);
console.log(`Runtime: ${(end - start)/1000}s`);
} else { fs.writeFileSync(timingFile, `${Date.now()}`, `utf8`); }
Inspired by #user1816491 answer, I remembered that I used to use a shell utility, ts.
In unix (apt is for debian/ubuntu), install moreutils that contains ts, as e.g.
sudo apt install moreutils -y
Then e.g.
$ npm run build | ts '%FT%T'
2022-08-24T09:55:13
2022-08-24T09:55:13 > build
2022-08-24T09:55:13 > next build
2022-08-24T09:55:13
or
$ npm run build | ts -s '[%H:%M:%.S]'
[00:00:00.416378]
[00:00:00.416511] > build
[00:00:00.416577] > next build
[00:00:00.416603]

function to detect cli installation

I have inline checking to detect the installation of cli packages to save time on installing existing package, but I found it is tedious and not that readable for those long list.
For example:
which -s redis-cli || brew install redis
which -s java || brew cask install java
which -s yarn || npm install -g yarn
Are there any function to make it nice looking? For example:
function npmInstall(name) {
if (which -s name) {
return;
}
npm install -g name;
}
Thanks a lot!
You may pass client packages as parameters.
Example, script.sh:
for cli in $#; do
which "$cli" || npm install -g "$cli"
done
invoked with ./script.sh java yarn
Update:
As package names may differs from executable names, you can handle these differences using a Bash associative array. Package name passed as parameter to the script will be used only if no value is found in the array for that package:
for pkg in $#; do
declare -A exe
exe=([redis]="redis-cli" [otherpkg]="otherpkg-cli")
package=${exe[$pkg]:-$pkg}
which "$package" || npm install -g "$package"
done

Bash: Automatic reaction on press y or n

I'm starting to learn shell scripting.
I using Ubuntu and the APT and for example I will install apache with a shell script.
#!/bin/bash
sudo apt-get update
sudo apt-get install apache2
Eveythink work's but their prompt a message with
"Press y/n to install ..."
And I want that my script press automatic yes for me.
Thank's for help.
Use
$ sudo apt-get install apache2 -y
You can look here to learn more.
For any command that don't have a -y option as apt-get, you can use yes command :
yes | yourcmd
To give other input :
yes nothanks | yourcmd
Or with a delay between inputs :
while true; do echo "y"; sleep 1;done | yourcmd

Resources