JavaScript
Node.js
CircleCI
lerna

CIでLerna publishするまで

絶対に忘れる自信があるので今のうちにメモっておく。

Lerna is 何

  • Lerna はmonorepoを管理するためのツール
  • Babelのように、単一レポジトリで複数のnpmパッケージを管理できる
  • レポジトリ内パッケージ間の依存関係をsimlinkにより解決してくれる(勝手に npm link してくれるイメージ)

やりたいこと

  1. 開発者がmasterへコード修正commit(PRのmergeなど)
  2. CIでテスト実行
  3. 開発者がリリース意思表示
  4. CIでリリース実行
    • lerna publish が実行されて、npmへpublish完了!

今回はCIサービスにはCircleCI(2.x)を選択。
特にCircleCIにこだわっているわけでもなく、workflow的な仕組みが備わっているCI Serviceであれば問題ないはず。WerckerCIとか。

準備

lerna publish は下記を逐次的に実行していく。

  1. リリースバージョンの決定(デフォルトでは、質問に答えることでインタラクティブに決定される)
  2. publishが必要なパッケージの選定
  3. lerna.json, publish対象パッケージのpackage.jsonのversion番号を書き換えて git commit
  4. 決定したバージョンで git tag 実行
  5. 対象パッケージを npm publish 実行
  6. git push origin master --tags 実行

lernaは、各個のコマンド呼び出しにはchild_process.execSync を叩いているだけなので、CIでも上記の個別コマンドが動くようになっていれば問題ない。

GitHub deploy key

CircleCIからGitHubへgit pushできるようにする必要がある。ここでは、Deploy key(SSH公開鍵認証)を使う。

下記コマンドで、パスフレーズ空の鍵ペアを生成。

ssh-keygen -t rsa -b 4096 -P "" -C "<GitHubのメアド>" -f ${HOME}/.ssh/gh_dep_rsa

秘密鍵(~/.ssh/gh_dep_rsa)をコピって、CircleCI設定画面の、Permissions -> SSH Permissions -> Add SSH keyから登録。

Project_settings_-_Quramy_reg-suit_-_CircleCI.png

公開鍵(~/.ssh/gh_dep_rsa.pub)をコピって、GitHubレポジトリの Setting -> Deploy keys -> Add deploy key に登録。"Allow write access" を忘れずに。

Deploy_keys.png

Deploy_keys_2.png

fingerprintをコピっておいて、CircleCIの設定ファイルに追記.

circleci/config.yml
    steps:
      - add-ssh-keys:
          fingerprints:
            # 上記でコピったfingerprintをここに貼り付け 
            - "a1:a2:a3:a4:a5:a6:a7:a8:a1:a2:a3:a4:a5:a6:a7:a8"

Git user config

地味に忘れがちなのがこれ。 package.jsonやらをcommitする際に必要になるので。

circleci/config.yml
    steps:
      - run:
          name: Setup git user
          command: |
            git config --global user.email "<メアド>"
            git config --global user.name "<ユーザー名>"

NPM token

npmにpublishするために必要。

ローカルで、npm adduserを実行してnpmにログインしておいてから、

~/.npmrc
//registry.npmjs.org/:_authToken=xxxxxx-yyyyyy-wwwwww-zzzzzz

_authToken=... の値をコピー。

Build settings -> Environment Variables -> Add variableを選択して、コピーした値を NPM_AUTH_TOKEN という名前で保存しておく。
これで、環境変数としてnpmの認証トークンを取り出せるようになったので、この値を使ってCI側でログインするようにしておく。

circleci/config.yml
      - run:
          name: Login npm
          command: |
            echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > ~/.npmrc
            npm whoami

なお、 npm whoami はログインの確認用。

実行

これで準備が整った。最後はlerna publishをstepに加えるだけだ。

circleci/config.yml
      - run:
          name: Publish
          command: |
            ./node_modules/.bin/lerna --cd-version="patch" --yes --registry="https://registry.npmjs.org/" publish

--cd-version="patch"--yes でリリースバージョンが自動的に決定されるようにしておく。
--registryhttps://github.com/lerna/lerna/issues/896 のworkaround。多分そのうち不要になるだろうけど、最初はコイツを忘れたお陰で、npm whoamiが正常終了なのに、lernaから実行される npm publish でauth errorとなって悲しい思いをした。