Azure Devops Predefined Variables - pass as parameter - npm

I am using an NPM run task in Azure Devops Pipelines. I would like to pass an Azure Predefined Variable into my package.json.
eg: npm run cypresstask
So that I can then pass this as a parameter for 'cypress run --ci-build-id '

Answering my own question:
NPM Run Task command:
run cypress:ci --azbuildid=$(Build.BuildNumber)
then within package.json you can provide it as
cypress run --ci-build-id $npm_config_azbuildid
So you set params with the --. Provide predefined variables using $() and access them within package.json using $npm_config_

In your package.json file you can write your commands inside scripts:
"scripts": {
"test": "cypress run --ci-build-id"
}
And in your yml file you can just use:
npm test

Related

What are the equivalent CI commands for Vue projects based on Vite instead of the Vue CLI?

I created a new Vue project via npm init vue#latest. I used the Vue CLI before and want to get into Vite now. Inside my Github action I used the Vue CLI service commands before but now I'm looking for the equivalent commands using Vite.
Check that the code style is fine (no errors, no warnings)
Inside my workflow I previously used the command
npm run lint -- --no-fix --max-warnings=0
Based on the lint script command
eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore
I added the lint:ci script command
eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --max-warnings 0 --ignore-path .gitignore
Check that unit tests are passing
Inside my workflow I previously used the command
npm run test:unit
Based on the test:unit script command
vitest --environment jsdom
I added the test:unit:ci script command
vitest --environment jsdom --run
Check that e2e tests are passing
Inside my workflow I previously used the command
npm run test:e2e -- --headless
There already is a test:e2e:ci script command and based on the Cypress docs I think I have to use it this way (which worked for me)
- name: Check if e2e tests are passing
uses: cypress-io/github-action#v2
with:
build: npm run build
start: npm run test:e2e:ci
Do you have any better solutions? I'm not sure if this is the most elegant way or if Vue/Vite already provide some commands I don't know about yet.
Thanks in advance!

How to execute nested "npm run commands" inside an npm#^7.0.0 monorepo set up within the context of the current workspace?

I have a monorepo with several workspaces within it. It has been very common for me to use chained npm scripts for simple tasks instead of using a task runner. So for example, the following configuration (pseudo code) is very common for me and usefull as well, specially for pre and post build scripts
"scripts": {
"prebuild:task1":"task1 --task1-arguments",
"prebuild:task2":"task2 --task2-arguments",
"prebuild": "npm run prebuild:task1 && npm run prebuild:task2",
"build":"build-script --build-arguments",
}
So the above is the package.json for the child worskpace itself and then in the master package.json I have the call to the script that triggers the build for that workspace.
build:packageA: "npm run build -w packageA"
All seems working well but the chained "npm run script" inside the workspace is actually execute in the context of the master monorepo and not inside that particular workspace.
So, in summary, the first call is to run the build script in the workscape and then triggers the prebuild script of that workspace BUT as that script execute chained npm run scripts those are run in the context of the master repo which happens that they don't exist in there. So the callstack might be ...
(master) build:packageA
(packageA) prebuild
(master) npm run prebuild:task1 >>>> EXIT ERROR
The only way I found, up to now, to bypass this issue was to make my child workspace a monorepo itself holding zero woskpaces. Essentially I have a "workspaces" key in its package.json pointing to the root directory. This enables me to use the -w flag in the scripts section so to refer all scripts to itself. So my current workaround looks like this ...
"workspaces": ["."],
"scripts": {
"prebuild:task1":"task1 --task1-arguments",
"prebuild:task2":"task2 --task2-arguments",
"prebuild": "npm run prebuild:task1 -w packageA && npm run prebuild:task2 -w packageA",
"build":"build-script --build-arguments -w packageA"
}
Isn't there already a better way to solve this?
Thanks in advance to everyone!
Following this post https://stackoverflow.com/a/67060676 I found out that npm changed the way it calls nested scripts in workspaces.
I ran into similar issues like you while running npm#7.5, but the feature was introduced in npm#7.7. Updating node to v17 and npm to 8.3 resulted in everything is running as intended.
In my case I wanted to execute nested npm run build commands in workspaces.

Passing arguments to combined npm script with condition [duplicate]

