新しい PostgreSQL 17 の make dist

PostgreSQL プロジェクトがリリースを行う際、主な成果物はソースコードの tarball の公開です。これは、リリース時点までに PostgreSQL ソフトウェアの作成に関わったすべての作業の成果を表しています。ソース tarball は、その後、パッケージャーによってバイナリパッケージ(またはファイルシステムイメージ、インストールスクリプトなど)を作成するために使用されたり、一部の人々はソースから手動でソフトウェアをビルドするために使用します。

ソースコードの tarball を手動で作成するのは、実際にはかなり厄介です。もちろん、現在チェックアウトされているソースツリーに対して「tar」を実行することもできますが、チェックアウトがクリーンでローカルに変更されていないことを確認する必要があります。また、tarball に含まれるべきファイルがすべてそこにあり、他のファイルが含まれていないことを保証する必要があります。tarball に含めたくない特定のソースコントロールファイルもあります。ファイルの権限や所有権も適切である必要があります。また、これらすべてがプラットフォームや時間を超えて一貫して機能する必要があります。

幸いなことに、これらはすべてスクリプト化されており、長年にわたり非常に信頼性があります。さらに、PostgreSQL のソースコード tarball には、さまざまなプリビルドファイルが含まれています。これらは、実際には Git にチェックインされたソースコードの一部ではないファイルですが、通常のコンパイルの一部としてビルドされるものです。たとえば、ソースコードの tarball には、プリビルドの Bison や Flex のファイル、Perl スクリプトによって生成されたさまざまな .c および .h ファイル、DocBook XML ファイルから生成された HTML および man ページのドキュメントが含まれています。この理由は、便利さと伝統的な慣行の混合です。

これらすべての出力ファイルはプラットフォームに依存せず、ビルドオプションにも依存しません。したがって、誰もが同じものを受け取ることになるため、あらかじめビルドしておくことができます。また、その方法で、ソース tarball のユーザーはこれらのファイルをビルドするためのツールを必要としません。たとえば、ソース tarball から PostgreSQL をビルドするのに Perl は実際には必要ありません。なぜなら、Perl スクリプトから生成されたすべてのファイルはすでにビルドされているからです。また、歴史的に見ても、PostgreSQL は Bison と Flex(またはそれらがまだサポートされていたさまざまな yacc および lex の実装)の限界を押し広げていたため、すべての人に同じプリビルドの Bison と Flex の出力ファイルを提供するのが便利でエラーが発生しにくいものでした。

このシステムには二つの大きな問題があり、これが PostgreSQL 17 で廃止されることになりました。

まず第一に、このアレンジメントをビルドシステムに実装し維持するのは非常に厄介です。「クリーンなソースコード」、「部分的にビルドされたソースコード」、「完全にビルドされたソースコード」の異なる状態を慎重に維持し、それらの間を移行するコマンドを管理する必要があります。(これは make distprep、make all、次に make clean および make maintainer-clean で反対方向に移動するものでした。)アウトオブツリー(「vpath」)ビルドでこれを機能させることは非常に奇妙でした:ソース tarball からビルドすると、Bison(など)の出力ファイルはソースディレクトリにありましたが、Git チェックアウトからビルドすると、Bison の出力ファイルはビルドディレクトリにあり、これらの両方を適切にサポートする必要がありました。最後に、新しい Meson ビルドシステムは、ソースディレクトリにビルド出力を書き込むことに非常にアレルギー反応を示します。

歴史的な理由のいくつかももはや古くなっています。Bison と Flex の良いバージョンをインストールすることはもはや問題ではありません。誰もが簡単に Perl をインストールできるようになりました。ドキュメントのビルドはまだ少し厄介ですが、一般的には数十年前よりもはるかに簡単で堅牢です。

第二に、現在ではソフトウェアサプライチェーンに対してより多くの注意が払われています。これにはセキュリティ上および法的な理由があります。ユーザーがソフトウェアをインストールする際、彼らはそれがどこから来たのかを知りたいと思い、それが正しいものであることを確認したいと思っています。偽のバージョンや法的な出所が疑わしいバージョンではなく。

ダウンストリームのパッケージング慣行は、すでに何年も前からこれに注意を払っています。パッケージやパッケージリポジトリは暗号的に署名されているため、インストールするものが信頼できるソースから来たものであることを確認できます。また、バイナリビルドを再現可能にするための努力もあり、バイナリパッケージ内のバイナリファイルが期待通りのものであることを確認できます。いくつかのパッケージャーはすべてのものがソースからビルドされる必要があるというポリシーを持っているため、プリビルドファイルを削除して再ビルドすることになります。

