ADR-0013: dowel 自体の取得は別バイナリが担い、参照は commit sha に固定する
状態: Accepted
文脈
dowel を使うプロジェクトが、使用する dowel の版を宣言し、環境に依らず 同じ版でビルドできる必要がある。rustup が確立した使用感(stable / nightly、 任意の版の指定、プロジェクト単位の固定、透過的な切り替え)に加えて、 リリースが未整備である現状では、上流の特定の branch / commit を 直接使えることが要る。
決める点は3つあった。
| 論点 | 選択肢 |
|---|---|
| 機構の置き場所 | A. 本体に内蔵(dowel self install) / B. 別バイナリ / C. ブートストラップスクリプトのみ |
| 取得の手段 | git / cargo の起動に委譲する / HTTP クライアント等の crate を導入する |
| 固定として記録するもの | commit sha / チャネル名やブランチ名のまま |
前提となる規約: 「外部の成果物はすべて一意に固定する。タグやブランチ名のみに よる参照は固定とみなさない」(50-development.md 5節)。
決定
案 B を採る。取得・固定・切り替えは別バイナリ dowelup(crates/dowel-up)が担う。
- 取得はソースからのビルドとし、
git(clone / fetch / 参照の解決)とcargo(ビルド)の起動に委譲する。dowelup 自身も外部 crate に依存しない (ADR-0007) - すべての指定子(
stable/nightly/nightly-<日付>/X.Y.Z/branch:<名前>/tag:<名前>/ sha)は、install/pin/defaultの 時点で commit sha に解決され、以後は sha が正本になる。 インストール先は$DOWELUP_HOME/versions/<sha>/ - プロジェクトの固定は
.dowel-versionに書く。書かれるのは解決済みの sha であり、チャネル名やブランチ名は書かない dowelという名前で起動された dowelup(シンボリックリンク)は shim として 働き、.dowel-version→ 既定、の順で版を選んで exec する。 この経路はネットワークに触れない
根拠
別バイナリにする理由。 更新機構が更新対象の中にあると、壊れた版を 掴んだときに脱出手段も一緒に壊れる。また、実行中の自分自身を置き換える 処理は固有の問題(実行中バイナリの上書き、途中失敗時の状態)を持ち込み、 起動時間の予算(20-architecture.md 5.4)を持つ 本体の起動経路に分岐を足すことになる。rustup / rustc の分離と同じ判断である。
案 C を採らないのは、1回きりの取得しかできないためである。プロジェクト単位の pin と透過的な切り替えは、起動のたびに版を選ぶ常設の入口を要する。
外部コマンドへ委譲する理由。 ソース取得に必要なプロトコル(HTTPS、SSH、 git プロトコル)を自前実装するか crate を導入するかの二択を避けられる。 実行層を ninja に委ねた判断(00-overview.md 7節)と 同じく、確立したツールの責務は奪わない。
sha に固定する理由。 タグとブランチは可動であり、規約上も固定と みなさない。sha を正本にすると、(1) 同じ pin からは常に同じ内容が得られ、 (2) shim の選択がネットワークに触れずに決定でき、(3) 将来 prebuilt 配布 (Q10)を足しても pin の形式が変わらない。
帰結
dowelupの名は仮称dowelに追随する(ADR-0006)。 名称の確定時に一緒に改名するstableとX.Y.Zは、上流に release タグが現れるまで解決できない。 それまでは nightly / branch / sha を使うnightly-<日付>は「既定ブランチに、その日(UTC)の終わりまでに入った 最後のコミット」と定義する。rustup のような日次アーカイブを持たないため、 日付は履歴への問い合わせで解決する- 取得には Rust ツールチェーンを要する。prebuilt バイナリの配布と その検証は未決事項とする(Q10)
.dowel-versionに手書きでチャネル名を書いた場合、shim は解決せずに 誤りとして拒む。暗黙にネットワークへ触れないための制約であり、dowelup pin <指定子>が解決して書き直す- ネットワークに触れるのは
install/pin/defaultのみ