Unyablog.

のにれんのブログ

YAML から JSON に変換するツールを Nim で書き、GitHub Actions でリリースする

最近 config が YAML になっているアプリケーションが多い。ただ、自分は YAML の読み書きが苦手である。

設定を書くには機能が多すぎるのと、(config なので)ネストしやすいのにインデントが関わってくるのが苦手なのだと思う。

何度かハマった結果、これからは JSON に変換して読むことにした。JSON を読むのには慣れているし、jq など色付・抽出するツールも持っているので最高 *1

YAMLJSON に変換するツールは世の中に多くあるが、そんなに大変じゃないので自分で作ることにした*2

github.com

何で作るか

案1 Ruby で書く

Ruby は標準ライブラリに YAML パーサーが入っているので、適当な rubyスクリプトを書けば目的は達成される。

ただ、そのためだけに Ruby 入れるのも嫌だな…って思ってやめた。

案2 Go で書く

Go のようなコンパイラ言語であれば、標準ライブラリに入ってなくともコンパイルすれば良いので楽である。

また、Go は goreleaser や go get などインストールしやすい環境が整っており最高。

というわけで初めは Go で書いていたのだけど、YAMLJSON で型が微妙に違う(YAMLmap[int]interface{} のこともあるが、JSONmap[string]interface{})のが面倒でやめた。

案3 Nim で書く(採用)

Nim は先日 1.0.0 が出たイケイケの言語で、Python っぽく書けて便利という評判が自分の中である。Go が無理なら Nim チャンス!ということで Nim で書くことにした。

Nim の YAML ライブラリ は最高で、loadToJson 関数があるので一瞬で終わった。

バイナリを作る

リリース周りは CI でやりたい。今回は GitHub Actions を使ってみることにした。GitHub Actions では、Action を組み合わせたり、自分でコマンドを記述したりして CI の動作を記述する。

Action は 公式がいくつか配布している 他、サードパーティのもある。今回はサードパーティ Action は使わない方向でやってみた。

Nim with GitHub Actions

公式では Golang など様々な言語をインストールする Action があるが、残念ながら Nim はない。なので自分で環境構築を行った。

macOS

brew が入っているので、 brew install nim する。

Ubuntu

Ubuntu では Docker を使った(apt で Nim が配布されているものの、バージョンが古くて依存ライブラリがコンパイルできない)。

amd64 だと 公式 Nim Docker Image を使えばよかったが、クロスコンパイルはできなかったので、 arm 用には クロスコンパイルできる Image を Docker Hub に作った *3

ちなみに、GitHub Workflow には Docker 上で動かしたり Volume を作ってくれたりする機能があるが、それを使うにはパブリックイメージを使う必要がある。そうでない場合は自前で docker build して docker run ... することになると思う。

その他

良かった

悪かった

まだ出たばかりというのもあって、使いづらい点も多かった。

  • 公式の Actions が機能不足

    artifact は一つずつしか Upload できない等、「一応できるけど不便」みたいな例が多い。 特にリリース周りは不便で、本当はもっとうまくできるのにな…と言いながら長い Workflow になってしまった。

  • job 間で値の受け渡しがしずらい

    値を直接受け渡しすることはできず、 artifact 経由になってしまう。「一回リリースつくって、そこに並列で artifact を追加する」といったケースでは upload_url を渡すことができずに困った。

  • 情報が多くない

    ドキュメントはちゃんとしているが、ユースケースがまだ少ないため情報が探しにくい。

  • YAML エディタが使いにくい

    エラーや補完を出てくれるのは嬉しいが、改行時は普通に改行してほしいな…。

多くの問題は時が経てば解決するだろう。

感想

  • YAML から逃げるために作ったのに、 GitHub Actions で数十行の YAML を書いていたのは悲しかった
  • こんな面倒なことをしなくても、Go 言語を使えばクロスコンパイルもリリースも一瞬でできるので最高だと思った。でも Nim も悪くないよ。

*1:書くのに向いているとは言っていないが、YAML よりはハマらない…

*2:手段が目的になった面もある

*3:実は Docker Hub 初めてです