🍇

Taskfileを使用して記事管理を自動化した話

2023/10/02に公開

https://zenn.dev/jy8752/articles/bff01aa5e2fcda

こちらの記事で自作のnote-cliというnoteや個人ブログの記事を管理するためのCLIツールを作成した話を紹介させていただきました。

個人的に使いやすいようにちょこちょこいじっていて個人ブログの記事管理にも対応させたのとコマンド実行時に複数のフラグを指定する感じになってしまったのでタスクランナーとしてTaskfileを導入したのでその備忘録です。

Taskfileについて

https://qiita.com/schrosis/items/12b4361c528819d13901

Makefileを覚えてから何かとMakefileでやろうとするくらいMakefileが気に入っていたのですが上記記事でMakefile警察の存在を知ったので次Makefile使いたくなったらTaskfileを使用しようと思っていたため採用してみました。

詳しくは上記記事や公式のドキュメントを参照していただければと思いますがざっくり言うとTaskfile.ymlというようなyamlファイルでタスクを管理します。以下は公式ドキュメント記載の例です。

Taskfile.yml
version: '3'

tasks:
  hello:
    cmds:
      - echo 'Hello World from Task!'
    silent: true
% task hello

> Hello World from Task!

Taskfileのインストール方法はいろいろ用意されていますが今回はHomebrewでインストールしました。

brew install go-task

他の方法はこちらを参照してください。

https://taskfile.dev/installation/

個人ブログの記事管理に導入してみる

個人ブログをAstroで公開していて記事ファイルはsrc/content/blog配下にmarkdownファイルを配置して管理していました。

tree ./src/content/blog 

./src/content/blog
├── 2023-10-01.md
├── 20230321.md
├── 20230506.md
└── 20230719.md

各記事ファイルには以下のようなメタデータ的なものを記載してます。

---
title: "Workers Tech Talk#1に参加した感想"
tags: ["tech", "ポエム", "Cloudflare"]
date: "2023-07-19"
---

これらの記事ファイルは直接手動で作成していたのを自動化したいと思っていたため、note-cliの機能を拡張して対応させてみました。

% note-cli create article ./src/content/blog -n article --no-dir -author Junichi.Y

% cat ./src/content/blog/article.md

---
title: ""
tags: []
date: "2023-10-02"
author: "Junichi.Y"
---

このコマンドを毎回実行するのもあれなのでTaskfileを使用してタスク化してみます。

Taskfile.yaml
version: '3'

tasks:
  new:article:
    dir: $HOME/myapp/my-blog/astro-my-blog/src/content/blog
    cmds:
      - note-cli create article -a Junichi.Y --no-dir -t .

これで以下のコマンドだけで記事ファイルが作成されます。

% task new:article

せっかくTaskfileを導入したので個人ブログでもTaskfileの導入について簡単に記事にしてみました。

https://jy-panda.com/2023-10-01/

noteの記事管理にも導入してみる

noteの記事管理にも同じように導入してみます。作成したTaskfileは以下のような感じです。

Taskfile.yaml
version: '3'

tasks:
  new:article:
    dir: $HOME/note
    cmds:
      - note-cli create article -a Junichi.Y -t .

個人ブログのときとほとんど一緒です。noteの方は一応記事ファイルのメタデータからアップロード用の画像ファイルを生成できるようにしているのでそれもタスク化してみます。

先にコマンドはこんな感じで画像生成できます。

% note-cli create image ./article/article.md -i ./icon.png --template 1 -o ./article/output.png
  • ./article.md メタデータを読み込むために対象の記事ファイルのパスを指定
  • -i 生成する画像に埋め込むアイコン画像のパスを指定
  • --template 使用する画像テンプレートの番号を指定
  • -o 出力ファイル名

Taskfileに引数を渡す

画像生成の場合、対象の記事ファイルを引数として指定する必要がどうしてもあったためタスクの実行に引数を指定できるようにする必要がありそうでした。いろいろやり方がありそうだったんですがまず以下のようにして引数をそのままTaskfileに渡せます。以下の例はTaskfileの公式ドキュメントに記載の例です。

version: '3'

tasks:
  yarn:
    cmds:
      - yarn {{.CLI_ARGS}}
$ task yarn -- install

--のあとに指定した引数はTaskfile内で{{.CLI_ARGS}}で全て渡すことができます。上記タスクの実行するコマンドはyarn installとなります。

この仕組みを使い引数にディレクトリ名を渡しTaskfile内でごにょごにょして必要な変数を用意します。

Taskfile.yaml
  new:image:
    dir: $HOME/note
    cmds:
      - |
        # 変数に引数から渡ってきたディレクトリ名を格納
        DIR={{.CLI_ARGS}}
        # 一応、末尾のスラッシュあれば除去しておく
        [[ $DIR == */ ]] && DIR="${DIR%/}"

        # 出力先
        OUTPUT=$DIR/output.png
        # 対象の記事ファイル
        ARTICLE=$DIR/$DIR.md

また、cmdsには上記のようにして複数行のコマンドをスクリプトとして書くこともできます。

(おまけ)乱数を使用してテンプレートをランダムに使用する

本題から逸れますが画像生成に使用するテンプレート画像が番号を指定するだけなので疑似乱数を生成してランダムに選択されるようにしてみました。シェルで乱数生成をしたことがなかったのですが$RANDOMを使用することで0 〜 32767の範囲の数値をランダムに生成できるようです。テンプレートは3つしかないので1-3の範囲で乱数が生成できればいいので問題なさそうです。

