近年はOSS・フリーソフトウェアのリポジトリを公開する場所としてGitHubが選ばれる事が多くなりましたので、フィードバックをする際も、GitHub上のIssuesで障害を報告したり、Pull Requestという形で具体的なソースコードの変更を提案したりといった形を取る事が多くなりました。同様のフィードバック方法が、BitBucketやGitLabなどの競合サービスにおいても可能です。
その一方で、歴史の長いプロジェクトではフィードバックの受け付けがメーリングリストに限られていたり、ソースコードがGitHub等での公開ではないため実装の提案をプルリクエストの形では行えなかったりという事があります。Firefoxもそういった例の1つで、不具合の報告や機能の追加要望はBugzillaで行い、実装内容は伝統的なパッチやPhabricatorといった専用ツールで送付する必要があります。
そこでこの記事では、Windows上でFirefoxに対してパッチを含むフィードバックを行う際の流れをご紹介します。基本的にはHow to submit a patchという記事(日本語訳)に書かれている内容ですが、本記事では周辺情報も併せてまとめています。Firefoxに直接的なフィードバックをしてみたいという方は、ぜひ参考にしてみて下さい。
まずは、ソースコードからFirefoxをビルドできるようにする
パッチを送付するようなフィードバックを行うためには、まずソースコードからFirefoxをビルドできる環境を整えておきます。1行だけの変更なのに大袈裟な……と思うかもしれませんが、Firefoxほどの規模のソフトウェアでは、些細な変更が予想もしない所に影響を及ぼす事があります。ファイルの内容に変更を行う際は必ずビルドと自動テストを行い、後退バグ(regression)が発生していない事を確認する必要があります。
基本的には、Windows上でのビルド環境一式がセットになっている「MozillaBuild」というツールを使う事になります。これにはMSYSベースのUnix系コマンド群やPython、Mercurialなどが含まれています。また、以下の手順の中に含まれていますが、それ以外の必要なツール類も半自動でインストールされるので、準備は非常に簡単です。
以下は、2018年7月3日時点でのビルド環境整備手順の要約となります。
-
MozillaBuildの最新版リリースをダウンロードし、インストールする。一般的には
c:\mozilla-build
にインストールする。 -
C:\mozilla-source
の位置にフォルダを作る。Firefoxのソースコード一式はこの配下に置く事になる。 -
c:\mozilla-build\start-shell.bat
を実行して、MozillaBuildのシェル(Bash)を起動する。 -
export PATH=$PATH:~/.cargo/bin
という行を、~/.bash_profile
、~/.bash_login
、または~/.profile
のいずれかに追記する。echo 'export PATH=$PATH:~/.cargo/bin' >> ~/.bash_profile
のようにするとよい。 -
MozillaBuildのシェルを一旦終了し、
c:\mozilla-build\start-shell.bat
で起動し直す。 -
cd /c/mozilla-source
して、パッチを書く対象となるFirefoxのMercurialリポジトリをcloneする。-
通常は、最新の開発版のリポジトリであるmozilla-centralをcloneする。
hg clone https://hg.mozilla.org/mozilla-central
でcloneできる。以下の説明はこちらのケースを前提とする。 -
ベータフェーズにあるバージョンへのパッチを作りたい場合は、releases/mozilla-betaをcloneする。
hg clone https://hg.mozilla.org/releases/mozilla-beta
でcloneできる。 -
既にリリースされたバージョンへのパッチを作りたい場合は、releases/mozilla-releaseをcloneする。
hg clone https://hg.mozilla.org/releases/mozilla-release
でcloneできる。
-
-
cd mozilla-central
してリポジトリに入り、./mach bootstrap
を実行する。これにより、Visual StudioやRustなどのビルドに必要なソフトウェア群が自動インストールされる。
必要なソフトウェア群が揃ったら、./mach build
でFirefoxをビルドして、ビルドが完了後に./mach run
でFirefoxを起動してみましょう。無事に起動すれば、準備は完了です。
ビルド時間を短縮するには
Firefoxのビルドに要する時間のほとんどは、C++で実装された基盤部分のバイナリのビルド時間です。フィードバックしたい変更がGUI部分のJavaScriptの実装に関わる部分だけであるという場合、ビルド済みバイナリを使ってビルド時間を短縮する事もできます。これはartifact buildと呼ばれます。
artifact buildを使うためには、リポジトリ直下に置く.mozconfig
というファイルを使ってFirefoxのビルドオプションを指定する必要があります。具体的には以下の要領です。
cd /c/mozilla-build/mozilla-central
echo 'ac_add_options --enable-artifact-builds' >> ./.mozconfig
echo 'mk_add_options MOZ_OBJDIR=./objdir-frontend' >> ./.mozconfig
この状態で./mach build
を実行すると、C++のコンポーネントをビルドする代わりにビルド済みバイナリが自動でダウンロードされてきて、それと組み合わせる形でFirefoxがビルドされるようになります。
筆者はJavaScript部分だけのフィードバックとC++部分に関わるフィードバックのどちらも行う場合があるため、/c/mozilla-source/mozilla-central-artifact
と/c/mozilla-source/mozilla-central-full
という具合にリポジトリ自体を2つcloneしておき、片方をartifact build専用にして使っています。
「自分の名前」を設定しておく
作業を始める前に、Mercurialリポジトリへのコミットに表示される作業者名を設定しましょう。これは、MozillaBuildのシェルから見た時に~/.hgrc
の位置にあるファイルで指定します。具体的には、以下のように書きます。
[ui]
username = YUKI "Piro" Hiroshi <yuki@clear-code.com>
パッチを書けそうなBugを報告する、または見付ける
Firefoxでは、不具合の報告や新機能の提案はすべて「Bug」としてbugzilla.mozilla.orgのバグトラッカーで管理されています。
Bugを登録する場合は、まずアカウントを作成してログインします。ログイン済みの状態だと、ページ上部に鉛筆型のアイコンの「File a new bug」というリンクが現れ、そこから新しいBugを報告・登録することができます。Bugの登録時にはまずそれがどの部分(プロダクト)の話なのかを指定する必要がありますが、基本的には、FirefoxというWebブラウザ固有のUIや機能に関わる話題は「Firefox」プロダクト、Thunderbird等と共通の基盤部分のうちJavaScriptで実装されている物は「toolkit」プロダクト、C++で実装された低レベルの基盤技術に関わる物は「core」と覚えておくとよいでしょう。また、プロダクトの選択後はさらに細分化された「コンポーネント」を選択する必要がありますが、リストの中からそれらしいものを選んでおけば大丈夫です。もしプロダクトやコンポーネントを間違えたとしても、他の開発者の人がBugの内容に合わせた適切なプロダクト・コンポーネントを再設定して誘導してくれます。その後、「summary(要約)」と、コメントとして「steps to reproduce(詳細な再現手順)」「expected result(期待される結果)」「actual result(実際の結果)」を入力して投稿すれば、Bugの報告は完了です。
既ににあるBugの中からパッチを書けそうな物を探す場合は、good-first-bug
というキーワードで検索すると、比較的難易度が低いと考えられているBugを一覧表示することができます。興味のある話題のBugを見付けたら、これまでの経緯を読んで、どのようなパッチが求められているのかを読み取ってみましょう。
パッチを書くBugを登録あるいは検索結果から見付けたら、他の人が同時に作業を始めないように、自分がこれからパッチを書いてみますという事を宣言しておくとよいでしょう。これは、単純に「Now I'm trying to write a patch for this bug.」のように書いてもいいですし、「Assignee(担当者)」という欄に自分のアカウント名を設定しても良いです(前者のようにだけしていても、他の人が気を利かせてあなたの名前をAssigneeに設定してくれる事もあります)。
パッチを実際に作成する
準備ができましたので、早速パッチを作ってみる事にします。
クリーンな環境に戻す
以前にパッチを作るために変更した結果が残っていると、作成したパッチが期待と異なる内容になってしまいます。Mozilla公式のリポジトリの内容に対するパッチを作るために、まず以下のようにコマンドを実行し、リポジトリの状態をMozilla公式の物と同じに揃えておきましょう。
hg update -C default # 変更を全て取り消す
hg pull -u # Mozillaのリポジトリから変更点を複製し、手元のコピーに反映する
作業用のブランチを作る
次に、作業用の一時的なブランチを作成します。hg branch fix-bug-xxxxx-working
のように実行して、新しいブランチの作成を予約しましょう(gitではgit checkout -b branch-name
のようにするとその瞬間にブランチが作られますが、Mercurialではこのように「ブランチの作成を予約」した後で何かコミットした段階で初めてブランチが作られます)。
このブランチそのものは、後でパッチを作るための素材として使うだけなので、名前には「working」を付けて作業用である事を示しています。(用事が終わったら、このブランチはhg branch -C xxxxx
コマンドで消去してしまって問題ありません。)
コードを改変する
問題を修正するための変更(新機能を追加するための変更)を行います。変更はhg commit path/to/file
でコミットすることができ、新しいファイルを追加する場合はhg add path/to/file
でリポジトリに登録できます。作業経過を失わないように、こまめに「Bug XXXXX - 変更の概要」といった要領のコミットメッセージを付けてコミットするようにしましょう。コミット時にはEmacsが起動しますが、普通にコミットメッセージを入力して、上書き保存して終了すればOKです。
方針を間違えたなどの理由でコミットを取り消したくなった場合は、hg log -G
でコミットツリーを表示して、取り消したいコミットの番号(XXXX:YYYYYYY
という形式の、数字と文字列の組)を調べた上で、調べたコミットの番号の「:」より手前の数字を指定してhg strip XXXX
と言うコマンドを実行します。こうすると、指定したコミットとその後に続くコミットが無かったことになります。
また、コミット単位ではなく作業そのものを最初からやり直したいという場合には、ブランチそのものを破棄して作り直すのが手っ取り早いです。その場合はhg update -C default
でデフォルトブランチに戻した上で、hg branch -f fix-bug-xxxxx-working
と-f
オプションを付けて同名のブランチ作成を予約すれば、ブランチ作成の時点から作業をやり直す事ができます。
自動テストを書く
不具合の修正でも新機能の追加でも、対応する自動テストの追加は原則として必要です。変更対象のファイルの近傍に自動テストのファイル群が配置されている事が多いはずなので、それらを参考にして、関連していそうなテストファイルにテストケースを追加したり、あるいはテストのファイルそのものを新たに追加したりしましょう。
新しいテストファイルを追加する場合は、hg add
でのリポジトリへの登録だけでは不十分で、同じディレクトリのini
ファイルにもテストファイル名を追記する必要があります。
自動テストを実行する
自分で追加した自動テスト(テストケースを追加したファイルや、自分で追加したテストファイル)は、./mach test path/to/test/dir/or/file
とすると適切なフレームワークで実行する事ができます。テストが確実に通る事を確認しておきましょう。また、ディレクトリを指定すると複数のテストを一括実行できますので、関連する他の機能に意図しない影響を及ぼしていないか(他のテストが失敗するようになっていないか)も確かめておきましょう。
(なお、何度もパッチを投稿していると、tryserverという自動テスト専用のサーバーの使用権を貰えることがあります。tryserverを使うとWindows以外のプラットフォームでも自動テストを実行できますし、手元での実行ではないのでテストの実行中も他の作業を並行して行えるので、非常に有用です。tryserverの使用権を持っている場合は、./mach try -b o -p linux,macosx64,win64 -u all -t none --no-artifact
というコマンド列を実行するだけで、現在作業中のブランチの内容を反映した状態でtryserver上で全てのテストを実行する事ができます。)
コーディングスタイルを揃える(2019年4月12日追記)
実装も自動テストも両方揃ったら、コーディングスタイルがMozillaのルールに則っているかも確認しておきましょう。せっかくパッチを提出しても、コーディングスタイルがMozillaのルールに則っていないと受け付けてもらえません。
コーディングスタイルのチェックは、文法チェックの一環として./mach lint (チェックしたいファイルのパス)
で行えます。例えば以下の要領です。
./mach lint browser/components/extensions/test/browser/browser_ext_sessions_restoreTab.js
文法チェックでエラーが出なくなったら、パッチを提出できるクオリティに達したと判断して次のステップに進みます。
変更の完了とパッチ作成の準備
作業用ブランチ上で複数回コミットしていた場合、変更内容を1つにまとめたコミットを作成してパッチにします。これは以下の手順で行うことができます。
hg diff -r default > ../working.diff # 変更内容を差分ファイルに出力する
hg update -C default # デフォルトブランチに切り替える
hg pull -u # 念のためデフォルトブランチの状態を最新にする
hg branch -f fix-bug-xxxxx # ブランチを作り直す
patch -p 1 < ../working.diff # 差分ファイルに出力した内容を書き戻す
hg add path/to/added/files # ファイルを追加していた場合は、この時点で手動で追加し直す。
hg commit
この時のコミットメッセージは「Bug XXXXX - 変更の概要」のようにします。このコミットメッセージはパッチに含まれる事になります。
複数回のコミットがあった状態のままでパッチを作成すると、1コミットが1パッチとして分割される事になります。大規模な変更を行う場合はパッチも複数に分けて段階的に反映する場合がありますが、そのような大規模な変更を行う機会は一般の外部コントリビューターはまず行う機会がありませんので、基本的には上記の手順で1コミットにまとめるようにしましょう。
なお、自分が作業を始めた時点のデフォルトブランチの状態とhg pull -u
で更新したデフォルトブランチの状態が異なっていた場合(自分が作業中に他の人の変更が反映された場合)、パッチの適用に失敗する事があります。このような場合、衝突箇所を修正して(自動テストも再実行して)、「最新のデフォルトブランチに対して行った変更」という体裁のパッチに手直しする必要があります。
パッチの提出
準備が整ったら、このブランチの変更内容をパッチとしてBugに添付します。
2019年4月12日現在、パッチはPhabricatorというレビューツールを使って提出するようになっています。Phabricatorによるパッチの提出手順は別の記事で詳しく説明していますので、そちらを併せてご覧下さい。以下は、何らかの理由でPhabricatorを使用できない場合に使う、伝統的な差分ファイル形式でのパッチの提出手順の解説となります。
hg bzexport -e
というコマンドを実行すると、Emacsが起動してコメントの入力を求められます。対応するBugの番号が最初の行に「Bug XXXXX」と表示されていれば大丈夫なので、そのまま保存して終了して下さい(「No changes made; continue with current values (y/n)?」と訊かれるので、yと入力して下さい)。コミットメッセージにBugの番号を入れ忘れていた場合は、対応するBugの番号を「Bug XXXXX」のように記入した上で、変更を保存してEmacsを終了します。すると、パッチがBugに自動的に添付されます。
(なお、同じBugに複数回パッチを送信すると、前のパッチは自動的に「Obsolete」扱いになります。)
Mercurialの拡張機能がまだインストールされていないと、hg bzexport -e
はエラーになります。その場合は、先に./mach mercurial-setup
を実行して必要なプラグインをMercurialにインストールしておくか、またはhg export > ./bugXXXXX.patch
で手動でパッチを作成して手動で当該Bugにファイルを添付します。この場合、古いパッチを適宜手動で「obsolete」にする必要があります。
Mozillaでは、全てのパッチはレビュアーによるレビューを経てからマージされる運用になっています。このパッチをFirefoxに取り込んでもらうためには、レビューを依頼しなくてはいけません。
パッチがBugに添付されたら、Bugのページをブラウザで開いて、添付されたパッチの「Details」のリンクをクリックします(hg bzexport
を使わない場合は、パッチファイルの添付時のフォームでそのまま操作します)。「review」という欄があるので「?」を選択し、その隣の入力欄にレビュアーを指定してレビューを依頼します。基本的にはそのモジュールの担当者を設定するのですが、誰に依頼したらいいか分からない場合は、suggested reviewersという所をクリックすると、お薦めレビュアーが出てきます(モジュールから自動的に検索された結果が一覧表示されます)。基本的には、レビューのキューの数が少ない人を設定するのがお薦めです。ただし、レビューの件数が多くても猛烈なスピードで消化する人や、レビューの件数が少なくてもなかなかキューが減らない人もいるので、できれば類似のBugを見て活動がアクティブな人を設定する方が望ましいです。あるいは、変更対象のファイルの変更履歴を確認し、最近投入されたパッチのレビューを担当した人を設定するのも有効です。
その後、指定した人物によりレビューが行われます。レビューを無事通過できれば、パッチのメタ情報に「r+」と表示されるようになります。
パッチの内容に不具合や考慮不足、コーディングルールに反している部分などがあると、レビューが却下され、パッチのメタ情報のステータスが「r-」になります。その場合は、指摘された問題点を修正してパッチを再提出しましょう。
なお、このように伝統的な差分ファイル形式のパッチを使ったパッチ提出のやり方の他に、2019年4月12日現在ではPhabricatorという専用の仕組みを使ったレビュー運用も行われています。こちらについては別の記事で詳しく解説します。
チェックインの依頼
パッチのステータスが「r+」になったら、いよいよチェックインです。Bugの「whiteboard」欄にcheckin-needed
と記入してBugを更新しておくと、担当者の人がそれを見付けて、だいたいその日の中に「inbound」というリポジトリにパッチをチェックインしてくれます。このinboundの自動ビルドと自動テストで何もエラーが検出されなければ、同じ内容が自動的にmozilla-centralなどのリポジトリにチェックインされます。
もしinboundのビルドや自動テストが失敗した場合は、その旨のコメントがBugに書かれますので、適切に対応してパッチを再提出する事になります。もし自分の行った変更が原因で他の自動テストが失敗したようなら、それらのテストに悪影響を与えた原因を修正したり、あるいは、もし他の部分の方に問題がある場合(例えば、やっつけで実装されていたテストが、自分の行った変更の影響で失敗するようになった場合など)はそちら側を修正したりします。
また、inboundへのチェックイン自体に失敗したという事でパッチが差し戻される事もあります。これは、自分が作業した時のデフォルトブランチの状態と、担当者がinboundにパッチをチェックインしようとした時の最新の状態とがずれていて、パッチが衝突してしまったという場合に起こります。その場合、複数コミットを1つのコミットにまとめる時と同じ要領で、最新のデフォルトブランチを対象にしてパッチを作り直しましょう。他の変更と衝突はしていたものの、パッチは全体的に以前の物から代わっていないと言える場合は、再レビュー依頼を省略できます。再提出したパッチに対して「r?」を設定する代わりに「r+」を自分で付けて、コメントには「r+ is carried-over from the previous patch」のように書いておきましょう。
Beta版のBugを直したい場合は
次期リリースのBeta版を使っていて見付けた問題でも、まずはmozilla-centralに対して修正を行います。以下は、変更が既にmozilla-centralに反映されたという前提での話になります。
まず、releases/mozilla-betaのリポジトリをローカルにcloneして、mozilla-centralにチェックインされたパッチをpatch -p 1 < path/to/patch.diff
で反映します。もし衝突が発生してパッチを反映できなかった場合は、衝突箇所を修正してコミットし、新しいパッチを作り直して改めて提出します。内容的に変更がなければ、ここでもレビューを省略して「r+」を自分で付け、前のパッチからレビュー済みの状態を引き継いだ旨を書いておきます。
元のパッチがそのままBetaに反映できる状態、またはBeta向けにパッチを再提出し終えた状態で、そのパッチをreleases/mozilla-betaに取り込んでもらうよう依頼する事を、uplift申請と言います。Beta版またはリリース版に対しては原則としてこのuplift申請を経由してパッチが取り込まれるようになっています。
uplift申請をするには、当該パッチの詳細情報の画面で「approval-mozilla-beta」欄に「?」を設定します。すると、コメント入力欄にuplift申請のテンプレートが自動入力されますので、「ベータフェーズでクオリティを高める段階にある今、新たな問題を引き起こすリスクを押してでもこの変更を反映するべき理由」「この変更を反映しても問題は起こらないと言える理由」を説明するよう各欄を埋めて投稿します。実際の申請例(Firefox 60betaに対して、セーフモード無効化のポリシー設定を導入するパッチのuplift申請を行っている物)も参照して下さい。申請が受理されれば、パッチはチェックインされます。
充分な理由を示せていなかった場合、申請は却下される場合もあります。その場合、改めてその修正の重要性を説明し直したり、味方に付いてくれる人(Mozillaの中の人)にコメントを求めたりという形で、説得・交渉を行う事になります。
まとめ
以上、Windows上での作業を前提とした、Firefoxへのパッチ提出の流れを解説しました。
「Firefoxのような大規模プロジェクト、しかもGitHubではない独自のやり方でソースコードや問題を管理している所にコントリビュートする」というのは、GitHub上でフィードバックした事がある人でも、心理的に高いハードルがあるかもしれません。しかし、根本的な部分ではそう大きな違いはなく、むしろ、Bugzillaのような高機能のバグトラッキングシステムやinboundのような規定は、GitHub上でのプロジェクト運営では「運用でカバー」されているものをシステムとしてきちんと体系化した物と言う事ができるでしょう。皆さんも必要以上に恐れずフィードバックしてみて下さい。