I have the below scripts in my package.json:
"scripts": {
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
The 'vumper' package takes in a command line argument (such as 'dv'). What I would like to be able to do is have a command that runs both of these in succession.
Essentially, I would like to be able to run:
npm run vumber dv
and then
npm run format
but in one command, something like
npm run my-build dv
which would run both of the above commands, correctly accepting the command line argument 'dv' and passing it to the first npm run vumper. Is this possible?
Short Answer:
Essentially, what you're wanting is to have an npm-script something like this, whereby <arg-here> is provide via the CLI;
...
"scripts": {
"my-build": "npm run vumper <arg-here> && npm run format",
...
},
...
However, unfortunately npm does not have a built-in feature to achieve this.
The special npm option --, (refer to the end of Solution 1 below for further info about this option), can only be used to pass an argument to the END of a script but NOT into the MIDDLE. So, if your two commands were in the opposite order, the -- option could be used like this:
...
"scripts": {
"my-build": "npm run format && npm run vumper --",
...
},
...
To overcome the limitation of there being no built-in feature to pass an argument into the MIDDLE of a script consider the following solutions:
For a Bash only solution refer to the "Solution 1" section.
If cross platform support is required then follow the solution described in the "Solution 2" section.
Solution 1 - Bash (MacOS/Linux/ etc..):
Configure your my-build script in the scripts section of package.json to invoke a Bash shell function, as shown below:
package.json
...
"scripts": {
"my-build": "func() { npm run vumper \"$1\" && npm run format; }; func",
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
...
Explanation:
The Bash function named func does the following:
Firstly runs npm run vumper <arg>. Whereby <arg> will be the shell argument passed via the CLI. It is referenced in the script using $1 (i.e. the first positional parameter/argument).
Subsequently it runs the script named format via the command npm run format.
These two npm run commands are chained using the && operator, so the second npm run format command will only run if the initial npm run vumper <arg> command completes successfully (i.e. returns a 0 exit code).
Running my-build script:
To invoke my-build via your CLI you'll need to run:
npm run my-build -- dv
Note:
In this instance the trailing dv part is the argument that will be passed to your vumper script.
The special option -- must be specified before the argument. The docs describe the -- option as:
... The special option -- is used by getopt to delimit the end of the options. npm will pass all the arguments after the -- directly to your script: ... The arguments will only be passed to the script specified after npm run and not to any pre or post script.
Solution 2 - Cross-platform:
For a cross-platform solution, (one which works successfully with Bash, Windows Command Prompt / cmd.exe, and PowerShell etc..), you'll need to utilize a nodejs helper script as follows.
run.js
Let's name the nodejs script run.js and save it in the projects root directory, at the same level as package.json.
const execSync = require('child_process').execSync;
const arg = process.argv[2] || 'dv'; // Default value `dv` if no args provided via CLI.
execSync('npm run vumper ' + arg, {stdio:[0, 1, 2]});
execSync('npm run format', {stdio:[0, 1, 2]});
package.json
Configure your my-build script to invoke run.js as follows:
...
"scripts": {
"my-build": "node run",
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
...
Running my-build script:
As per Solution 1, to invoke my-build via your CLI you'll need to run:
npm run my-build -- dv
Explanation:
run.js utilizes process.argv to obtain the argument passed via the CLI (e.g. dv). If no argument is provided when running npm run my-build the default value, (i.e. dv), is passed to the vumper npm-script.
run.js also utilizes child_process.execSync(...) to shell-out/invoke the two npm run commands.
Npm now has a built-in option to pass cli arguments directly to scripts.
The cli arguments are stored in environmenet variables with prefix npm_config_<flagname>, and they required a very strict syntax, with the form --<flagname>=<flagvalue>.
Example:
"my-build": "npm run vumper %npm_config_myflag% && npm run format",
In the terminal, run npm run my-build --myflag=my_value to execute npm run vumper my_value && npm run format.
Note:
To refer the environment variable in the npm script, you have to use the platform specific syntax, ie %npm_config_myflag% in Windows or $npm_config_myflag in Linux.
UPDATE:
To avoid risks of conflict with the npm_config variables used to configure npm itself, just prefix your arguments with a unique prefix, such as the name of your app.
The potential conflict is a very common problem, which applies in many contexts: any application could use environment variables already used by other applications; for this reason, the environment variables are usually prefixed with the name of the application (eg NVM_HOME, JAVA_HOME). But this potential conflict is not a good reason to avoid using environment variables. The same in my opinion applies to npm params / npm_config env vars. The doc does not say anything about the risk of conflicts, implying I guess they should be managed as usual.
My preferred method is by using environment variables:
{
"scripts": {
"ncc-build": "ncc build $ACTION/src/index.ts -o $ACTION/dist",
"build:pr-changelog": "ACTION=pr-changelog npm run ncc-build",
}
}
It should work in UNIX systems. I'm not sure about windows platfrom compatibility though.
a different approach for doing this - to reach super deep into you dependency chain:
npm scripts section:
"test:local": "cross-env-shell UPDATE_BASELINE=false UPDATE_MODULE=%npm_config_vizdifsingle% run-p koa:ci wdio:local",
"test:remote": "cross-env-shell UPDATE_BASELINE=false UPDATE_MODULE=%npm_config_vizdifsingle% run-p localtunnel:start koa:ci wdio:remote"
by using crossenv and npm's value placement you can pass args to env.args
like this:
npm run test:local --vizdifsingle=some,value,or,values
it will be available to you in
process.env.npm_config_update_module

is it possible to do tasks using npm-scripts only without task runner?

I am new to npm run scripts can I do the following tasks using only npm run scripts? (i.e without any task runner like gulp and grunt)
concat js
scss to css watch
get notified about succesful js concatenation and scss to css conversion
and moving only html, css, js to deployment directory
Any help would be greatly appreciated!
I don't see why not? To give you a little context:
npm run scripts allow you to easily run: any custom script you create, or any script provided from within your node_modules directory. This is exactly what any task runner is providing you with: i.e. custom scripts to accomplish common development tasks, they have just premade these scripts whereas with npm run scripts you're creating them yourself. These npm scripts are created by adding them to the "scripts" field within your package.json file and can be executed by typing the following: npm run <script-name>.
How are we able to just run the binaries of locally installed packages?
Well, the binaries of locally install packages are made available to you courtesy of your PATH environment variable. This is extremely convenient and allows you to run said binaries simply by typing the the name of said package instead of having to point to: node_modules/.bin/<node_module>. Furthermore, to see which scripts are available to you issue a: npm run
Ok back to your question.. Yes you'll will just have to create custom scripts utilizing various libraries to accomplish said task.
For example, scss to css watch, you could create a script like so:
"scripts": {
"buildscss": "sass --watch app/sass:public/stylesheets"
},
Alternatively, you could use node-sass to handle this task:
npm install --save-dev node-sass
"scripts": {
"buildscss": "node-sass --output-style compressed -o dist/css src/scss"
}
To serve and automatically inject changes you can utilize browser-sync. Something like the following:
npm i -D browser-sync
"scripts": {
"serve": "browser-sync start --server --files 'dist/css/*.css, dist/js/*.js'"
}
Alternatively if you only want to move html, css, js to a deployment directory, <dist> in this case, you could do the following:
"scripts": {
"copy": "cp <html_dir> dist/ && cp <css_dir> dist/ && cp <js> dist/",
}
As for your question about notifications: your custom script would run other custom scripts and print to the console the outcome of said script. There is much more that you can do with npm run scripts, such as: linting, watching, combining scripts, etc.. For a great tutorial check out this link as I am just scratching the surface.
Hopefully that helps!

Pass command line args to npm scripts in package.json

I have the below scripts in my package.json:
"scripts": {
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
The 'vumper' package takes in a command line argument (such as 'dv'). What I would like to be able to do is have a command that runs both of these in succession.
Essentially, I would like to be able to run:
npm run vumber dv
and then
npm run format
but in one command, something like
npm run my-build dv
which would run both of the above commands, correctly accepting the command line argument 'dv' and passing it to the first npm run vumper. Is this possible?
Short Answer:
Essentially, what you're wanting is to have an npm-script something like this, whereby <arg-here> is provide via the CLI;
...
"scripts": {
"my-build": "npm run vumper <arg-here> && npm run format",
...
},
...
However, unfortunately npm does not have a built-in feature to achieve this.
The special npm option --, (refer to the end of Solution 1 below for further info about this option), can only be used to pass an argument to the END of a script but NOT into the MIDDLE. So, if your two commands were in the opposite order, the -- option could be used like this:
...
"scripts": {
"my-build": "npm run format && npm run vumper --",
...
},
...
To overcome the limitation of there being no built-in feature to pass an argument into the MIDDLE of a script consider the following solutions:
For a Bash only solution refer to the "Solution 1" section.
If cross platform support is required then follow the solution described in the "Solution 2" section.
Solution 1 - Bash (MacOS/Linux/ etc..):
Configure your my-build script in the scripts section of package.json to invoke a Bash shell function, as shown below:
package.json
...
"scripts": {
"my-build": "func() { npm run vumper \"$1\" && npm run format; }; func",
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
...
Explanation:
The Bash function named func does the following:
Firstly runs npm run vumper <arg>. Whereby <arg> will be the shell argument passed via the CLI. It is referenced in the script using $1 (i.e. the first positional parameter/argument).
Subsequently it runs the script named format via the command npm run format.
These two npm run commands are chained using the && operator, so the second npm run format command will only run if the initial npm run vumper <arg> command completes successfully (i.e. returns a 0 exit code).
Running my-build script:
To invoke my-build via your CLI you'll need to run:
npm run my-build -- dv
Note:
In this instance the trailing dv part is the argument that will be passed to your vumper script.
The special option -- must be specified before the argument. The docs describe the -- option as:
... The special option -- is used by getopt to delimit the end of the options. npm will pass all the arguments after the -- directly to your script: ... The arguments will only be passed to the script specified after npm run and not to any pre or post script.
Solution 2 - Cross-platform:
For a cross-platform solution, (one which works successfully with Bash, Windows Command Prompt / cmd.exe, and PowerShell etc..), you'll need to utilize a nodejs helper script as follows.
run.js
Let's name the nodejs script run.js and save it in the projects root directory, at the same level as package.json.
const execSync = require('child_process').execSync;
const arg = process.argv[2] || 'dv'; // Default value `dv` if no args provided via CLI.
execSync('npm run vumper ' + arg, {stdio:[0, 1, 2]});
execSync('npm run format', {stdio:[0, 1, 2]});
package.json
Configure your my-build script to invoke run.js as follows:
...
"scripts": {
"my-build": "node run",
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
...
Running my-build script:
As per Solution 1, to invoke my-build via your CLI you'll need to run:
npm run my-build -- dv
Explanation:
run.js utilizes process.argv to obtain the argument passed via the CLI (e.g. dv). If no argument is provided when running npm run my-build the default value, (i.e. dv), is passed to the vumper npm-script.
run.js also utilizes child_process.execSync(...) to shell-out/invoke the two npm run commands.
Npm now has a built-in option to pass cli arguments directly to scripts.
The cli arguments are stored in environmenet variables with prefix npm_config_<flagname>, and they required a very strict syntax, with the form --<flagname>=<flagvalue>.
Example:
"my-build": "npm run vumper %npm_config_myflag% && npm run format",
In the terminal, run npm run my-build --myflag=my_value to execute npm run vumper my_value && npm run format.
Note:
To refer the environment variable in the npm script, you have to use the platform specific syntax, ie %npm_config_myflag% in Windows or $npm_config_myflag in Linux.
UPDATE:
To avoid risks of conflict with the npm_config variables used to configure npm itself, just prefix your arguments with a unique prefix, such as the name of your app.
The potential conflict is a very common problem, which applies in many contexts: any application could use environment variables already used by other applications; for this reason, the environment variables are usually prefixed with the name of the application (eg NVM_HOME, JAVA_HOME). But this potential conflict is not a good reason to avoid using environment variables. The same in my opinion applies to npm params / npm_config env vars. The doc does not say anything about the risk of conflicts, implying I guess they should be managed as usual.
My preferred method is by using environment variables:
{
"scripts": {
"ncc-build": "ncc build $ACTION/src/index.ts -o $ACTION/dist",
"build:pr-changelog": "ACTION=pr-changelog npm run ncc-build",
}
}
It should work in UNIX systems. I'm not sure about windows platfrom compatibility though.
a different approach for doing this - to reach super deep into you dependency chain:
npm scripts section:
"test:local": "cross-env-shell UPDATE_BASELINE=false UPDATE_MODULE=%npm_config_vizdifsingle% run-p koa:ci wdio:local",
"test:remote": "cross-env-shell UPDATE_BASELINE=false UPDATE_MODULE=%npm_config_vizdifsingle% run-p localtunnel:start koa:ci wdio:remote"
by using crossenv and npm's value placement you can pass args to env.args
like this:
npm run test:local --vizdifsingle=some,value,or,values
it will be available to you in
process.env.npm_config_update_module