2025年の振り返り

haya14busa
·
公開:2026/1/1

2026年あけましておめでとうございます。haya14busaです。

こうやって日本語で文章を書いて公開するというのはSNS(X)を除けばとっっっっっっっても久しぶりでなんだか緊張しますね。

久々に筆(キーボード)を取った理由は他でもない、深い理由がある....と見せかけて特に何もない思いつきです。特段振り返るほどの出来事がたくさんあったわけではないですが、今年はいくつか大きな出来事がありつつ、近年あまりにもアウトプットが少ないと自覚しているのでリハビリがてら年の瀬にキーボードを叩いてみます。

ぶさベビちゃん誕生 & 育休 & 育児

いきなり2024年の話になりますが、2024年10月頃にぶさベビちゃんが誕生し、その後はフルで育休取りつつ育児に明け暮れた日々でした。

育児の様子はたまに #ぶさぶさ育児日記 タグでつぶやいています。

ぶさベビちゃんはすくすくと育って最近は元気に公園を駆けずり回ってます。育児は楽しいけど大変で、ヨッピーさんが育児を運転に例えて、それぞれのタスクは簡単だけどずっとしていると大変というようなことを書いているのですがしみじみ言いえて妙だなと感じます。ちょまどさんが赤ちゃんの可愛さでMPは回復するけど、HPは回復しないと(引用)ポストしてるのも首を上下に振りすぎて首がもげそうです。なおぶさベビちゃんは「イヤイヤイヤイヤイヤ....」と嫌でもないのに何故か首を横にブンブンブンブン振るクセが有りかわいい。首もげないでね。

そんなこんなであまりまとまった時間を取りづらく、特に育休明けてからは仕事と家庭&育児のこと以外ほぼ出来てないです。もうちょっと大きくなったら時間取りやすくなるんだろうか?どちらかというと休憩時間としてYouTubeなどみたりちょっとだけゲーム(麻雀)してる時間をもっと活用できるバイタリティが必要な気はします。なんならガッツリゲームする気力もなくなってきててまずい。

reviewdog / tj-actions サプライチェーンアタック

今年の3月頃、reviewdog/action-setup がチェーンの1つとしてサプライチェーンアタックを受けてしまいました。

↑の図は https://unit42.paloaltonetworks.com/github-actions-supply-chain-attack/ から引用。

なんだかサプライチェーンアタックってやつ最近見るようになった気がするなぁ...と事件の前から薄っすら思っていましたが、まさか依存してるライブラリが攻撃を受けてるどころか、自分がメンテしてるプロジェクト自体が攻撃を受けるなんて露ほども思っていませんでした。

能天気にぶさベビちゃん育児してたら reviewdog/action-setup が攻撃されてるんじゃね? これが tj-actions の攻撃の原因じゃね?というツイートとセキュリティリポートがある日急に飛んできました。

あまりに攻撃が巧妙で痕跡がほとんど残ってなかったせいで最初は「いやいや何かの間違いだろよく見てくれよ...」と誤報を半ば願いつつ調査を始めました。内心こういった形の誤報なんてあるわけないとは理解しつつも。

そんなこんなで調査した結果実際 reviewdog/action-setup がv1タグを書き換えられる攻撃を受けていたことは理解し、reviewdog orgの使用するactionsをすべてSHAでpinしたりアナウンスするなどといった最低限の一次対応を並行して行ったあと、tj-actions の依存を含めたその影響のデカさにひとしきり涙しました。なんてことになってしまったんだ... まさか自分がメンテしてるプロジェクトがチェーンの一部となったサプライチェーンアタックが発生してしまったなんて。

なお後からわかったことですが、どうやら攻撃者は Coinbase という特定の暗号資産関連のリポジトリを攻撃しようとして最終的には失敗したらしく、実は知られている限りでは思ったほどには直接的な被害は少なかったと思われます。もっと実際の被害がデカかったら完全に心が折れてたかもしれない。

一次対応のあとは何故タグが書き換えられたのか原因を突き止めるため、GitHub Support に連絡をとって調査し、その結果 reviewdog org のあるメンテナのPersonal Access Token (PAT)が悪用されたことが判明。それが悪意あるメンテナではなかったのですぐには周りに公開・共有できず、そのメンテナのPATが何故流出したのかもGitHub Supportにデータを共有してもらいつつ一緒に調査して、どうやらSpotbugsのあるリポジトリのアクティビティが原因と突き止めたりしてました。

