Is there any way to add environment variables to a npm package and modify it in azure build pipeline? - npm

I've created one npm package which accesses few API's running in the backend. The URL to access those api's are hardcoded in the package. Most of the times we need to change the URL to point to some another api (different version pointing different database). And we end up editing the code and update the URL and re-publish the npm package.
Our npm package code is in a private git repo. We are creating a pipeline which will auto-publish the package on check-in. We want to add the URL's as build variables which will be fetched during build pipeline and will be added as part of npm package before publishing.
Is there any way to do so? If yes what changes needs to be done in the azure pipeline process and in the actual code?

As what you said, you store your npm package code in Repos. Here I think the Replace Token task can for you to achieve replacing the URL from variable into your code.
To use that task:
(1). you need firstly store URLs into variables. For example, create one variable names A and input the value.
(2). Then follow that task syntax(#{****}#) to modify your code.
Go the script where you want it to be replaced with the variables
value. Modify it as #{A}# . (Here please make sure the **** value
is same with the relevant variables name you configured before.)
Thus the corresponding location can be replaced by the variables
value automatically during the build.
For detailed steps, you can refer my previous answer which has the similar demands.
Another things you need pay attention to is (3). add this Replace token task before your package publish step. After you check in the code and trigger the build, it will firstly override the source code by replacing the variable value into script. Then the next publish step could pack and publish a completed source files with these changed codes.

Related

How to get the version of a remote npm package using a bin script

I'm trying to set up an npx script to create a template project.
In package.json I have:
"bin": {
"init": "bin/init"
}
In the init script I'm using tag='v'$(npm pkg get version | tr -d '"') to get the version of the package. I then use git clone --depth 1 --branch $tag https://github.com/matriarx/typescript.git to clone that specific repository for that specific tag.
When I do yarn link and try use it locally, from within that specific project, it works because it's able to correctly pick up the package.json version. So the above only works if it's run inside an existing project. However that's not what I want to do.
I want to enable someone to run it even if they have nothing locally, by simply doing npx #matriarx/typescript init and it should create the new project by cloning it. More than that I want them to be able to clone any specific version by using npx #matriarx/typescript#0.0.1 init in order to clone a specific version.
However it seems that anything I try is only able to get the version from a local package.json that already exists.
I could just clone the current existing repository without specifying any tag, but that would defeat the point of having releases, then it would just clone any current code completely disregarding the release. So it has to clone the tagged release.
How can I get the remote package version stored on npm from the bin script without having anything locally before hand?
Alternatively is there a better way to do what I'm trying to do?
EDIT: I ended up just hardcoding the version in the script, which works but it sucks because it's tedious to have to update it every time I bump the version. Though for now I still don't know a better way to do it.
After some more time messing around I figured out there is a standard way of doing it, at least since npm 7.
If you have a project like example then you can create a completely separate project called create-example with a bin script.
When you use npm init example, npm will automatically search for a package prefixed with "create-" and execute its main bin script. So when running npm init example it will search for that create-example package and execute the bin script, which will install the example package.
This is how most of the bigger packages like react and next do it.
This approach comes with some disadvantages that I really don't like, for example it will show the incorrect dependencies on npm and it will cause you to have to maintain multiple projects and semvers on different projects. However it will also allow you to create a clean separation between the actual project and the installation of that project.
For some projects it might also make a lot more sense. For example if you have a project that doesn't have a package.json at all and you want to create a setup for it, it wouldn't make sense to create an npm package inside that project just for that. Instead you can create a separate "create-project" package just to set it up and keep npm out of the actual project. In other words it gives you a neat way to create bin scripts for a completely separate project that doesn't have anything to do with npm.
You could also just have created a normal shell script and execute it using curl but I guess npm just gives you another way to do it.
You still have to hardcode the version in that "create-project" package, I still have not seen a way to automatically determine the version from a remote package. The only way I've managed to do that is to completely download the package, get the version, then delete it, but that would be terrible for people with a slower internet connection or limited data.

Using Cro run for rebuilding changed client side files

cro run stops the server, recompiles, restarts the server when anything in the directory tree changes. That's great.
But when developing the client side UI, and using NPX/yarn/webpack, there is an additional step that is needed to produce the main.js file.
In the Cro tutorial this step seems to be done manually, viz., we have the line "And there we have it. npm run build, refresh, and give it a spin." Here npm run build is a command that has to be run 'manually'.
Is there a simple way, eg., using .cro.yml to force another command when changes in a sub-directory tree are detected? Eg, if the client side UI files are under path/to/cro-app/client-ui-directory and the command to be run if any files change is path/to/cro-app/client-ui/directory/yarn build
The cro-tools repo has all the file watching code associated with cro run.
So, one way would be to subclass the appropriate stuff in that repo and make a super-cro run command.
But I think the thing to do would be to set up a file watcher and trigger the rebuild in your server process. Cro files set environment variables, so you could use them to configure this behavior.

Using auth tokens in .npmrc

