Shamshir が Github Actions に対応しました

従来のスタンドアローンでの起動に加えて、Github Actions からも起動できるようになりました。よろしければお使いください。

https://github.com/kyagi/shamshir

f:id:kyagi:20220204204204p:plain f:id:kyagi:20220204204219p:plain

        uses: kyagi/shamshir@v1

トリガーのイベントとして「PR のレビューや修正」だと数が多くて Github Actions の実行時間の制限が心配かもしれません。その場合、cron 起動にして「平日の 9-19時(JST=UTC+9)に 毎時 0, 30 分の 2 回ずつ」であれば 1 レポジトリ20 回/日なので大丈夫だと思います。

on:
  pull_request_review:
    types: [submitted, edited, dismissed]
  pull_request:
    types: [edited, labeld, unlabeled]
on:
  schedule:
    - cron: '0,30 0-10 * * 1-5'

以下は振り返りになります。

独自 DSL である Github Actions の理解が難しい

Github API Reference をみてスタンドアローンの js を書くのはスムーズに行きました。一方 Github Actions のドキュメントを読んで YAML を書くのは恐ろしく手間でした。これは背景知識の差によるものです。あらかじめ Rest API とはどういうものかを知っているかからはじめるのと、独自 DSL を スクラッチから学ぶ学習コストの違いです。Github Actions を「使う」側ではなく「作る」側は全くの経験だったのでのドキュメントを読んでも「つまり、どういうことだってばよ?」で エラーメッセージを読んでトライ & エラーを延々と繰り返すしかありませんでした。

トライ&エラーの一例を挙げます。例えば、action.yml で「使いますよ」宣言したログを

outputs:
  log:
    description: 'log'

octkit ライブラリを使用して js 内ではこうやって使用して

core.setOutput('log', files)

Github Actions の Web 画面に出すために workflow の yml でこう書かなければいけない

 - run: echo "${{ steps.id.outputs.log }}"

こういったところでつまづきまくりました。要は Github 側でスポーンさせたコンテナに対してどうやって入出力をつなぐか、の仕組みをつくって YAML で提供してくれているのだと思いますがそれぞれがどう連携して動いているか、がわかりづらかったです。ただ慣れればササッとかけるかもしれません。これは利便性と柔軟性のトレードオフですね。

Github Actions を動かすのが面倒(使うのは楽)

動かすために、ダミーレポジトリをつくってダミーの PR でダミーのコミット(Update README) を延々と繰り返すしかありませんでした。PR を 30 個ほど、README に 1 文字加えるだけのコミットを 100 回ほど繰り替えしたでしょうか...

スタンドアローンと Github Actions の両方をサポートする、という設計が無理めだったかも

振り返るとスタンドアローンと github actions 両方やろうとしたのが間違いだったかもしれません。最初はスタンドアローンで作っていたのを友人が「Github Actions で動かせば制限時間内ならタダなのにサーバ代乙 (^Д^) pgr」と煽ってきたため、カッとなって「え!! おなじ動作を Github Actions で!? ... (両方)出来らあっ!! ヽ(・Д・)ノ」と作り込みをはじめてしまいました。結局、認証の違い(personal access token or ${{secret.GITHUB}} )からくる octokit の差分とパラメータの取得処理の違いをどうやって吸収するかに苦しみました。Github Actions 側のコンテナに独自の環境変数や /etc/system-release 的なファイルがあって、「ここは Github 様のコンテナ内ですぞ」が js 内から判別できれば楽だったのですがそんな美味い話があるわけもなく…

結局コンストラクタ内で分岐させましたが、共通メソッドを用意した親クラスを用意して継承 or コンポジションを使った方がよかったかもしれません(v2 の予定が出てくればリファクタリングしたい)。今後拡張する場合、肥大化しそうなのはスタンドアローン側ではなく Github Actions 側のはず。

DSL でのプログラミング(?) について

個人的に触っている Kubernetes も CloudFormation も Ansible も YAML で用意された箱に納めるデータだけ用意する形なので「リソースの定義だけ準備しろ」が Ops における最近形式なのかもしれません。その場合、各コンポーネントがどう連携しているか理解することが重要になってきます。しかし YAML を書くには、フレームワークが提供するコンポーネントをしっかり理解しないといけないので、初動までの学習コストはどうしても高くなるように思えます。Github API Refereces を見てスタンドアローンの js を自由に書いて好きなサーバで動かすのか、Github Actions の DSL に従って Github というプラットフォームで統合された形で動かすのがいいのか... どちらも一長一短です。

「Github Actions おじさん」は副業 or 新規事業になるか

Github API を利用してスタンドアローンのスクリプトを作るのは楽でしたが、それを Github Actions 上で動かすためにカスタムの Github Action を作るのは独自 DSL の学習コストや実行環境の点で、想像以上に大変でした。

ここまで大変なら「Github Actions おじさん」がビジネスになるのではないか、作るのは面倒なので誰もやりたがらない反面、使うのは便利だからこれでビジネスができないか、という議論を友人としたところ、すでに普及したプラットフォームであり、ネットワーク効果が高いので専門職として成り立つ気はする、との結論になりました。

PR だけではなく、commit, issue, packages など、ほぼすべての github イベントに対してアクションを実行できるので用途は幅広く、拡張性も高いので「ウチの Github レポジトリでこういうことをしたい」会社はそれなりにあるのではないでしょうか。スタートアップに提供する場合、彼らは本業のプロダクト開発を効率化できますし、大企業に提供する場合、彼らは複数レポジトリに一括して恩恵を享受できます。使用者が kyagi/shamshir@ref で使い分けられるのも、開発者(私)にとってはブランチごとにクライアントを管理できるのでよさそうです。

まとめ

オレはようやくのぼりはじめたばかりだからな。このはてしなく遠い Github Actions 坂をよ…(未完)。

次回作(v2)にご期待ください。( •ᴗ•)੭

追記

Github Sponsors

使ってみて気に入りましたら Github Sponsor で支援していただけると嬉しいです ( ᵕᴗᵕ ) 支援していただいた方/組織は機能開発の優先リクエストを開発者(私)に送ることができます。 github.com

営業メッセージ

もしこの Github Actions が気に入った場合は Github Sponsors から支援していただけると嬉しいです。$1/月でスポンサーのバッジを、 $5/月で開発における優先リクエストを受け付けています。

現状、Shamshir は「Approved の数」を条件として「ひとつの」ラベルをつけたり/はがしたりしていますが、より複雑な条件や複数のラベル、ユーザーのロールに応じての動作も開発可能です。

Github Actions はとても便利な反面、そのドキュメントはお世辞にも読みやすいものとは言えず、独自の DSL とワークフローがさらにプログラマの理解を難しくしています。また、ドキュメントは基本的に全て英語で書かれており、非ネイティブの開発者は読み解くのに時間がかかります。

わずかなコスト、わずかな時間であなたの開発チームにあったカスタム Github Actions の開発ができたらどうでしょうか? あなたも私もハッピーです。ご連絡、お待ちしています :-)