ソフトウェア生産パイプラインの別の端では、Git をソースコントロールシステムとして使用することで、他の人が得ているのと同じソースコードを取得しているという一定の整合性の保証が得られます。したがって、私がコミット b18b3a8150dbb150124bd345e000d6dc92f3d6dd を見ていて、さまざまな公的なサーバーで同じコミットを見た場合、それはおそらく他の人が見ているのと同じコミットです。そして、そのコミットの親が何であるか、コードがそのポイントに達するまでの経緯などを確認できます。

しかし、これまで私たちには、そのコミットからリリース tarball への透明で再現可能な方法がありませんでした。

tarball 作成の仕組みは、リリースを準備する人がその目的のために特別に「クリーン」に保たれたマシンで make dist を実行するというものです。このプロセスを第三者がどのように検証できるでしょうか?生成された tarball は完全に再現可能ではありません。自分で make dist を実行すると、似ているが同一ではない tarball が得られます。tarball が正常であるかどうかを確認する方法は、解凍して内容をソースディレクトリまたは自分で作成した解凍 tarball と diff することでした。しかし、これには手動の判断が必要です。同じバージョンを使用しない限り、Bison や Flex のファイルは同じにはなりません。ビルドされたドキュメントも完全に同一にはなりません。ファイルのタイムスタンプは異なります。また、ファイルが不足しているか多すぎるかを手動で慎重に確認する必要があります。これは完全に満足のいくものではありませんでした。

(この作業は、XZ Utils のバックドアの発見と重なりましたが、これは(他の要因の中で)まさにこの再現不可能な tarball 作成プロセスを利用していました。しかし、これは完全な偶然であり、この作業はそれに対する応答として行われたものではなく、PostgreSQL の tarball が侵害された可能性についての疑いはありません。)

いずれにせよ、PostgreSQL 17 ではこれが変更されました。tarball の生成は引き続き make dist を呼び出すことで実行されますが、内部では git archive を呼び出します。git archive は、特定の Git コミットに属するファイルを再現可能かつ検証可能な方法で tar(または他の)アーカイブにパックします。したがって、特定のコミット(リリースタグなど)で make dist を実行すると、次の人と全く同じ(ビット同一)tarball が得られます。パッケージャーは、tarball を Git リポジトリにさかのぼることができ、最終的なユーザーはバイナリパッケージを Git リポジトリにさかのぼることもできます(再現可能なビルドを前提とした場合、これは継続的な課題です)。

(明確にするために、この変更は主要バージョン PostgreSQL 17 のみにあり、将来的な主要バージョンにも適用されると思われます。古い主要バージョン(16 およびそれ以前)のメンテナンスリリースは、サポートが終了するまで従来の方法で公開され続けます。)

これを機能させるのも完全に簡単ではありませんでした。プラットフォームやローカル Git 構成全体で一貫して機能させるために、git archive オプションを慎重に調整する必要があります。これが、make dist の呼び出しをラッパーとして保持している理由です。また、これには新しいバージョンの Git(2.38.0 以上)が必要です。

現在、リリース tarballs を生成するために使用されている Git のバージョン(上記の「クリーン」ボックス上)は、再現可能な .tar.gz tarballs を作成するには古すぎますが、再現可能な .tar.bz2 tarballs を作成します。後者は、ほとんどのユーザーやパッケージャーが使用するものです。これを気にする場合は、今のところ .tar.gz を避けてください。

これは、ソフトウェアサプライチェーンの整合性を気にする場合には進展だと思います。(ビルドシステムの維持を気にする場合にも安心です。)確かに、さらに多くのことができるでしょう。上記で言及したことの一つは、再現可能なビルドがすべての状況で PostgreSQL に対して機能しないということです。私の理解では、これは他の場所で修正される必要があります。もう一つは、Git リポジトリに物事がどのように入るかについての追跡性を高めることです。make dist の変更は、コードが Git リポジトリに入った後、それを追跡できることを保証するだけです。理想的には、エンドユーザーのインストールまで追跡することができます。もちろん、PostgreSQL 開発者コミュニティには、ソースコードの整合性を監視するためのさまざまな技術的および社会的プロセスがありますが、現在 Git リポジトリに何が入るかの起源をコンピュータ化された暗号的な方法でチェックするものはありません。したがって、署名付きコミットのようなものは、将来的にさらに改善するために検討する価値があるかもしれません。