blog.anqou.net
rss
author
tags

Nix で N 日前の nixpkgs を使う

サプライチェーンアタックへの対策として、パッケージが公開されてから実際にそのパッケージを使用するまでにしばらく時間を空けるという対策が取られる場合があります。例えば pnpm の minimumReleaseAge が有名です。同じようなことを Nix でやってみます。つまり nixpkgs でリリースされてから N 日立った後のパッケージだけを使うようにしてみます。

新しいパッケージが nixpkgs に取り込まれる場合、まず masterrelease-25.11 ブランチにマージされた後、Hydra でのビルドとテストに成功すると nixos-unstablenixos-25.11 ブランチにマージされる(つまりリリースされる)という手順を踏みます(参考)。したがって nixos-unstablenixos-25.11 ブランチが指すコミットがいつ、どのように変化したかが分かれば、 N 日前のブランチの中身が分かるので対応できそうです。

しかし自分がインターネットを放浪した限りだと、これが分かるような簡単な仕組みは無いようです。というのも nixos-unstable ブランチなどへのマージは fast forward によって行われるようなので、過去にどのコミットがブランチによって指されたものなのかという履歴が残りません。 GitHub のイベントを API 経由で取得することでいつ何が push されたかを確認することができそうですが、これは取得できるイベントの件数の上限が 300 イベント固定で、nixpkgs は非常に頻繁に変更が行われているため全く足りません。過去にはコミットの履歴を保存していた外部のサービスもありましたが、現在は更新が止まってしまっているようです。

ということで、nixpkgs のブランチがどのコミットを指していたかを日付と共に記録するためのシステムを GitHub Actions を活用して作ってみました。その名も github-branch-head-history です:

https://github.com/ushitora-anqou/github-branch-head-history

例えば nixos-unstable の場合、以下の URL でこのブランチが指すコミットがどのように変わってきたかを取得できます[1]

https://raw.githubusercontent.com/ushitora-anqou/github-branch-head-history/refs/heads/master/history/https___github_com_NixOS_nixpkgs_git/nixos-unstable/history.txt

中身は以下のようなテキストファイルで、空白区切りで左から取得日時・コミットハッシュ・コミットの author date・コミットの comimtter date になっています。定期的に起動する[2] GitHub Actions のワークフローによって nixpkgs の現在の状況が取得され、それを踏まえて新しい行が末尾に次々書き込まれる仕組みです[3]

2026-06-10T11:50:12Z a799d3e3886da994fa307f817a6bc705ae538eeb 2026-06-06T12:30:50Z 2026-06-06T12:30:50Z

以下のような awk のスクリプトを使うと、現在から 1 日前までにリリースされた最新のコミットを取得できます。 N 日前にしたい場合は 24*3600 を適当に変えてください:

curl -s https://raw.githubusercontent.com/ushitora-anqou/github-branch-head-history/refs/heads/master/history/https___github_com_NixOS_nixpkgs_git/nixos-unstable/history.txt | awk -v now="$(date +%s)" '
{
    gsub(/[-TZ:]/, " ", $3);
    if (mktime($1) <= now - 24*3600) {
        latest_hash = $2;
    }
}
END {
    if (latest_hash) print latest_hash;
}'

なお github-branch-head-history の中身や上記の awk スクリプトのほとんどは GLM-5.1 によって書かれました。

注釈

  1. といいつつこの記事を書き始める直前に動かし始めたので、執筆時点では一行しか内容がありませんが……。

  2. GHA の cron の機能を使っています。ところでこの機能は最小で 5 分おきにワークフローを起動できるはずなのですが、最近の実績としては約 1 時間おきになっているようです。

  3. こういう仕組みなので、当然全てのマージを追えるわけではなく、見落とすマージが発生します。ただし、ファイルに書き込まれているコミットハッシュはどこかの時点で必ずそのブランチが指していたハッシュ値であるという保証はつきます。