Cloud Penguins

Flying penguins in the cloud.

Flowを自動でgit commitする仕組みを作ってみた話

Node-RED Advent Calenadarの14日目! 遅くなってすみません。 今回は、Node-REDのフローを自動でgit管理する仕組みを作ってみた話です。

そう、Node-RED LT祭でデモしたアレです。結局記事に出来ていなかったので、今回の記事ネタにしてしまおうと思ってしまった次第。

きっかけ

Node-REDはGUIでガシガシFlowを作っていけるところがウリなのですが、過去のFlowに戻す方法がなくて困ったことが何度かありました。 ブラウザを閉じるまでは、Ctrl+zでUndoできるので、数手前までは戻すことができます。が、ブラウザを閉じてしまうともう戻せなくなってしまいますし、そうでなくてもだいぶ前のFlowの状態に戻すというのは、今のNode-REDでは難しいです。 いい手を思い付いたと思ってガシガシFlowを変更してみたはいいが、実は前のヤツのほうが良かった・・・という時に、何らかの方法で戻す方法が欲しい。

もちろん、手を加える前にJSONでexportしておけばよいのですが、ものぐさな自分にとってはちょっとそれが面倒くさい。

というわけで、試しに自動で変更をgit commitする仕組みを作ってみました。

しくみ

Node-REDのFlowは、userDirの下にJSONで保存されています。Node-RED上でDeployするたびに、このJSONファイルが更新される仕組みです。 であれば、このJSONファイルが更新される度にgit commitすれば、過去の変更をgitで管理できるのではないか、と。

そこで、今回はGruntを使って自動化することにしました。

GulpではなくGruntを使った理由は、Node-REDのpackage.jsonで元々Gruntが含まれている (Node-RED本体の開発用)からです。Gulpを使っても同様のことは可能だと思われます。

次に、JSONファイルのwatchにはgrunt-contrib-watchを利用。これもNode-REDのpackage.jsonに含まれています。 Gitの操作はgrunt-gitを利用。

userDirはデフォルトだとNode-REDのインストーディレクトリになりますが、今回はconfigディレクトリを作成し、その中にJSONが作られるように設定しました。

userDir: 'config'

Gruntfile

Gruntfileは、こんな感じになりました。 リポジトリの指定やファイル名の指定はもうちょっと上手いやり方があるような気がします。

せめて相対パスで書ければもう少しスッキリするはずなんですが、相対パスで書くと何故かgrunt-gitが意図したとおりに動作してくれないため、現時点では絶対パスで指定しています。

使い方

使い方は、Node-REDを起動した後、grunt watchコマンドを実行してJSONファイルのwatchをするだけです。

Node-RED上でFlowを編集し、Deployするとgrunt側ではこのような表示になります

>> File "config/king.json" changed.
Running "gitcommit:task" (gitcommit) task

Done, without errors.
Completed in 0.943s at Tue Dec 15 2015 21:13:51 GMT+0900 (JST) - Waiting...

git logしてみると、このようにコミットが積まれていることが分かります

$ git log
commit 310db8be68829a7f47937a5d5c6cfb41ecb5b5f2
Author: Kazuto Kusama 
Date:   Tue Dec 15 21:13:51 2015 +0900

    2015-12-15T21:13:51+09:00

developからmasterへのマージ

デフォルトでは、developブランチにコミットを積むようになっています。

$ git log --graph --decorate --pretty=oneline --abbrev-commit --all
* d90cf6e (HEAD, develop) 2015-12-15T21:18:05+09:00
* 310db8b (master) 2015-12-15T21:13:51+09:00

developブランチで開発をすすめ、良い感じになってきたらmasterにマージするという、よくあるフローも今回取り入れてみました。 今回作ったGruntfileでは、versionという名前のファイルもwatchしています。

このversionファイルが更新されると

  • versionファイルの数字を読み取り
  • developブランチをmasterブランチにmerge
  • versionファイル内の数字でtag付け

という作業を行います。 versionファイルの更新は、Node-RED上でInject Nodeを押すだけで行われるようにしました。

Node-RED___10_9_8_171

ボタンを押すと、以下のようになります。masterとdevelopが同じIDになり、v2タグが降られていることが分かります

$ git log --graph --decorate --pretty=oneline --abbrev-commit --all
* 4067c47 (HEAD, tag: v2, master, develop) 2015-12-15T21:22:51+09:00