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リクエストを送信します。 adduser
を強制的に希望どおりに動作させる代わりに、cliを経由せずにレジストリに直接リクエストを行い、npm set
で認証トークンを設定できます。
ソースコードが示唆する 次のペイロードで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
ではなく、ユーザーの.npmrc
(ローカルと同様)のレジストリURLに追加する必要があります。これらは、私の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アプリケーションにも当てはまらないのかわかりません。
これは、Alexander 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}`);
});
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
パッケージを使用した私のハッキング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]"
}
}
}
1つの解決策は、トークンを取得して〜/ .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 で公開されたソリューション2の場合 duplicated post は機能しています。
マッシュアップ:
export NPM_USERNAME=mUs34
export NPM_PASSWORD=mypassW0rD
export [email protected]
npm adduser<<!
$NPM_USERNAME
$NPM_PASSWORD
$NPM_EMAIL
!