I have a project where we use font awesome 5 library. I followed the instructions that are written here and added an .npmrc file with my auth token.
Is this a safe behaviour to put this in a repo? I want the devs to have access to it, but if the repo goes public we might be exposing the token.
What is the best practice in situation like this?
UPDATE 2021-05-02
This answer remains questionable - see the comments below. I no longer have access to a private ($paid) npm account anymore, so I can no longer test to answer questions.
Perhaps try #konyak's answer.
It is definitely NOT a safe behavior to put the token in any git checked file, including .npmrc.
Below are the steps your team can take to safely leverage your npm token.
There are two different environments to consider:
each developer's local dev machine
the app's deployment platform
local dev
Following the Global Set Up instructions you linked to in your question, is not the solution.
Create the .npmrc file similar to the "Per project" instructions, but substitute your real token with a variable name, prefixed by $. ie:
#fontawesome:registry=https://npm.fontawesome.com/
//npm.fontawesome.com/:_authToken=$TOKEN
npm will detect an environment variables file named .env. So, in a .gitignored .env file, add your secret key value pair, ie:
TOKEN=ABC123
You can also prefix the variable name with "NPM_CONFIG_", according to the npm-config docs, ie:
NPM_CONFIG_TOKEN=ABC123
Now, when the dev runs npm i, font-awesome dependencies will load from the private repo.
NOTE: Don't follow the current npm-config docs about the environment variables syntax! See this stack overflow answer, ie:
👎 BAD npm-config ENVIRONMENT VAR SYNTAX 👎
${TOKEN}
👍 GOOD npm-config ENVIRONMENT VAR SYNTAX 👍
$TOKEN
app deployment platform
Do all the steps from the local dev section above, PLUS:
create an environment variable on the platform with the same name as in the .npmrc file.
If your app host is Netlify, see their Build Environment Variables docs.
https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow
Export your secret token into your session, e.g., export NPM_TOKEN="00000000-0000-0000-0000-000000000000"
Inside your ~/.npmrc, add //registry.npmjs.org/:_authToken=${NPM_TOKEN}
I put the relevant config line, with the token in plaintext, in a .npmrc file in my home directory. You can then use filesystem / OS permissions to protect it, avoid accidentally checking it in to source control, and NPM will read it automatically with no further action on your part.
In the project directory, we have .npmrc with a scoped registry declaration only (#fontawesome:registry=https://npm.fontawesome.com/), and a separate ci.npmrc which has that plus the variable-substitution authToken assignment:
#fontawesome:registry=https://npm.fontawesome.com/
//npm.fontawesome.com/:_authToken=$FONTAWESOME_NPM_TOKEN
The CI build job just has to replace .npmrc with ci.npmrc before doing anything with npm, and set a secret environment variable with an auth token assigned to the appropriate service account.

Extracting MSDeploy Zip package using variables

I’m setting up an automated build in VSTS that will FTP the published files to my server.
I have this working but the way I’ve achieved it, I feel is hacky and non-sustainable.
the process as you can see from the screenshots will publish the artefact which consists of a readme, cmd file and a zip containing all my publish files and then I extract the ZIP with the very explicit location below.
$(Build.ArtifactStagingDirectory)\temp\Content\d_C\a\1\s\IntermittentBug\IntermittentBug\obj\Release_EukHosts\Package\PackageTmp
I’m using a hosted build server in VSTS but as the path contains
d_C\a\1\s\
I assume this will change in time. What I need is a variable to cater for this path so it will always succeed.
How can I update this to make it more efficient and sustainable?
First, as jessehouwing said that the variable is called Build.SourcesDirectory.
Regarding the path structure, the simple way is specifying /p:PackageTempRootDir="" msbuild argument in Visual Studio Build task to remove the source path structure, then the path will be like Content\D_C\PackageTmp.
On the other hand, you also can publish the web app through File System mode.
This variable is caught in a predefined variable called Build.SourcesDirectory. see the complete list of predefined variables here.
In your batch or powershell scripts this variable is available as a environment variable called %BUILD_SOURCESDIRECTORY% / $env:BUILD_SOURCESDIRECTORY.

Is it possible to automatically insert version number in code using bazaar?

I am currently working with a coding project using the bzr (bazaar) source code management software. I would like to include the version number in the file code of my project
So that I could call the variable "VERSION" and echo out my current working version.
Within the code be able to do this:
var VERSION = ###;
Where ### is the current version number. Is this possible? or do I have to inspect the bzr info on a file and increment my version manually prior to committing new code?
The only solution I know is the Keyword plugin for Bazaar:
http://doc.bazaar.canonical.com/plugins/en/keywords-plugin.html
(This points to https://launchpad.net/bzr-keywords but the first link has more explanation).
Steps:
Get the plugin
bzr branch lp:bzr-keywords
Install plugin (basically copy it in bazaar plugins install folder)
Get the help
bzr help keywords
Once installed, commit your code with the keywords inside, it will be replaced.
Another option is to invoke the 'bzr version-info' command, which can output the version number in various convenient ways.