出口 (@dex1t) です。
現在開発中のサービスでは、Railsを使いつつ、React.jsを導入しています。
React.jsを使うと必然的にBrowserifyなどのnpmのエコシステムを、Railsプロジェクトに取り入れることになります。
そうすると、Railsプロジェクトであっても、npmで管理するライブラリが増えていきます。今回はそのアップデートを自動化してみました。
CircleCIで Gemfile.lock を定期更新する
本題に入る前に、bundle update
の自動化について触れます。
ググると、やり方はいろいろ出てくるのですが、
- 開発用のサーバからcronで定期的にCircleCIのAPIを叩く
circle.yml
のdeploymentセクションで、スクリプトを実行する- そのスクリプト内で、
bundle update
の実行と差分をプルリクエストする
というのが、基本的な流れです。詳しくは、 CircleCIを使ってbundle updateを定期実行する - Qiita をごらんください。
CircleCIで package.json を定期更新する
npmのpackage.jsonを定期更新する場合も、上記の流れと同様です。 今回は、3を行うスクリプトをgulpで組んでみました。
npm-check-updates
でpackage.jsonを更新する
package.jsonの更新には、npm-check-updates を利用します。
$ npm install -g npm-check-updates $ ncu --upgradeAll
これだけで、npmパッケージの更新確認とpackage.jsonの書き換えを行ってくれます。便利!!
今回はこれをgulpから呼び出します。
package.jsonを更新してプルリクエストする
gulpからgitとgithubが扱えれば何でもいいのですが、今回は主に以下を使いました。
run-sequenceは、各gulpタスクを直列に実行するために使います。 また、gulpプラグインの読み込みを簡単にするため、gulp-load-pluginsも使っています。
これら組み合わせると、ちょっと長いですがこんな感じで、package.jsonの更新~プルリクができます。
var gulp = require('gulp'); var gulpLoadPlugins = require('gulp-load-plugins'); var $ = gulpLoadPlugins(); var ncu = require('npm-check-updates'); var github = require('octonode'); var branch = 'npm-update'; var runSequence = require('run-sequence'); gulp.task('ncu', function(cb) { ncu.run({ packageFile: 'package.json', jsonUpgraded: false, upgradeAll: true }).then(function(){ cb(); }); }); gulp.task('createBranch', function(cb) { $.git.checkout(branch, {args:'-b'}, function(){ cb(); }); }); gulp.task('addAndCommit', function() { return gulp.src('package.json') .pipe($.git.add()) .pipe($.git.commit('Upgrade package.json')); }); gulp.task('pushBranch', function(cb) { $.git.push('origin', branch, function(){ cb(); }); }); gulp.task('sendPullRequest', function(cb) { var token = process.env.GITHUB_ACCESS_TOKEN; github.client(token).repo('bitjourney/journey').pr({ 'title': 'Update npm packages', 'body' : '@bitjourney/developers Please :eyes:', 'head' : 'bitjourney:' + branch, 'base': 'master' }, function() { cb(); }); }); gulp.task('autoNpmUpdate', function(){ runSequence(['ncu', 'createBranch'], 'addAndCommit', 'pushBranch', 'sendPullRequest'); });
注意点としては、プルリクエストを送るユーザの、GithubのPersonal access tokenをCircleCIに登録しておく必要があります。
CircleCI側のEnvironment variablesにて、GITHUB_ACCESS_TOKEN
という名前で登録しておけばOKです。
circle.ymlのdeploymentセクションで実行する
あとは、circle.ymlのdeploymentセクションで、gulp autoNpmUpdate
を実行するようにすればOKです。
参考までに、以下のようにしました。
deployment: maintain-libraries: branch: master commands: - > if [ -n "${NPM_UPDATE}" ] ; then git config --global user.email user@example.com git config --global user.name 'username' gulp autoNpmUpdate fi
git config
もgulp内でやってしまってもいいのですが、今回は外出ししています。
実際にCircle CIをAPI経由で叩く方法については、こちらを参考にしてください!
おわり
要点だけかいつまみましたが、これで弊社のbotがプルリクをくれるようになりました 🎉