How do I conditionally output eslint results to a file using npm scripts? - linux

I am trying to make a simple npm script to run eslint and check if it's in CI or not and output the results to a file if it is.
This works to output the results to the terminal:
"lint": "eslint src --cache --format $(if [ -z ${SOMEVAR} ]; then echo \"stylish\"; else echo \"checkstyle\"; fi)",
But I want to save them to a file if there is an ENV var present using > checkstyle.xml
Is there a way to tack this onto that command? I've tried several ways, but no luck getting the file to output.
Edit:
I was able to get this working by adding --color | tee checkstyle.xml which writes the xml file regardless of ENV var value and displays a colorized version to terminal. This is not ideal, but does work. Open to other ideas though.
I found this great chart that shows what combos of output you can use together to achieve this: https://askubuntu.com/a/731237/541276

Do you mean something like this?
if [ "$somevar" ]; then exec >checkstyle.xml; fi; eslint ...

Related

how to extend a command without changing the usage

I have a global npm package that provided by a third party to generate a report and send it to server.
in_report generate -date 20221211
And I want to let a group of user to have the ability to check whether the report is generated or not, in order to prevent duplication. Therefore, I want to run a sh script before executing the in_report command.
sh check.sh && in_report generate -date 20221211
But the problem is I don't want to change the command how they generate the report. I can do a patch on their PC (able to change the env path or etc).
Is it possible to run sh check.sh && in_report generate -date 20221211 by running in_report generate -date 20221211?
If this "in_report" is only used for this exact purpose, you can create an alias by putting the following line at the end of the ".bashrc" or ".bash_aliases" file that is used by the people who will need to run in_report :
alias in_report='sh check.sh && in_report'
See https://doc.ubuntu-fr.org/alias for details.
If in_report is to be used in other ways too, this is not the solution. In that case, you may want to call it directly inside check.sh if a certain set of conditions on the parameters are matched. To do that :
alias in_report='sh check.sh'
The content of check.sh :
#!/bin/sh
if [[ $# -eq 3 && "$1" == "generate" && "$2" == "-date" && "$3" == "20"* ]] # Assuming that all you dates must be in the 21st century
then
if [[ some test to check that the report has not been generated yet ]]
then
/full/path/to/the/actual/in_report "$#" # WARNING : be sure that nobody will move the actual in_report to another path
else
echo "This report already exists"
fi
else
/full/path/to/the/actual/in_report "$#"
fi
This sure is not ideal but it should work. But by far the easiest and most reliable solution if applicable would be to ignore the aliasing thing and tell those who will use in_report to run your check.sh instead (with the same parameters as they would put to run in_report), and then you can directly call in_report instead of the /full/path/to/the/actual/in_report.
Sorry if this was not very clear. In that case, feel free to ask.
On most modern Linux distros the easiest would be to place a shell script that defines a function in /etc/profile.d, e.g. /etc/profile.d/my_report with a content of
function in_report() { sh check.sh && /path/to/in_report $*; }
That way it gets automatically placed in peoples environment when they log in.
The /path/to is important so the function doesn't call itself recursively.
A cursory glance through doco for the Mac suggests that you may want to edit /etc/bashrc or /etc/zshrc respectively.

Execute p4 aliased command result in messed wrong order of lines in output

I have the following content inside my p4aliases.txt.
diff-cl $(target-cl) = diff -dl //...#$(EQ)$(target-cl)
Basically it diffs against your files in current workspace toward the target shelved files of changelist.
It is fine. I can execute it. But when I compare the result coming from above aliased command against the direct raw (non-aliased) command as follows
p4 diff -dl //...#=<target-cl>
the output lines of text from aliased command is in wrong order e.g. changes according to a certain file shows up first before a line of file shown, line orders are messed up. This is not the case if you execute with a non-aliased command.
Example
Expected result
==== //depot/common.h#none - x:\mydir\project\src\common.h ====
==== //depot/file.cpp#none - x:\mydir\project\src\file.cpp ====
3a4
> added line 1
==== //depot/file.h#none - x:\mydir\project\src\file.h ====
Actual result
3a4
> added line 1
==== //depot/common.h#none - x:\mydir\project\src\common.h ====
==== //depot/file.cpp#none - x:\mydir\project\src\file.cpp ====
==== //depot/file.h#none - x:\mydir\project\src\file.h ====
I have p4 version as of Rev. P4/NTX64/2021.1/2126753 (2021/05/12).
Perforce server version (got from p4 info) is Server version: P4D/LINUX26X86_64/2017.1/1574018 (2017/10/02).
How can I solve this issue?
Could this be a version too far away between client and server
Update
I have tested p4 client all the way down from 2016-2020 version by downloading old binaries from ftp.perforce.com (in directory perforce). No luck. Output still messed the same. So it's not the problem about version mismatch.
This looks like a bug in the p4 client. When the client does a diff, it's written by the ClientUser::Diff() method, which defaults to writing to stdout (i.e. it does not route the output through ClientUser::OutputText()):
https://workshop.perforce.com/projects/perforce_software-p4/files/2018-2/client/clientuser.cc#436
https://workshop.perforce.com/projects/perforce_software-p4/files/2018-2/client/clientuser.cc#573
Output from commands run as part of an alias go through the ClientUserStrBuf subclass, which buffers all of its output. The file headers, for example, are buffered by ClientUserStrBuf::OutputInfo():
https://workshop.perforce.com/projects/perforce_software-p4/files/2018-2/client/clientaliases.cc#1647
There isn't a ClientUserStrBuf::Diff() implementation, though, so that diff output goes straight to stdout while the headers are buffered and printed at the end (presumably after some post-processing) -- hence the diff output showing up first in the console.
The fix I'd make would be to have the base ClientUser::Diff() implementation route the output through OutputText() when no output file is provided, which seems like the least-surprise behavior; that'd fix the aliases behavior and might even make life a little easier for other client developers who would otherwise hit the same issue. If you have a support contract with Perforce you can file this as a bug report, or since the client is open source you can take a crack at fixing and building it yourself. I don't think there's a workaround that doesn't involve modifying the client source code.
Samwise has the correct approach to truly fix the problem at hands although it might take some effort to understand the code, and conduct the fix itself.
At any rate, if we took such approach we won't be able to take benefits of bug fixes and future updates as we will be stuck with 2018-2 version of p4 as it's the latest as it can be in which we can grab the source.
I would recommend to use WSL then interact with p4.exe (yes, a Windows-based binary) for Windows-based project, and p4 for Linux-based binary. If you didn't use WSL, please find the .bash_aliases-like solution as I have below to seamlessly solve aliases diff operation.
Put the following code into your ~/.bash_aliases
# p4 - fix of aliases diff operation
# platform independent, it will choose a correct binary path to execute properly
p4() { cmd="p4.exe" # default is Windows-based
# get the last argument value, if "-lx" passed in then we know it's linux
if [[ "${#: -1}" == "-lx" ]]; then
cmd="/usr/local/bin/p4"
fi
if [[ $1 == "diff-cl" ]]; then
if [ -z "$2" ]; then
echo "usage: p4 diff-cl <CL>"
return 1
fi
$cmd diff -dl //...#=$2 | diffp4 | less -r
elif [[ $1 == "diff-cl-fonly" ]]; then
if [ -z "$2" ]; then
echo "usage: p4 diff-cl-fonly <CL>"
return 1
fi
$cmd diff -Od -dl -ds //...#=$2 | diffp4 | grep ==== | less -r
else
$cmd "$#"
fi
}
then source ~/.bash_aliases.
What it does is to allow you to still use p4 with all of its original commands & arguments normally with exceptions of diff-cl (which is the same name of alias I've put into p4aliases.txt for Windows or ~/.p4aliases for Linux). You can safely remove diff-cl entry from p4's alias file, or just leave it there. What we have in ~/.bash_aliases file will intercept whenever such argument matches then execute the raw command, just that we don't have to type long command ourselves.
We can later remove such section in our ~/.bash_aliases file when upstream p4 has been fixed.
In else section, we just relay the the whole arguments, and it will be performed just as normally done.
Extra: diff-cl-fonly to list out only files (its depot path, and local workspace path) which have changes.

npm command doesn't update json

This command works fine:
json -I -f ./src/environments/build.json -e 'this.patch++'
I'm trying to create a custom build NPM command in my package.json file that runs this command before the actual build, but first I just tried to run the json command, just to see if it's working, but it doesn't :/
package.json
{
...
"scripts": {
...
"svrge-build-dev": "json -I -f ./src/environments/build.json -e 'this.patch++'",
...
}
then I get this output (which is exactly the same as when I run the JSON code by itself) which means that the command is definitely running
> web-client#1.0.0 svrge-build-dev D:\repos\test\web-client
> json -I -f ./src/environments/build.json -e 'this.patch++
json: updated "./src/environments/build.json" in-place //<- this is exactly the same'
However, the build.json file is not being updated
No errors in the terminal
any idea how I can get it to work? I can't seem to find anything regarding that.
I would appreciate any help, been scratching my head for hours
Tom
Re-stating what I said in the comment: try to replace the single quotes with double quotes:
{
// ...
"scripts": {
// ...
"svrge-build-dev": "json -I -f ./src/environments/build.json -e \"this.patch++\"",
// ...
}
What triggered that thought was this line in the output:
> json -I -f ./src/environments/build.json -e 'this.patch++
After doing some digging, I think it depends on the OS and/or command line interpreter. It shows the command that was run, but not with the finishing single quote.
After some searching, it appears that is indeed a bug: see this issue and this issue. You might want to give the maintainers a heads up about it: the last issue I've linked to, makes it seem like it's a Windows issue.

Gearman: troubles with first use

I tried to start with Gearman. After downloading and setting it, gearman_version() works. But, when I start server and try to init worker like so:
php myFileName.php &
I see the code:
And when I init the client, I see code too. What am I doing wrong?
i don`t know why, but the examples from youtube was not correct in my case. The first scripts, which worked I get from http://php.net/manual/ru/gearman.examples-reverse-bg.php
You likely have short open tags disabled on your install. Notice, running a php file that doesn't actually contain any PHP will just echo the contents of the file.
>$ echo 'hello' > text.php
>$ php text.php
hello
>$
You can verify the setting for your install with the following
>$ php -i | grep "short_open_tag"
short_open_tag => On => On
If tags are On you're all set.

Colored logging in terminal with NPM run script

I'm trying to setup a project exclusively with NPM as a build system (no Gulp or Grunt) so I'm a bit of a beginner, but so far it's working pretty nicely except for this little road block.
The scripts section of my package.json looks something like that :
"scripts": {
"clean:task": "rimraf dist/*",
"clean:notify": "notify --t 'Cleaning done.' --m 'dist/ has been cleaned successfully.",
"clean": "npm run clean:task -s && npm run clean:notify -s",
"serve": "browser-sync start --p 'xxx.dev/app' --host 'xxx.dev' --port '3000' --open 'external' --f 'app'",
"styles:task": "node-sass --output-style nested -o app/assets/css app/assets/css",
"styles:notify": "notify --t 'Styles compilation' --m 'Styles have been compiled successfully'",
"styles:build": "npm run styles:task && npm run autoprefixer",
"imagemin": "imagemin app/assets/img dist/img -p",
"scripts:lint": "jshint --reporter=node_modules/jshint-stylish app/assets/js/scripts.js"
}
I have notifications to announce successful tasks, but ideally I'd like some nice colored messages directly in the terminal. I know this can be done with Gulp via colored logging but I can't fin any NPM package that has a CLI that would be able to do that.
Any ideas ? Is it even possible ?
Thanks for your help.
Individual scripts defined in package.json can output a message to Mac's Terminal in color by following a syntax that boils down to echo + ANSI color reference + some text although you can get more complicated than this, as well.
Step 1: Define your scripts
"scripts": {
"greeting": "echo \"\\033[32mHello World\"",
"notification": "echo \"\\033[33mThe Server Has Started\"",
"timestamp": "echo \"\\033[31m--------\";date \"+%H:%M:%S\n--------\n\" && echo \"\\033[00m\""
{
Step 2: Run your scripts
npm run greeting
npm run notification
npm run timestamp
Some things to note
Escaping is inherently a part of this. A comment by James Lim on StackOverflow mentions the use of -e which apparently ensures that echo honors escaping slashes. I found this was necessary when running the command directly in Terminal but unnecessary when firing it as part of npm run <script>.
The ANSI code that sets the color is made up of eight characters that always begin with a backslash, like this \033[32m. Also, notice that the text I am outputting in my scripts above begins immediately after the last character in the ANSI code– this is so the message will be flush left in the Terminal.
In the timestamp script above, the semicolon separates the echo and date commands but maintains the same color we set at the beginning. In fact, this color will affect everything defined in this script and, in my case, even changed the color of a message output by a separate script that immediately followed this one. For this reason, I included another echo that simply resets the color to the Terminal's default color (in this case, black).
For reference, I could have used && in place of the semicolon and achieved the same results. If you do not already know the difference between these two operators, see this post.

Resources