ハンドルネームの敬称は省略できます

🦀パソコンを叩く日々🐈

Taskfile で文字列として二重中括弧「{{ foo }}」を扱う場合は print をしよう

こんにちは。 id:rokuokun です。

この記事はタイトルが全てです。 Taskfile において、{{ foo }}のような text/template によって解釈されるようなテンプレート記法を用いる場合は print を使いましょうという話です。

何があったのか

atlas というスタンドアロンマイグレーションツールを使い始めており、引数が徐々に長くなってきたので Taskfile に移そうとしていました。

atlasgo.io

atlas では inspect という動いているデータベースからスキーマ情報を抜き取るコマンドがあり、それの引数に--format "{{ sql . }}" と書くことがありました。

❯ docker compose run --rm atlas schema inspect -u "mysql://root@db:3306/database" --format "{{ sql . }}"

これをそのまま Taskfile に移してみます。

version: '3'

tasks:
  atlas:inspect:sql:
    cmds:
      - docker compose run --rm atlas schema inspect -u "mysql://root@db:3306/database" --format "{{ sql . }}"

これを実行すると、以下のように怒られてしまいます。

❯ task atlas:inspect:sql
template: :1: function "sql" not defined

なぜこうなるのか

記事冒頭に書きましたが、Taskfile も atlas も Go で書かれており、どちらもテンプレートを展開するために text/template パッケージを使用しています。

pkg.go.dev

github.com

github.com

ちなみに余談ですが、Taskfile は text/template を拡張したパッケージを使用しています。

github.com

解決策

❯ task atlas:inspect:sql
template: :1: function "sql" not defined

これを解決するためには --format "{{ sql . }}"'{{ print "{{ sql . }}" }}' のように書き換えてあげます。

version: '3'

tasks:
  atlas:inspect:sql:
    cmds:
      - docker compose run --rm atlas schema inspect -u "mysql://root@db:3306/database" --format '{{ print "{{ sql . }}" }}'

実はこの時一つ落とし穴があり、'{{ print "{{ sql . }}" }}'"{{ print '{{ sql . }}' }}"と書いてしまうと以下のように怒られてしまいます。

❯ task atlas:inspect:sql
template: :1: malformed character constant: '{{ sql . }}'

おわりに

今回は組み込み関数の print を使用しましたが、このほかにも多くの組み込み関数があります。時間があればドキュメントを読んでみてください。

taskfile.dev

pkg.go.dev