我正在尝试在Docker容器中自动化npm publish
,但是当npm login
命令尝试从提示中读取用户名和电子邮件时我遇到了麻烦:
npm login << EOF
username
password
email
EOF
它在Bash终端中工作,但不在没有stdin打开的容器中工作,并显示以下错误消息:
Username: Password: npm ERR! cb() never called!
npm ERR! not ok code 0
据npm-adduser说:
用户名,密码和电子邮件将从提示中读入。
那么如何在没有stdin打开的情况下运行npm login
?
TL; DR:直接向注册表发出HTTP请求:
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
在幕后,npm adduser
向注册表发出HTTP请求。您可以直接向注册表发出请求,而无需通过cli,然后使用adduser
设置身份验证令牌,而不是强制npm set
按您希望的方式运行。
The source code suggests你可以用以下有效载荷向http://your_registry/-/user/org.couchdb.user:your-username
发出PUT请求
{
name: username,
password: password
}
这将在注册表中创建一个新用户。
非常感谢@shawnzhu找到了更清洁的方法来解决问题。
期望脚本对我有用。你需要确保安装了expect,这个命令应该为ubuntu做:
apt-get install expect-dev
你的脚本看起来像这样(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
}
然后像这样调用它:
expect -f npm_login_expect myuser mypassword "[email protected]"
我采取了一种略微不同的方法,似乎仍然很好用。首先,您需要一个身份验证令牌。这很容易通过本地运行npm adduser
然后从位于用户文件夹中的~/.npmrc
中获取生成的令牌来获得。为了在你的ci服务器上进行身份验证,这个身份验证令牌需要附加到用户的.npmrc
中的注册表URL(类似于本地的注册表URL),而不是位于repo中的.npmrc
,所以这些在我的脚本步骤中很有用。 CI配置
- echo "//<npm-registry>:8080/:_authToken=$AUTH_TOKEN" > ~/.npmrc
- npm publish
其中AUTH_TOKEN在您的设置中存储为秘密变量。测试这个的一个好方法是用npm publish
替换npm whoami
来测试并确保它成功登录了你。
这是我的整个发布配置
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!'
我正在使用gitlab-ci,但我不明白为什么这不适用于任何ci应用程序。
npm-cli-login允许您在没有STDIN的情况下登录NPM。
为了安装运行
npm install -g npm-cli-login
示例用法: -
npm-cli-login -u用户名-p密码-e [email protected] -r https://your-private-registry-link
难以置信,毕竟这段时间仍然没有针对npm登录的解决方案。当然,您可以获取一次令牌并将其用于满足您的所有CI需求,但是永不过期的令牌的安全含义又如何呢?如果有一天管理员决定令牌应该到期怎么办?
下面是我使用npm-registry-client
包的hacky javascript解决方案。只需传递一个json字符串参数,它就会登录并将.npmrc
文件写入当前目录。要像往常一样注销使用npm logout
。
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}`);
});
输入示例:
{
"uri": "https://my-nmp.reg",
"scope": "@my-scope",
"params": {
"auth": {
"username": "secret-agent",
"password": "12345",
"email": "[email protected]"
}
}
}
这是建立在亚历山大F的答案之上的。这只是他提供的代码的简化版本,与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}`);
});
一种解决方案是获取令牌并更新〜/ .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
这可以防止从npmjs检索@scope包的问题
您可以使用expect脚本,也可以编写使用pty.js的节点脚本。
对于ke_wa在这个duplicated post暴露的解决方案2已经奏效。
混搭:
export NPM_USERNAME=mUs34
export NPM_PASSWORD=mypassW0rD
export [email protected]
npm adduser<<!
$NPM_USERNAME
$NPM_PASSWORD
$NPM_EMAIL
!