(この間、内部データにアクセスしやすい GitHub の Secruity Team か誰かがそもそももっと積極的に調査してくれないか?とサポートにエスカレートしたりコンタクトを試みましたがなかなかいい返事がもらえずヤキモキしてました。なお僕が原因を突き止める数時間前に Spotbugs のメンテナにあやしいアクティビティがあると連絡が行ってたらしく、もし reviewdog/tj-actionsの事件の関連で調査して連絡してたんだとしたら、こっちにもっと連絡して連携してくれよ...という気持ちになりました。)

そしてSpotbugsのあるリポジトリの不信なアクティビティが何故起こったのか?というところは謎だったのですが、このあたりで海外のセキュリティリサーチャーの人とある程度状況を共有することができ、後はトントン拍子で調査が進み、Spotbugsの別のリポジトリの pull_request_target event が悪用されたことから始まっていたことが判明して調査は一件落着しました。

と、ここまである程度書いてきましたがもっと詳しい事件の詳細を知りたい方は↑にリンクした記事、または日本語だとそれを読んで書かれた https://zenn.dev/shunsuke_suzuki/articles/tj-actions-incident-2025 を参照してください。この事件を受けて得た教訓とか根本的な対策などは別途記事を各予定です。(時期未定)(既にかなり遅い)

この事件の頃はまだ育休中でぶさベビちゃんも5ヶ月前後で寝てる時間も多く、使命感にも駆られて何とかやってましたが思い返すと大変でした。対応の途中でミルクあげたりしてた気がする。MITライセンスで公開してるので何かこういう事件があっても自分が責任を取らされたりすることはなく、何なら修正したり調査したりする義務もないわけですが、実質自分がやらなきゃいけない、自分しか(権限的に)できないこともありOSSの憂鬱の一端を感じました(自分が悪かったところを棚に上げておいて)。この頃 GitHub Sponsor で支援してくれたりXやSlack (vim-jp) などで声かけてくれたりサポートしてくれた方には感謝しています。

サプライチェーンアタック対策リリースエンジニアリングプロジェクト

上述したサプライチェーンアタックを当事者として受けて理解が深まり、こういうものがあったらいいなぁというアイデアもいくつか浮かびました。だいたい時を同じくして AI Agent をつかったコーディングがかなり実用的になってきた時期でもありました。Sonnet 3.7 が2月末、Claude 4 が5月末あたりリリースです。育休中にもAI使っておきたいなという思惑がもともとあったこともあり、いくつかサプライチェーンアタック対策、ないしリリースフロー関連のOSSを作ることにしました。

勘のいい読者ならお気づきでしょうか?そう、事件のポストモーテム記事だったりを公開する予定が、まずそれらのプロジェクトを終わらせて、どう対策すればいいかもまとめて共有しようと思った結果ヤックシェービングでプロジェクト数が膨らみ育休中どころか年内に間に合わなかったのです....(土下座)

別に元々そこまで完璧主義で完璧になるまで公開しないっていう性格でもないと思っていたのですが、近年そもそもアウトプットしなさすぎで腰が重いのもあり、ほぼどこにも紹介してませんでした。ここでせっかくなので懺悔として(?)先行紹介させてください。反応がよければブラッシュアップしてちゃんと公開するまでの時間が短くなるかも(かも)。

binstaller: config 書くとそこからGitHub Release にアップロードされている適切なos/archに対応したバイナリをダウンロード&インストールしてくれるインストーラーシェルスクリプトを生成するツール。生成されたスクリプト内でバイナリのチェックサムを検証できるのはもちろんのこと、そもそもインストーラーが自動生成かつreproducibleなのでそのインストーラーシェルスクリプト自体が正しい過程で生成されたか gh attestation verify や cosign を使って検証できる。

curl したシェルスクリプトをそのまま実行するなんて正気かよ...という人にも安心。

またスクリプトを実行するとインストールする代わりにダウンロード&バイナリを実行してくれる runner スクリプトを生成することも可能。zellij ってツールが試しに実行できるスクリプトを公開していたのをみて、おもしろいと思って実装してみました。もちろんこちらもスクリプトを検証してから実行できる。

ステータス: スクリプト生成ツールとしてはほぼ完成といっていい状態。godownloader が生成するインストーラースクリプト互換のフラグになっており、reviewdogのインストーラースクリプトは移行済み。

