
NodeJSには便利なNPMというパッケージ管理ツールがあります。今回は、NodeJSで自作のコマンドラインツールを作り、Travis CI経由で自動でテストしてからNPMに公開する方法を紹介します。
はじめに
NodeJSにはNPMというパッケージ管理の仕組みがあります。この仕組みを使うことでJavaScriptで書かれた便利なライブラリやコマンドラインツールを誰でも簡単に利用することができます。
今回は、NodeJSで自作のコマンドラインツールを作成しNPMに公開するのはもちろん、Travis CIを使って自動でテストして、自動でNPMに公開するまでの方法を紹介します。
前提
以下の準備が完了している必要があります。
- GitHubのアカウントがある
- NPMのアカウントがある
- Travis CIのアカウントがある
- NodeJSがインストールされている
細かいバージョンは「環境」を確認してください。
NodeJSでコマンドラインツールを作る
まずは公開するコマンドラインツールを作りましょう。
NPMで検索してパッケージ名を決める
NPMでパッケージを公開する場合、パッケージ名は一意である必要があります。NPMのサイトに行って、検索窓から自分が作りたい名前を検索して被っていないことを確認します。
後述しますが、ここで決めるのはあくまでパッケージ名(GitHubにおけるリポジトリ名)であって、コマンドラインツールのコマンド名ではありません。コマンド名は後で決めれますし、NPM上で被っていてもエラーにはなりません。
GitHubでプロジェクトを作る
NPMで公開する予定のパッケージ名でGitHubのリポジトリを作成します。今回は仮に「hello-simple-cli」とします。
簡単なコマンドラインツールを実装する
GitHubからプロジェクトをクローンして、コマンドラインツールを作成します。
$ git clone https://github.com/{your-github-account}/hello-simple-cli.git
$ cd hello-cli/
$ npm init -y
$ npm i -D jest
$ mkdir src
$ touch src/index.js
$ chmod +x src/index.js # 必要であれば
$ touch src/utils.js
$ mkdir test
$ touch test/utils.spec.js
package.json
package.jsonにコマンドラインツール用の設定と、開発用のスクリプトを追加します。具体的には「main」を削除して「bin」を追加します。versionはひとまず「0.1.0」にしておきます。
{
"name": "hello-simple-cli",
"version": "0.1.0",
"description": "Hello Simple CLI",
"bin": {
"hello": "src/index.js"
},
"scripts": {
"start": "src/index.js",
"test": "jest"
},
"keywords": [],
"author": "You",
"license": "MIT",
"devDependencies": {
"jest": "^23.6.0"
}
}
この「bin」に指定したプロパティ名がコマンドラインツールのコマンド名になります。今回は「hello」というコマンド名にします。
utils.js
名前を渡すと挨拶のメッセージを返してくれるだけの関数を作ります。
module.exports.createHelloMessage = firstName => {
return `Hello ${firstName}!`;
}
utils.spec.js
関数のテストを簡単に書きます。
const { createHelloMessage } = require('../src/utils');
describe('utils test', () => {
describe('createHelloMessage function test', () => {
test('should return a correct message', () => {
const firstName = 'Keid';
const result = createHelloMessage(firstName);
expect(result).toBe('Hello Keid!');
});
});
});
テストが通ることを確認します。
$ npm test
> hello-simple-cli@0.1.0 test /Users/you/hello-simple-cli
> jest
PASS test/utils.spec.js
utils test
createHelloMessage function test
✓ should return a correct message (3ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.033s
Ran all test suites.
OKですね。
index.js
コマンドラインからの引数で名前を受け取って実行するだけのコマンドラインを作ります。ファイルの最初に「#!/usr/bin/env node」を追加する必要があります。
#!/usr/bin/env node
const { createHelloMessage } = require('./utils');
const firstName = process.argv[2];
if(!firstName) {
return console.error('A firstName is required as the first argument.');
}
console.log(createHelloMessage(firstName));
コマンドラインから実行してみます。
$ npm start
...
A firstName is required as the first argument.
$ npm start Keid
...
Hello Keid!
OKですね。NPMに公開して、NPM経由でダウンロードして使う場合、この「npm start」の部分が「bin」で指定したコマンド名(今回は「hello」)に置き換わります。
これで、簡単ではありますが、実装は完了です。
.npmignoreを設定する
NPMに公開したくないフォルダやファイルを「.npmignore」で指定します。
$ touch .npmignore
テストのソースコードはコマンドラインツールのユーザには不要なのでtestフォルダを指定します。
test/
NPMに公開する
ここでひとまず手動でNPMに公開してみましょう。
プロジェクトをGitコマンドでGitHubにPushして、NPMコマンドでNPMにログインして公開します。
$ git add .
$ git commit -m "Add awesome feature"
$ git push origin master
$ npm login
$ npm publish
NPMの公開に成功していれば、NPMを経由して、自作のコマンドラインが利用可能になっています。
$ npm i -g hello-simple-cli
$ hello Keid
Hello Keid!
自作のコマンドラインツールが完成しました!
Travis CIで自動でテストしてNPMに公開する
ここからTravis CIを使ってテスト実行とNPM公開を自動化します。
Travis CIとGitHubのリポジトリを連携する
Tracis CIの画面から連携したいGitHubのリポジトリ(今回は「hello-simple-cli」)を選択して、連携します。
Travis CIのファイルを準備する
プロジェクトにTracis CIの設定ファイルを作成します。
$ touch .travis.yml
Travis CI経由で自動テストする
Travis CIの設定ファイルにNodeJSで実行できるようにします。
language: node_js
node_js:
- "10"
これで、GitHubにPushするとNodeJSのバージョン10で環境が作成され、「npm test」のスクリプトが自動実行されます。詳しくは公式ドキュメントを参照してください。
$ git add .
$ git commit -m 'Add travis yaml'
$ git push origin master
Travis CIの画面で以下のようにグリーンになっていれば自動テストは成功しています。(参考として別プロジェクトのキャプチャを掲載しています)
NPMのAPIトークンを取得する
次にNPMへ公開する作業を自動化します。そのためにNPMをプログラムから実行するためのAPIトークンを取得します。
NPMのTokensのページから「Create New Token」をクリックします。
「Read and Publish」を選択して、「Create Token」をクリックします。
作成されたAPIトークンをメモしておきます。
Travis CIにNPMのAPIトークンを設定する
Travis CIの対象のプロジェクト(今回は「hello-simple-cli」)の環境変数の設定画面から「NPM_TOKEN」という名前で先程のNPMのAPIトークンを登録します。
注意点として「Display value in build log」のところはデフォルトのままオフにしておきましょう。そうしないとパブリックなTravis CIのログにAPIトークンが漏洩してしまいます。
Travis CI経由で自動テスト後にNPMに自動で公開する
準備が整ったので、Travis CIの設定ファイルを編集しましょう。
language: node_js
node_js:
- "10"
deploy:
provider: npm
email: "{your-npm-email-address}"
api_key: "$NPM_TOKEN"
on:
tags: true
after_deploy:
- test ! -e /home/travis/.npm/_logs ; TRAVIS_TEST_RESULT=$?
{your-npm-email-address}の部分は自分のNPMの公開メールアドレスに変更してください。もし書きたくなければ、先程のAPIトークンと同じようにTravis CIの環境変数の設定画面から環境変数として登録しておけば隠せます。(とはいえ、そもそもNPMには公開用のメールアドレスが必要なのでその必要性があるかは微妙です)
GitHubのリポジトリにタグをPushするとデプロイが実行されるように設定しています。
また、今回は一工夫しています。Travis CIでは自動テストの成功や失敗は確認するのですが、デプロイの成功や失敗に関しては見ていません。そのため、デプロイが失敗してもTravis CIのビルドは成功してしまうという問題があります。そこで、今回はNPMコマンドが失敗した場合にデバッグログが特定のフォルダに出力されることを利用して、そのフォルダが無ければ成功、あれば失敗という定義でデプロイの失敗を検知するようにしています。Travis CIのデフォルトの動作のまま(デプロイの失敗は検知されない)で良ければ「after_deploy」の箇所は削除してください。
TravisのNPM設定はこちら、Travisの環境変数はこちらに公式ドキュメントがあります。
では、NPMパッケージをGitHubへのPushだけで自動的にNPMに公開されるか確認しましょう。
$ git add .
$ git commi -m "Edit travis yaml"
$ git push origin master
$ npm version patch
v0.1.1
$ git push origin master
$ git push origin v0.1.1
これでTravis CIの画面でグリーンになれば、NPMに新しいバージョン(今回はv0.1.0 -> v0.1.1に変更)で自動的にパッケージが公開されます。
ポイントとしては、NPMにパッケージを公開する時の条件として、「package.json」の「version」が上がっている必要がある点です。「npm version」コマンドを使うことで、Gitのタグを作ると同時に「package.json」の「version」も変更してコミットされます。なので、手動で「package.json」の「version」を変更してコミットし、Gitのタグを付ける、という操作が不要になり、便利です。(また、補足として「diet-tag」という方法もあります。)
おまけ(Gitのタグコマンド復習)
最後に、Gitのタグを扱うコマンドを簡単に復習しましょう。
Gitのタグを追加してコミットする
$ git tag v1.0.0
または
$ git tag -a v1.0.0 -m "Release version"
GitのタグをPushする
$ git push origin v1.0.0
または
$ git push --tags
Gitのタグを表示する
$ git tag
v0.1.0
v0.1.1
v1.0.0
Gitのタグを削除してPushする
$ git tag -d v1.0.0
$ git push origin :v1.0.0
または
$ git tag -d v1.0.0
$ git push --delete origin v1.0.0
これでGitのタグも問題なしですね。
最後に
いかがでしたか?これで、自作の好きなコマンドラインツールを作っていつでも簡単にNPMで公開できるようになったのではないでしょうか。思いの外、痒いところに手が届くようなツールというのは無かったりするので、自作して公開すると世界中のエンジニアがあなたに感謝するかもしれませんよ。それでは。
環境
- NPM: 6.4.1
- NodeJS: v10.12.0


コメントを残す