LoginSignup
8
5

More than 5 years have passed since last update.

Werckerでnpm-scriptsが実行できなくなったときは

Last updated at Posted at 2016-12-18

@Quramy です。

「アドカレやろうぜ」とか言い出した割には書くネタが全く思い付かないので、少し前に Wercker でドはまりした話を書きます。

Node.js でフロントエンドの開発をしていると、npm-scriptsにタスクを定義しておき、npm testnpm run deploy のように利用することは多いと思います。

package.json
  "scripts": {
    "test": "mocha",
    "deploy": "webpack && gh-pages -d dist"
  },
  "devDependencies": {
    "gh-pages": "^0.12.0",
    "mocha": "^3.2.0",
    "webpack": "2.2.0-rc.1",
    ...
  },

npm run では、./node_modules/.bin にPATHが通るので、ローカルにnpm iした mockaやwebpackのコマンドが使えるというアレです。

折角定義したタスクはCIでも利用したいのが人情です。Wercker の場合、次のようにyamlの script 部分に指定するだけです。

wercker.yml
box: node:6.9

test:
  steps:
    - npm-install

    - script:
      name: test
      code: npm test

deploy:
  steps:
    - script:
      name: deploy
      code: npm run deploy

ところが、上記yamlのように testdeploy というように複数のpipelineに分割していると、問題が発生します。
2つめ以降のpipelineでnpm-scriptsが正常に機能しないのです。

より正確には、npm-scriptsに記述している webpack のようなコマンドが正しく動きません。ls -la node_modules/.bin で確認してみると分かるのですが、node_modules/.bin配下のsymbolic linkが壊れてしまっているのです。

lrwxr-xr-x 1 root root 0 12 19 00:48 gh-pages
lrwxr-xr-x 1 root root 0 12 19 00:48 mocha
lrwxr-xr-x 1 root root 0 12 19 00:48 webpack

上記のような状態になります。各コマンドの実行権限は残っているので、音もなくreturn code 0で終了するという状態になります。

symlinkが正常な状態であれば /.bin配下から各パッケージのコマンドへlinkが参照できるはずです。

lrwxr-xr-x 1 root root 18 12 19 00:48 mocha -> ../mocha/bin/mocha

werckerでは、各pipelineの最後にstoreというstepが実行されます。store stepで、プロジェクトルート配下をまるごと一時的にコピーし、次のpipelineではコピーした内容を復旧してからユーザー定義のstepが開始されます。
Werckerは1つのpipelineにつき、1つのcontainer を起動するため、pipelineを分けると別containerでの実行となるため、このような機構があるのでしょう。そして (何故かは分かりませんが) werckerのstore/restoreの過程でsymlinksが破壊されてしまいます。

storeする際にsymlinkが破壊されるのであれば、それは復旧すれば良いじゃない、ということで werckerのstepを作ってみました。 wacul/store-link

wercker.yml
box: node:6.9

test:
  steps:
    - npm-install

    - script:
      name: test
      code: npm test

    - wacul/store-link:
      type: store
      prefix: node_modules/.bin

deploy:
  steps:
    - wacul/store-link:
      type: restore
      prefix: node_modules/.bin

    - script:
      name: deploy
      code: npm run deploy

指定したディレクトリのsymlink情報を引っこ抜いて保持しておき、restoreに再度 ln -s するstepです。上記のように、pipelineの最後にlinkをstoreし、他のpipelineの先頭でrestoreして使います。

よくよく考えたら、 node_modules/.bin であれば、npm rebuild を叩けば復旧できるんじゃないか、という事に気づいたのは、このstepを作ってしまってからです。
こいつの場合 node_modules に限らず、simlink全般に対して汎用的に使えるので、全くの無意味だったわけではないですが。

もし似たような問題で悩んでいる人がいたら、お試しください。それでは、また。

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5