Reputation: 7585
I'm trying to automate npm publish
inside a Docker container, but I receive an error when the npm login
command tries to read the username and email:
npm login << EOF
username
password
email
EOF
It works in a Bash terminal, but in a container (without stdin
) it shows error:
Username: Password: npm ERR! cb() never called!
npm ERR! not ok code 0
According to npm-adduser:
The username, password, and email are read in from prompts.
How can I run npm login
without using stdin
?
Upvotes: 112
Views: 212457
Reputation: 4384
npm set "//<registry>/:_authToken=$TOKEN"
Example for Github Package Registry:
npm set "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN"
Example for NPM Package registry:
npm set "//registry.npmjs.org/:_authToken=$NPM_TOKEN"
This is the simplest solution that I have found.
Upvotes: 72
Reputation: 16544
This worked in one of my devops flows
echo -n 'myuser:mypassword' | openssl base64
Result will be something like : eWFob29vb2E=
npm config set registry https://nexus-acme.com/repository/npm-group/
npm config set _auth eWFob29vb2E=
That's all. You could run npm install, and your private modules will be downloaded.
~/.npmrc
Upvotes: 19
Reputation: 21
Had a similar problem with my continuous delivery pipeline on gitlab. After sleepless nights and a short weekend the following one and only command worked for me:
npm config set //registry.npmjs.org/:_authToken=${NPM_TOKEN}
This basically updates the .npmrc
in the user directory with the value of the token (and other values).
NPM_TOKEN
is a (secret) environment variable with a value of a created token from the npm site.
Hope, that anybody can save time with this information. The npm documentation was not the best friend in this case.
Upvotes: 2
Reputation: 1
Generally speaking, the use of _auth to pass in the base64 processing of username and password is good, I wrote a publishing tool to solve this problem, I hope to help you; https://www.npmjs.com/package/ausiliario
Upvotes: 0
Reputation: 1200
npm login
command stores all the credentials in the global .npmrc
file. The pattern is not similar and it changes. Explained below:
There are TWO patterns, either one should work. NOTE: There may be other patterns in which npm stores the auth data, hence it's always better to cross-check the content of the .npmrc
file in a global context.
Every time we do npm login
an entry is made in .npmrc
if it does not exist.
So the two pattern(I have copied the below lines from .npmrc)
//your_registry/:_authToken=amvasdfjkhjkjsdhflakjsdfhalskjh== //your_registry/:_authToken=NpmToken.6ca7867aba-d66a-32c0-9srr-fba908987d7987f
So the only thing to do is to copy the line from global .npmrc
and put it in local or project .npmrc
and run the npm publish
command from CI. Explicit npm login
is not required.
Upvotes: 6
Reputation: 11
i'm using gitlab-ci for this.
but my private npm response without authtoken, so that the npm-cli-login
can't run correctly.
i do a trick for my question, like this:
// If no entry for the auth token is found, add one
if (authWrite === -1) {
lines.push(args.registry.slice(args.registry.search(/\:\/\//, '') +
1) + '/:_authToken=' + (args.quotes ? '"' : '') + response.token + (args.quotes ? '"' : ''));
}
// DIY
var loginInfo = [
{pass: '_password'},
{user: 'username'},
{email: 'email'}
]
loginInfo.forEach(function(ele) {
var key = Object.keys(ele);
lines.push(args.registry.slice(args.registry.search(/\:\/\//, '') +
1) + '/:' + ele[key] + '=' + (args.quotes ? '"' : '') + args[key] + (args.quotes ? '"' : ''));
})
// DIYend
var toWrite = lines.filter(function (element) {
if (element === '') {
return false;
}
return true;
});
though it is foolish,but works
Upvotes: 1
Reputation: 249
npm login is an interactive method. So prefer using npm-cli-login login.
Follow the following steps:
1. npm install -g npm-cli-login
2. npm-cli-login login -u username -p password -e [email protected] -r http://registry.npmjs.org
3. npm publish src --registry=http://registry.npmjs.org
Here I want to publish the module to http://registry.npmjs.org and I have registered in it with my emailid([email protected]), username and password
Upvotes: 3
Reputation: 34001
Depends on jq
and three ENV vars set:
export NPM_REGISTRY_DOMAIN=
export NPM_REGISTRY_USER=
export NPM_REGISTRY_PASSWORD=
json="{\"name\": \""$NPM_REGISTRY_USER"\", \"password\": \""$NPM_REGISTRY_PASSWORD"\"}"
TOKEN=$(curl -s \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X PUT --data "$json" \
--user "$NPM_REGISTRY_USER":"$NPM_REGISTRY_PASSWORD" \
https://"$NPM_REGISTRY_DOMAIN"/-/user/org.couchdb.user:"$NPM_REGISTERY_USER" | \
jq -r '.token'
)
npm config set registry https://"$NPM_REGISTRY_DOMAIN"
npm set //"$NPM_REGISTRY_DOMAIN"/:_authToken "$TOKEN"
Based on the answer from https://stackoverflow.com/a/35831310/1663462
Upvotes: 3
Reputation: 179
npm-cli-login
allows you to log in to NPM without STDIN.
In order to install run:
npm install -g npm-cli-login
Example usage:
npm-cli-login -u Username -p Password -e [email protected] -r https://your-private-registry-link
Upvotes: 17
Reputation: 1211
One solution is to fetch the token and update the ~/.npmrc
export ARTIFACTORY_TOKEN=`curl --silent --show-error --fail -u $ARTIFACTORY_USERNAME:$ARTIFACTORY_API_KEY https://artifactory.my.io/artifactory/api/npm/auth | \
grep -oP '_auth[\s?]=[\s?]\K(.*)$'`
echo "@my:registry=https://artifactory.my.io/artifactory/api/npm/npm-release-local/" > ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:_auth=${ARTIFACTORY_TOKEN}" >> ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:email=${ARTIFACTORY_USERNAME}" >> ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:always-auth=true" >> ~/.npmrc
This prevents issues with @scope package retrieval from npmjs
Upvotes: 8
Reputation: 5183
TL;DR: Make an HTTP request directly to the registry:
TOKEN=$(curl -s \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X PUT --data '{"name": "username_here", "password": "password_here"}' \
http://your_registry/-/user/org.couchdb.user:username_here 2>&1 | grep -Po \
'(?<="token": ")[^"]*')
npm set registry "http://your_registry"
npm set //your_registry/:_authToken $TOKEN
Behind the scenes npm adduser
makes an HTTP request to the registry. Instead of forcing adduser
to behave the way you want, you could make the request directly to the registry without going through the cli and then set the auth token with npm set
.
The source code suggests that you could make a PUT request to http://your_registry/-/user/org.couchdb.user:your-username
with the following payload
{
name: username,
password: password
}
and that would create a new user in the registry.
Many thanks to @shawnzhu for having found a more cleaner approach to solve the problem.
Upvotes: 57
Reputation: 505
This builds on top of Alexander F's answer. This is just a simplified version of the code he provided, mashed up with the example code provided by npm-registry-client.
"use strict";
var RegClient = require('npm-registry-client')
var client = new RegClient()
var uri = "https://registry.npmjs.org/npm"
var params = {timeout: 1000}
var username = 'my.npm.username'
var password = 'myPassword'
var email = '[email protected]'
var params = {
auth: {
username,
password,
email
}
};
client.adduser(uri, params, function (error, data, raw, res) {
if(error) {
console.error(error);
return;
}
console.log(`Login succeeded`);
console.log(`data: ${JSON.stringify(data,null,2)}`);
console.log(`NPM access token: ${data.token}`);
});
Upvotes: 3
Reputation: 1003
Hard to believe that after all this time there is still no solution for npm login. Sure you can grab a token once and use it for all your CI needs, but what about the security implications of a never expiring token? And what if one day admins decide that tokens should expire?
Below is my hacky javascript solution using npm-registry-client
package. Just pass a json string argument and it will login and write an .npmrc
file into your current dir. To log out use npm logout
as usual.
var client = new (require('npm-registry-client'))({});
var std_in = JSON.parse(process.argv[2]);
if (std_in.uri === undefined) {
console.error('Must input registry uri!');
return;
}
// fix annoying trailing '/' thing in registry uri
if (std_in.uri[std_in.uri.length - 1] !== '/') {
std_in.uri = std_in.uri + '/';
}
if (std_in.scope === undefined) {
console.error('Must input scope!');
return;
//std_in.scope = '@my-scope'; // or add default scope of your own
}
if (std_in.scope[0] !== '@') {
std_in.scope = '@' + std_in.scope;
}
client.adduser(std_in.uri, std_in.params, function(err, data, raw, res) {
if (err) {
console.error(err);
return;
}
require('fs').writeFileSync('.npmrc', `${std_in.scope}:registry=${std_in.uri}\n//${(std_in.uri.split('//'))[1]}:_authToken=${data.token}`);
});
Example input:
{
"uri": "https://my-nmp.reg",
"scope": "@my-scope",
"params": {
"auth": {
"username": "secret-agent",
"password": "12345",
"email": "[email protected]"
}
}
}
Upvotes: 2
Reputation: 211
I took a slightly different approach that seems to work great still. To begin with, you will need an auth token. This is easily obtainable by locally running npm adduser
and then grabbing the generated token from your ~/.npmrc
located in your user folder. In order to be authenticated on your ci server this auth token needs to be appended to the registry URL in the user's .npmrc
(similar to how it was locally), not the .npmrc
located in the repo, so these worked great as script steps in my CI configuration
- echo "//<npm-registry>:8080/:_authToken=$AUTH_TOKEN" > ~/.npmrc
- npm publish
where AUTH_TOKEN is stored as a secret variable in your settings.
A good way to test this is to replace npm publish
with npm whoami
to test and make sure it successfully logged you in.
Here is my entire publish configuration
publish:
stage: deploy
only:
- tags
script:
- yarn run build
- echo "//<npm-registry>:8080/:_authToken=$NPME_AUTH_TOKEN" > ~/.npmrc
- npm publish
- echo 'Congrats on your publication!'
I'm using gitlab-ci but I don't see why this wouldn't apply to any ci application.
Upvotes: 15
Reputation: 2047
For the solution 2 exposed by ke_wa in this duplicated post has worked.
Mashup:
export NPM_USERNAME=mUs34
export NPM_PASSWORD=mypassW0rD
export [email protected]
npm adduser<<!
$NPM_USERNAME
$NPM_PASSWORD
$NPM_EMAIL
!
Upvotes: 1
Reputation: 3503
An expect script worked for me. You need to make sure expect is installed, this command should do it for ubuntu:
apt-get install expect-dev
Your script could look something like this (npm_login_expect):
#!/usr/bin/expect -f
# set our args into variables
set i 0; foreach n $argv {set "p[incr i]" $n}
set timeout 60
#npm login command, add whatever command-line args are necessary
spawn npm login
match_max 100000
expect "Username"
send "$p1\r"
expect "Password"
send "$p2\r"
expect "Email"
send "$p3\r"
expect {
timeout exit 1
eof
}
And then call it like this:
expect -f npm_login_expect myuser mypassword "[email protected]"
Upvotes: 14