binst install <tool> とか binst x <tool>[@version] (binx <tool>[@version]) でシェルスクリプトを生成せずにCLIだけでインストールしたり実行する機能を将来的につけたいなとは思ってる。

trusted-tag-releaser: git tag を gitsign を使って keyless 署名してリリースできるワークフロー。GitHub Actions みたいな生成される成果物がなく、タグ==リリースとみなせるようなプロジェクトで主に使える。例えば意図したリポジトリの意図したワークフローで正しくタグが打たれてるかを検証できるようになる。後述するGitHub Actionsはすべてこのワークフローを用いてリリースされてる。

GitHubがImmutable Releases機能を公開してタグが書き換えられることをGitHubの設定側で防ぐことはできるようになったけど、新しいタグが想定通りに打たれてるかはわからないので、trusted-tag-releaserを使って依存更新前に検証するフローを組んだりすることもできる。また v1, v2 といったタグはimmutableにできないけど、trusted-tag-releaserで署名して使用前に検証するということが可能。

ステータス: ほぼ完成してるといっていいけど、ドキュメントが書けてない。

trusted-go-releaser: タグだけでなくバイナリといった何かしらの成果物がある場合に goreleaser を使って keyless 署名付きのアセットをリリースするためのワークフロー。 goreleaserは実はGoだけでなくRustやZig, bun のシングルバイナリといった別言語のリリースにも使える。上述したbinstallerのconfigがある場合はリリースに署名付きインストーラースクリプトもアップロードしてくれる。

ステータス: ドキュメントがない。署名する部分をgoreleaserに頼ってるが自前でやるようにしようかなぁとか思ってる。

trusted-tag-verifier: gitsign (trusted-tag-releaser) で打たれたタグをverifyできるアクション。

ステータス: 基本機能は完成してるけど、複数いっきにverifyしたり起動&実行を速くしたい気持ちはある。

sigspy: trusted-{tag,go}-releaser, gh attestation といったいわゆる trusted publishing と呼ばれるような Sigstore のextentionがついた署名の中身を(検証せず)取得できるCLIツール。上記のtrusted-tag-verifierでも使われてる。gh attestation verifyとかcosignとか検証するときに事前に署名が生成されたリポジトリなどをフラグで渡す必要があるけどその値がよくわからなかったり、その検証で使われた以外の値を取得したりするのが面倒な場合があり、そういうときに sigspy を使って中身を確認することが簡単にできる。

ステータス: 完成済み

create-release-pr: リリース用のPRを生成してくれるGitHub Action。tagpr にインスパイアされてる。主な違いとしては tagpr と違ってリリース用のPRをマージしても勝手にタグを打ったりせずに、単にactionのoutput のstatusが違うものが返ってくるようになっており、タグを打ったりリリースをする前に自由なステップを挟むことができる。

ここでGitHubのリポジトリのタグにプロテクションルールを設定できて、対象のコミットが特定のステータスが成功していることや、特定のDeploymentが成功してることを要求できる。またDeploymentのルールとして特定のブランチ(e.g. main)にしかdeployできないような設定をすることができる。

つまりtagprと違ったcreate-release-prの嬉しいところとして、リリースPRがマージされた後にDeploymentを設定したジョブを作ることで意図しないフロー外でのタグ打ち&リリースをできないように設定できる。

またCHANGELOG生成やコード内のバージョンを上げるという機能も create-release-pr には含まれてない。代わりに create-release-pr の後続のステップで作成or更新されたリリースPRのブランチに対してユーザーが自由に何でもできるようになってる。

ステータス: ほぼ完成してるけどドキュメントがない。あとリリースノート生成機能はGitHubのAPIを使うようになってるけど、後述する gh-release-notes を直接使えるようにもしようかなと思ってる。

commit-or-rewrite: create-release-pr で作られたブランチに自動でコミットを積んでいく場合更新されるたび、つまりPRがマージされるたびにコミットが積まれるようになってしまうのを防ぐために同じidが付与されたコミットの場合は新規に作成せずリライトしてくれるアクション。

ステータス: 完成

sticky-comment: PRやissueなどで同じidであれば新しくコメントをポストするのではなく既存の同一idのコメントを更新してくれるアクション。例えば create-release-pr で作られた release PR に依存してるライブラリの更新情報をコメントとしてポストしたりなどなどできる。

ステータス: 完成済み

