Help us understand the problem. What is going on with this article?

マークダウンベースのタスクランナー saku を作った話

More than 1 year has passed since last update.

tl;dr

  • make をタスクランナーとして使うことに疲れた (.PHONY ってもう書きたくない)
  • yaml ベースのタスクランナーは幾つかあったがしっくり来ない (go-task / robo)
  • そもそもタスクの記述言語をマークダウンにした方が良いのでは?
  • マークダウンベースのタスクランナーを作った! saku! (update: Go言語バージョンも作った!)

モチベーション

自分は普段、趣味も仕事もほとんど JavaScript ばかり書いているため、タスクランナーとしては npm run-script を使っています。 run-script はタスクのドキュメントが書けないとか、タスクにコメントをつけれないとか(JSON の文法の制約上)、不満点は色々ありますが、npm-run-all などの支援ツールを利用することで、必要最低限のタスク定義は十分にできるツールと個人的には思っています。

とあるプロジェクトで terraform スクリプトのレポジトリを作ることになったのですが、terraform のベストプラクティスによれば、 Makefile に terraform コマンドを書くことがベストプラクティスとされているようです。確かに terraform はコマンドとしては長すぎなので、タスクランナーを使うというのは良いと思いますが、2018年に Makefile はどうなんだという気がしました。謎のディレクティブ .PHONY をまた書くのかと思うと辛いです。そもそも make はタスクランナーとして作られたツールではなく、コンパイル言語をコンパイルすることに特化されたシステムなので、それをタスクランナーとして使うこと自体がハックです。そこで、もう 2018年なので、タスクランナーとしての make をリプレースする何かが存在するはずだと信じてググり始めました。

go-task

幾つかのツールを見つけましたが、もっとも自分の要求に近そうなツールは go-task でした。go-task は yaml にタスクを定義していくシンプルなツールです。

でも何かが違うと感じました。それは yaml の中のキーです。 cmds, desc などのキーにタスクのコマンドと説明を書くのですが、これらのキーが "ノイズ" に感じるのと、キーの名前自体に恣意的な印象を受けました。

go-taskのタスク例
tasks:
  build:
    cmds:
      - go build -v -i main.go

  assets:
    cmds:
      - minify -o public/style.css src/css

Makefile では、コマンドはただのインデントで表されていて、cmds のような "ノイズ" はありません。これだったら Makefile の方がスッキリ書けるのではないか。make 置き換えを検討しているのに、書き方が逆にまどろっこしくなるのでは、本末転倒です。

同じものをmakefileで書いた例
build:
    go build -v -i main.go

assets:
    minify -o public/style.css src/css

Think syntax

yaml でもっと別な syntax は組めないかと考えてみましたが、yaml という特性上、あるオブジェクトの中身を記述する際には key: value という形が必須になってしまうため、go-task のデザイン以上にシンプル化は出来ないと感じました。

自分の知っている syntax を幾つか考慮した結果、コマンドをクオートなしの裸の状態で書ける文法でかつ yaml のように key: value のような構造を省ける記法を持った言語というとマークダウンしかないという結論になりました。

Markdown-based task runner

マークダウンでタスク定義ができるタスクランナーをググりましたが見つかりません。であれば作るしかないということで saku を作りました。

マークダウンのパーサは最近だと remark が元気が良さそうに見えたため remark を選択。CLI のベース部分は以前 bulbo, kocha などの為に作った自分のツールチェインがあるのでその辺を流用しました。

プログラムの対象はタスクランナーということで、Task というモデルクラスがひとつだけ存在して、それをベースに DDD のビルディングブロック (Factory など) で周りを固めていくとあとは自然につなぎ部分をコーディングしていって実装完了。node ecosystem 万歳 🙌 DDD 万歳 🙌

:dog2: Dogfooding

12コミット目から saku の開発に必要なタスクを saku.md で記述してドッグフーディングを開始しました。

# test
> Runs unit tests

    npx kocha --require src/__tests__/helper src{/,/**/}__tests__/*.js

# lint
> Runs lint checks

    npx standard

# fix
> Runs auto fixer of lint tool

    npx standard --fix

# cov
> Makes coverage reports

    npx nyc --reporter=text-summary --reporter=lcov saku test

# codecov
> Posts reports to codecov.io

    saku cov
    npx codecov

ドッグフーディングしてみると、思った通りタスクが記述しやすいと感じたのと、また、saku.md を github の機能でマークダウンとしてレンダリングした時の見栄えの良さが予想外の発見でした。

ロードマップ

  • 今後できれば windows サポートをしたいと思っています。 -> windows 対応しました。
  • npm-run-all のような saku -p build:* のようなワイルドカードタスク実行が欲しいです。

感想

  • 0 から何かを作るのは楽しい!
  • マークダウンは、yaml のような自然な論理的構造を持って居ないですが、逆にクオートなしで書ける値のバリエーションが多く、マークダウン AST に任意の意味付けを与えることで、非常に記述がしやすく可読性の高い DSL を作れる可能性を秘めた syntax だと感じました。
kt3k
JavaScript engineer
https://kt3k.org
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした