Be an Engineer.

社会人からWEBエンジニアになった人間の備忘録的勉強記録

READMEにtreeコマンドの結果を書き込むGitHub Actions「readme-tree-writer」を作った

GitHub Marketplaceのリンクはこちら。 github.com

GitHubリポジトリはこちら。 github.com

動機

会社のリポジトリを眺めていると、あるREADMEの中に「そのREADMEが置かれているディレクトリで実行したtreeコマンドの結果」が記載されていました。ディレクトリ構成が情報として重要なコードであったこともあり、確かにそのtreeの結果がREADMEに書かれていると簡単にその情報が得られることもあり便利なものでした。

一方でそれには一つ問題があり、それはすぐにその情報が陳腐化してしまうというものでした。日々の開発の中でディレクトリ構造が変わったりファイルが追加されたりしても書き換え漏れることがあるため、古い情報が記載されたままになっているということが多々発生してしまいます。

そこでGitHub ActionsのようなCIの中で、実際のtreeの実行結果とREADMEの記載内容に差分があるかチェックする、あるいは書き込めるような仕組みが用意できれば上記の問題の解決策になるかなと思い、作成しました。

readme-tree-writer

作成したものは「readme-tree-writer」というGitHub Actionで、GitHub Actionを導入したリポジトリ内のすべてのREADMEに対し、treeコマンドの結果の記載を更新する というものです。

例えば、以下のようなディレクトリ構成の場合を考えてみます。

some_dir
├── dir1
│   ├── README.md
│   ├── dir1
│   │   └── file
│   └── dir2
│       └── file
└── dir2
    ├── README.md
    └── file

この場合であればreadme-tree-writerはsome_dir/dir1/README.mdsome_dir/dir2/README.mdを対象とします。
このときsome_dir/dir1/README.mdには以下のような更新を行います。

...

# Tree

\`\`\`    # <- 本来はこのバックスラッシュは存在しません。ブログの記法上やむを得ずバックスラッシュを追加しています。
.
├── README.md
├── dir1
│   └── file
└── dir2
    └── file

\`\`\`

このようにそれぞれのREADME.mdが置かれているディレクトリでtreeを実行した結果が記載されます。つまりこのsome_dir/dir1/README.mdでは、some_dir/dir1/でのtreeの結果が記載されるわけですね。some_dir/dir2/README.mdについても同様です。

あまり文章で伝えるよりも、実際のサンプルを見てもらうほうがわかりやすいかもしれません。

ユースケース

このreadme-tree-writerを使って実現できるユースケースをいくつかこちらにて紹介します。

1. treeの結果に差分があればfailにしてプルリクエストのstatus checkを落とす

プルリクエストを出したときやcommitを重ねたときに、ファイルやディレクトリの変更があるにも関わらずREADME内の記載が変更されていなければ、status checkをfailにするという使い方が考えられます。こうすることで記載に差分がある状態でmergeできないようする・開発者にREADMEの記載を更新しないといけないことを知らせるなどを見込めます。

あくまで一つの例ですが、workflowの設定は以下のようなものでしょうか。

name: Check tree diff

on: push

jobs:
  sample-workflow:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Write tree outputs to README.md
        uses: shirakiya/readme-tree-writer@v1
        with:
          config_path: .github/readmetreerc.yml
      - name: Check diff
        run: |
          if [ "$(git diff --ignore-space-at-eol . | wc -l)" -gt "0" ]; then
            echo "Detected diff.  See status below:"
            git --no-pager diff HEAD .
            git status
            exit 1
          fi

2. treeの結果に差分があれば、その差分を追加でcommit

1のケースと似ていますが、1はチェックするのみに対して追加でcommitを重ねるパターンもありそうです。同様にプルリクエストを出したときに差分があれば、もうGitHub Actionsからその差分をcommitしてもらうことで、更新作業をも自動化できます。

こちらもworkflowの設定の一例を置いておきます。

name: Check and commit tree diff

on: push

jobs:
  readme-tree-writer:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Write tree outputs to README
        uses: shirakiya/readme-tree-writer@v1
      - name: Check diff and commit if diff exist
        run: |
          if [ "$(git diff --ignore-space-at-eol . | wc -l)" -gt "0" ]; then
            git config user.name github-actions[bot]
            git config user.email github-actions[bot]@users.noreply.github.com
            git commit -am "commit by shirakiya/readme-tree-writer"
            git push
          fi

まとめ

今回説明をしていないですが細かい設定等はreadme-tree-writerのドキュメントをご確認ください。treeの結果をREADMEに書かれていてそれをメンテナンスしたいというニーズがどこまであるのか自分でも懐疑的ですが、もし何か機能追加の要望・フィードバック等があればissueを作成していただければと思います。

それでは!