Taskfile.yaml
  new:image:
    dir: $HOME/note
    cmds:
      - |
        # 変数に引数から渡ってきたディレクトリ名を格納
        DIR={{.CLI_ARGS}}
        # 一応、末尾のスラッシュあれば除去しておく
        [[ $DIR == */ ]] && DIR="${DIR%/}"

+        # これを追加
+        TEMPLATE_NUM=$((RANDOM % 3 + 1))
        # 出力先
        OUTPUT=$DIR/output.png
        # 対象の記事ファイル
        ARTICLE=$DIR/$DIR.md

これで1-3の範囲の値がランダムに変数に格納されると思ったのですが毎回同じ値が使用されてしまう。。seedが毎回同じ値使われてるのかな?

ちょっと原因がわからなそうだったのでrubyのrand関数を使用するように変更しました。こういう時、スクリプト言語便利!!

Taskfile.yaml
  new:image:
    dir: $HOME/note
    cmds:
      - |
        # 変数に引数から渡ってきたディレクトリ名を格納
        DIR={{.CLI_ARGS}}
        # 一応、末尾のスラッシュあれば除去しておく
        [[ $DIR == */ ]] && DIR="${DIR%/}"

        # これを追加
-        TEMPLATE_NUM=$((RANDOM % 3 + 1))
+        TEMPLATE_NUM=$(ruby -e 'puts rand(1..3)')
        # 出力先
        OUTPUT=$DIR/output.png
        # 対象の記事ファイル
        ARTICLE=$DIR/$DIR.md

最終的なTaskfileは以下のようになりました。

Taskfile.yaml
version: '3'

tasks:
  new:article:
    desc: create new article. [command] task new:article
    dir: $HOME/note
    cmds:
      - note-cli create article -a Junichi.Y -t .
    silent: true
  new:image:
    desc: create new article image. [command] task new:image -- [directory name] 
    dir: $HOME/note
    preconditions:
      - sh: command -v ruby
        msg: This command requires ruby.Please install ruby.
    cmds:
      - |
        DIR={{.CLI_ARGS}}
        [[ $DIR == */ ]] && DIR="${DIR%/}"

        # TEMPLATE_NUM=$((RANDOM % 3 + 1))
        TEMPLATE_NUM=$(ruby -e 'puts rand(1..3)')
        OUTPUT=$DIR/output.png
        ARTICLE=$DIR/$DIR.md

        note-cli create image -i ./icon.png --template $TEMPLATE_NUM -o $OUTPUT $ARTICLE
    silent: true

タスクの実行

% task new:image -- 2023-10-01
Complete generate OGP image

% tree 2023-10-01 
2023-10-01
├── 2023-10-01.md
└── output.png

まとめ

今回は以下のことについて紹介しました。

  • note-cliの個人ブログへの導入方法について
  • タスクランナーであるTaskfileの導入方法について
  • Taskfileに引数を渡してスクリプトを実行する方法について

個人的にはこれでzenn, qiita, note, 個人ブログが同じような感覚で手元で執筆できるようになったので満足してます。使ってみた感じTaskfileは直感的にわかりやすくタスクが定義できるのでめちゃくちゃ良かったです。今後も個人的なものはMakefileではなくTaskfileを使用したいと思います。

今回は以上です🐼

Makefileと比較してみる(おまけ)

最後に作成したTaskfileをMakefileにしたものと比較してみます。

Taskfile.yaml
version: '3'

tasks:
  new:article:
    desc: create new article. [command] task new:article
    dir: $HOME/note
    cmds:
      - note-cli create article -a Junichi.Y -t .
    silent: true
  new:image:
    desc: create new article image. [command] task new:image -- [directory name] 
    dir: $HOME/note
    preconditions:
      - sh: command -v ruby
        msg: This command requires ruby.Please install ruby.
    cmds:
      - |
        DIR={{.CLI_ARGS}}
        [[ $DIR == */ ]] && DIR="${DIR%/}"

        # TEMPLATE_NUM=$((RANDOM % 3 + 1))
        TEMPLATE_NUM=$(ruby -e 'puts rand(1..3)')
        OUTPUT=$DIR/output.png
        ARTICLE=$DIR/$DIR.md

        note-cli create image -i ./icon.png --template $TEMPLATE_NUM -o $OUTPUT $ARTICLE
    silent: true
Makefile
.PHONY: new-article new-image

new-article:
	@cd $(HOME)/note && \
	note-cli create article -a Junichi.Y -t .

new-image:
	@if ! command -v ruby > /dev/null; then \
		echo "This command requires ruby. Please install ruby."; \
		exit 1; \
	fi
	@cd $(HOME)/note && \
	DIR=$(filter-out $@,$(MAKECMDGOALS)); \
	[[ $$DIR == */ ]] && DIR="$${DIR%/}"; \
	TEMPLATE_NUM=$$(ruby -e 'puts rand(1..3)'); \
	OUTPUT=$$DIR/output.png; \
	ARTICLE=$$DIR/$$DIR.md; \
	note-cli create image -i ./icon.png --template $$TEMPLATE_NUM -o $$OUTPUT $$ARTICLE

どちらのほうがわかりやすいでしょうか??

GitHubで編集を提案

Discussion