kugiri: ファイル中のマーカーのセクション内のテキストを取得したり挿入・更新などができるツール。以下マーカー例:

  • <!-- KUGIRI-BEGIN: {id} --> - Start of a section

  • <!-- KUGIRI-END: {id} --> - End of a section

  • <!-- KUGIRI-INSERT: {id} --> - Insertion point marker

CHANGELOG.md を半自動生成して手書きでかける余地を残しつつ自動更新したいという要望を叶えるために作った。ただ後述する gh-release-notes のテンプレート機能使えばいいのでは?という気もしてきている。

Rust製で上述したtrusted-go-releaserを使ってリリースされてる。

ステータス: 完成済み

gh-release-notes: 育休中にタスクが終わらなかった主な元凶。PRのデータを元にリリースノートを作成することができる。

元々GitHubのリリース生成APIでいいかな...と思ってたんだけど、なぜかこのAPIは contents: write 権限を要求したり、ラベルによるカテゴライズをするためのコンフィグもリポジトリ内のものしか使えず、複数のプロジェクトで同じコンフィグを使うといったことができないなど微妙なところが多々あった。そこでこの問題点だけ解決したツールを作るならすぐできるか...と思って取り組んだんだけど結局もっと便利にしたくなって時間がなくなってしまった。

minijinja のwasmバインディングを使ったテンプレート機能がサポートされており、テンプレートやラベルによるカテゴライズなどに使えるコンフィグもリモートのリポジトリに置いてあるものを使うことができる。コントリビュータのGitHub Sponsor情報を取得してスポンサーリンクを表示してあげたり自由自在にリリースノートがかける。また minijinja の include 機能で特定のパスにファイルを置いておけばリリースノートに手書き部分を含めたりできる。

一応公開が遅くなってる言い訳になってない言い訳をしておくと、育休終了後もちょっと頑張って公開までこぎつけようとしたんだけど、minijinja-js (wasm) で足りない機能がありPRを投げて、マージしてくれたら進めるの楽だなぁ、こっちで一時的にフォークしたもの使うの面倒だなぁ。。。と思ってたらその間に熱が冷めてきて仕事も本格的にはじまりだして放置気味になってしまった。別にminijinjaの作者は全く悪くなく、むしろ1ヶ月ちょいでマージしてくれてるのでそこまで遅くない。ここでもOSSの憂鬱の一端を感じました(その2)

ステータス: だいたい完成。minijinjaへのPRがマージされたので include 周りの処理を変更すれば一旦終わりだったハズ(覚えてない)


いやー大体のツールはほぼ完成してるのにドキュメントが足りないとか、組み込むに当たってちょっと気になった部分を改善したくなってヤックシェービングしまくってちゃんと公開できてないのよくない。どっかで時間つくって一旦やり切りたい。あと reviewdog org では少なくとも使う予定で、もし他の人達も使うようになった場合は特にメンテ手伝ってくれる人募集してるので興味あったら声かけてください。

育休復帰とその後、またはAIの話

弊社は Gemini 系列のモデルしか使えず、育休復帰当初は Gemini 2.5 Pro に絶望しつつ仕事の勘を取り戻してたんだけど、Gemini 3.0 Pro が11月にリリースされ gemini-cli が使えるレベルに到達しライフ(ワーク)チェンジングでした。モノレポでうまくAI Agent使うの大変そうじゃない?っていう疑念もあったんだけど、プロンプトとコンテキストがしっかりしてれば想定よりうまくツールを使ってくれて普通にやってくれるなぁという印象。たまにポンコツだけど。2026年以降どうなっていくか楽しみ。はやく仕事を奪われたい。

話は戻って個人のOSSでも本当はAIとreviewdog周辺ツールでなんか作ってみようと思ってたんだけど手が足りなかった。今年はできるだろうか?

ある種AI周辺ツールとしては育休中difitにそこそこコントリビュートして Gerrit スタイルのキーボードナビゲーションを実装したり、diffをstdinから読めるようにして今でも便利に使わせていただいてる。育休後の仕事でも jujutsu (jj) を使うことになったんだけど Vim で jj インテグレーションしてdiff hunk表示する...とかするの面倒になって現状 difit つかってAIが書いたコードレビューしてる。

Gerrit スタイルのキーボードナビゲーション使ってる人が僕以外いるのか定かではないけど、difit おすすめです。

2026年の抱負

(引き続き)ぶさベビちゃんファースト。今年ある程度発語できるようになるかなぁとは思うので成長が楽しみ。

あとはなるようになれの精神。無理せず頑張ります。