この記事は Node.js Advent Calendar 2019 - Qiita の2日目の記事です。遅くなってしまいました。
Node.js本体へのコントリビュート解説記事です。この記事は不足している情報や更新があれば、モチベーションが続く限り更新していきたいと思っています。
JSConf JPのスタッフの打ち上げのときに日本人のNode.jsへのコミットしている人が少ないという話がでました。
Node.jsに限らずOSSへのコミット経験があるという人は私の周りには少ないです。
もちろんOSSにコミットしているから良い悪いという話ではなく、Node.jsやOSSにコミットしてみたいと相談いただくことが時々あるので僕の経験でよければ伝えたいと思いました。
私の経験からNode.jsへのコントリビュート方法の解説とOSSへの貢献を通じて得たものについて書き残しておきたいと思います。
言葉の定義として、コードやドキュメントにコミットするだけでなく、「Issueを作る」「Pull Requestを送る」をまとめてコントリビュートと呼ぶことにします。
Node.jsのコントリビュートについてはGitHubのNode.jsのリポジトリに書かれています。
また、 大津さん(@jovi0608)が2016年のCode And Learn用に翻訳を公開してくれています。
今回はこのドキュメントをもとに私の経験や補足を合わせて解説します。
また、Node.jsのコラボレーターになったときに書いた記事もご興味あればご一読ください。
目次
- 目次
- 解説をする前に
- Node.jsへのコントリビュート解説
- 英語について
- Node.js コア以外へのコントリビュート
- はじめてのOSSへの貢献
- OSSに貢献するということ
解説をする前に
Node.jsにはmasterブランチへのwriteの権利を持っていてコードレビューを行ったりCIを実行する人々が世界中にいます。彼らのことをコラボレーターと呼びます。
さらにコラボレーターの中から数名が仕様を決めるTechnical Steering Committee(通称TSC)がいます。
彼らだけがNode.jsの開発をしているわけではありません。定常的にコミットはしなくてもコードやドキュメントの修正を行ってくれたりIssueを作って議論してくれるコントリビューターがいるからこそNode.jsはこれまで生存してきました。
Node.jsに限らずOSSはそういった人々に支えられています。
なので、基本的にコラボレーターはコントリビューターに対して感謝の気持ちを持っています。できるだけ気持ちよく開発できるように心がけている人が多いと感じます。
なので、恐れずにチャレンジしてほしいと思います。
Node.jsへのコントリビュート解説
Code of Conductを読む
Code of Conductとは行動規範です。
OSSは様々なバックグラウンドを持った人が関わっています。Node.jsも例外ではありません。
そのためOSSではCode of Conductを守ることは最も大切なことと言っても過言ではありません。
必ず読みましょう。
https://github.com/nodejs/node/blob/master/doc/guides/contributing/coc.md
過去にCode of Conductを違反したことがきっかけでコアメンバーの除名処分が議論されたこともありました。
yosuke-furukawa.hatenablog.com
Issueを作る
Issueによるバグ報告や質問やフィードバックや機能要望はとても大切なコントリビュートの一つの形です。
Node.jsに関するIssueには2種類あると考えています。
1つ目がNode.jsを使った開発に関する質問、2つ目がNode.jsコアに関する質問やバグ報告や機能要望などです。
細分化するともっとあるかもしれませんが、大きく分けるとこの2つだと考えています。
どちらのIssueにしても直面した問題や質問に関してできるだけ詳しく書くことが解決への一番の近道だと思います。
Node.jsを使った開発に関するIssue
Node.jsを使った開発に関する質問は、nodejs/helpにIssueを作るとよいでしょう。 nodejs/nodeの方にIssueを作ったからといって怒られたりすることはないと思いますが、nodejs/helpの方に書くように促されることはあるかもしれません。
Issueテンプレートが用意されているので、Issueを作ろうとすると以下のように本文にテンプレートが最初から書かれています。

以下のようにNode.jsのバージョン、動かしたOSのバージョン、スコープ、関係のあるパッケージ(なければ省略)を書いてください。
- Node.js Version: 12.2.0
- OS: macOS 10.13.6
- Scope (install, code, runtime, meta, other?): install
- Module (and version) (if relevant): jest
Node.jsコアに関するIssue
Node.jsコアに関する質問やバグ報告や機能要望などは、nodejs/nodeにIssueを作るとよいでしょう。
コアというのはNode.js本体のことを指します。
例えば、Node.jsでファイルシステムを操作するfsにバグがあったり、機能追加の要望を出したい、という場合です。
nodejs/nodeのNew Issueボタンを押すと以下のような選択画面が表示されます。

この画面では以下の選択肢があります。
- Bug report: バグ報告
- Feature request: 機能要望
- Report a security vulnerability: 脆弱性報告。セキュリティポリシーへのリンクになっています。
- ⁉️ Need help with Node.js?: Node.jsに関する質問。先に紹介したnodejs/helpへのリンクになっています。
- 🌐 Found a problem with nodejs.org?: Node.js公式ウェブサイト nodejs.org に関する問題報告です。nodejs/nodejs.orgのissue作成画面へのリンクになっています。
ここでは上記のBug reportについて説明をします。
Bug reportを選択すると以下のようにIssueテンプレートが書かれた画面が表示されます。

そこに以下のようなバージョン情報とモジュール名を記載します。
- Version: 13.1.0
- Platform: macOS 10.14.6
- Subsystem: fs
Subsystemについて
このSubsystemには以下の中からリポジトリ内のどこに問題があったかを書きます。
lib/*.js(assert,buffer, etc.)builddoclib / srctesttools
lib/*.jsはassertやfs、stream...などNode.jsコアが提供しているモジュールを書いてください。
Subsystemについて難しい場合は、以下を基準にしてください。
- コードに関すること:
lib / src - Node.jsコアのビルドに関すること:
build - nodejs.org/api などドキュメントに関すること:
doc - nodejs/node内で実行するNode.jsコアのテストに関すること:
test - nodejs/node内で使っているツールに関すること(e.g. eslint):
tools
また、IssueやPull RequestのタイトルにもこのSubsystemを用います。
例えば fs: fsPromises.lchmod throws AssertionError on Ubuntuといった感じのタイトルにすると良いでしょう。
Issueの場合、必ずしもSubsystemの記載が必要とは思いません。そこで挫折してIssueを送らないのであれば、書かずに送ってしまってもいいと個人的には思います。
前述のとおり本文をしっかり書いて伝わりやすくすることが大切だと思います。
また、コードやエラーの内容を載せると伝わりやすいです。私が書いたIssueで宜しければ以下を参考にしてみてください。
Pull Requestを送る
Pull Requestを送ることはIssueを作ることに比べるとやはり敷居が少し高くなります。 コマンドによる操作やGitの操作に不慣れだと難しいかもしれません。
しかし、送ってマージされてもされなくても学びがあったり感謝されることが多いです。多くの場合、コラボレーターから感謝されるでしょう。
この章ではPull Requestを送るときのルールや気をつけること、どのようなPull Requestから始めるのがよいか説明したいと思います。
Pull Requestを送るまで
手順が多いのでおおまかな流れを先に説明しておきます。
- nodejs/nodeをForkしてgit cloneする
- nodejs/nodeを
git remoteで追加する - nodejs/nodeのビルド環境を構築する
- ブランチを作成する
- コードやドキュメントを修正する
- ビルドして動作確認を行う
- テストやLintを実行する
- ForkしたリポジトリにPushする
- nodejs/nodeのmasterブランチに対してPull Requestを作成する
一つずつ説明します。
nodejs/nodeをForkしてgit cloneする
Node.jsのリポジトリに直接ブランチを作らずにForkしてPull Requestを送ります。
nodejs/nodeリポジトリの右上に表示されているForkボタンを押してForkしてください。
その後、Forkしたリポジトリをローカルの任意の場所にgit cloneしてください。
nodejs/nodeをgit remoteで追加する
前述でgit cloneした後にgit remoteを実行すると以下のようにoriginのみが表示されると思います。

しかし、nodejs/nodeとコンフリクトが起きるかもしれないので、Pull Requestを送る前にnodejs/nodeのmasterにrebaseしましょう。そのためにupstreamとしてremoteに追加しておきましょう。
$ git remote add upstream git@github.com:nodejs/node.git
Node.js のビルド環境を構築する
Node.jsの大部分はC++とJavaScriptによって書かれています。ビルドツールにはPythonが使われています。
以下に記載があります。
node/BUILDING.md at master · nodejs/node · GitHub
OSによって異なります。
macOSの場合
以下が必要になります。
- Xcode Command Line Tools >= 10 for macOS
- Python 2.7
- Python 3.x系はまだ実験的に導入している段階です。2.x系のサポート終了も近く現在3.x系への移行が進められています。
Xcode Command Line Toolsを使うにはXcodeをインストールし、xcode-select --installを実行する必要があります。
ビルドの確認はgit cloneしたnodeディレクトリ内に移動して以下を実行します。
$ ./configure $ make -j4
makeコマンドの-jオプションは並列処理するジョブを設定することができます。-j4は4並列で処理するように設定しています。並列処理することでビルド時間の短縮に繋がります。
この数値はCPUの数やCPUの数×2など諸説あったり環境によって違ったりするので、値を変更して試してみてください。
./node -vを実行し、Node.jsのバージョンが表示されれば環境構築は完了です。
macOSをお使いで途中でエラーが発生した場合は以下のコマンドを実行してみてください。
$ sudo ./tools/macos-firewall.sh
Windowsの場合
公式には色々と書かれていますが、実は一発で構築してくれるnpmパッケージが存在します。
Node.jsがインストールされていてnpmが実行できるのであれば以下のコマンドを実行してみてください。
$ npm install --global windows-build-tools
このnpmパッケージを使うことでVisual C++やPython2.7が勝手にインストールされます。既にインストールされている場合はスキップします。
ビルドの確認はgit cloneしたnodeディレクトリ内で以下を実行します。
> .\vcbuild
./node -vを実行し、Node.jsのバージョンが表示されれば環境構築は完了です。
ブランチを作成する
Pull Requestを送るためにブランチを切りましょう。
ブランチ名に関しては特にルールはありません。わかりやすい名前にしてください。
またupstreamのトラッキングが必要な場合は以下のように-tオプションを付けてブランチを作成してください。
$ git checkout -b my-branch -t upstream/master
コードやドキュメントを修正する
ディレクトリ構成
先に簡単に説明しておきます。
node ├── .github ├── benchmark ├── deps ├── doc ├── lib ├── out ├── src ├── test └── tools
- .github: IssueやPull Requestのテンプレートなどが置かれています。
- benchmark: ベンチマークを測るためのコードが置かれています。パフォーマンスに影響が出そうな修正を行うときはここにもコードを追加する必要があります。
- doc: ドキュメントが置かれています。Markdownで書かれています。https://nodejs.org/api のドキュメントもここで管理されており、
doc/apiの中に全部置かれています。 - deps: Node.jsが依存している他のOSSなどが置かれています。JSエンジンのV8やイベントループ処理をするlibuvもここに置かれています。それらのバージョンアップするときはここに取り込みます。
- lib: JavaScriptのコードが置かれています。主に
fsやstreamなどのAPIの入り口はここに書かれます。最近はなるべくC++に処理を書かずにJavaScriptに処理を書いていこうという方針が取られています。機能追加をしたいときはまずはここにJavaScriptで実装してPull Requestを送ると良いでしょう。 - out: これはビルド結果が出力されるディレクトリです。C++のコンパイル後のモジュールやRelease用のnodeのバイナリが出力されたりします。
- src: C++のコードが置かれています。主にV8の機能やlibuvの機能を使うコードが置かれています。また、JavaScriptではパフォーマンス上問題があるものもC++で書かれることがあります。nodeの起動エントリポイントはmain.ccというところにあります。
- test: テストコードが書かれています。主にNode.jsが提供しているAPIのテストが書かれています。並列実行できるように
parallelディレクトリに書くことが多いですが、直列実行が必要な場合はsequentialディレクトリに書く必要があったりネットワークが必要であればinternetディレクトリに書く必要があったりします。基本的にlibやsrcを修正するときはtestの修正も必要です。 - tools: nodeの開発に使うツールが置かれています。eslintやテスト用のPythonスクリプトなどがここに置かれています。
主にdoc、lib、src、testを修正することが多いと思います。
deps内のV8やlibuvやOpenSSLのバージョンアップに関しては詳しいメンバーに任せた方がいいかと思います。
コードスタイル
Lintがあるので、基本的に修正してコミットする前はLintを実行するようにしましょう。
$ make lint
また、.editorconfigがリポジトリ内に含まれているので、お使いのエディタのプラグインなどを使ってフォーマットかかるようにしてもいいと思います。
詳しくは以下にまとまっています。
https://github.com/nodejs/node/blob/master/doc/STYLE_GUIDE.md
https://github.com/nodejs/node/blob/master/CPP_STYLE_GUIDE.md
コードやドキュメントを修正する
バグ修正や機能追加など明確に課題がありlibやsrcを修正する必要がある場合は、もちろんlibやsrcのコードを修正してコミットするのが良いでしょう。
libやsrcを修正したときはtestにテストコードを追加してください。
しかし、明確なバグや機能追加に関しては特にないけど「Node.jsへのコミットがしてみたい」という方には以下の「テスト」「good first issue」「ドキュメント」へのコミットをオススメします。
テスト
Node.jsのテストはカバレッジが公開されています。まだ網羅されていないモジュールのテストがあればカバーするテストコードを追加するのがわかりやすいと思います。
テストを書くことで、libやsrcの構成についても徐々に把握していくことができると思います。
コードリーディングを通して知らないAPIを知ることもでき、テストといえど学ぶことが多いです。
id:yosuke_furukawa に勧めていただきfsのPromiseのAPIのテストのカバレッジを増やしていくところから始めました。
上記のPull Requestのように初めてのコミットではCongratulations @shisama on your first commit in Node.js core! 🎉 🎉 🎉のようにコメントがもらえることが多く、Node.jsのメンバーの人の良さが伝わります。
テストを増やしていくことはとても大切なことです。
以下のようにテストのカバレッジが低いとIssue管理されます。
good first issue
多くのOSSのIssueにはgood first issueというラベルが用意されていると思います。
nodejs/nodeのgood first issueのラベルが付いたIssue一覧: Issues · nodejs/node · GitHub
このgood first issueというのは初めてコミットする人にオススメのIssueということがわかるように付けられるラベルです。このラベルのIssueを見つけた場合はチャレンジしてみるとよいでしょう。
ドキュメント
APIのドキュメント内でtypoを見つけたり、サンプルコードの不備を見つけたときはdocにコミットしてみるのも良いと思います。
Lintを実行する
環境に合わせて以下のコマンドからLintを実行してください。markdownやC++やJavaScriptの静的解析が走りコードスタイルのチェックなどを行います。
$ make lint
Windowsの場合
> vcbuild.bat lint
テストを実行する
環境に合わせて以下のコマンドからテストを実行してください
$ ./configure && make -j4 test
Windowsの場合
> vcbuild test
さらに詳しくは以下のテストガイドラインをお読みください。
node/writing-tests.md at master · nodejs/node · GitHub
テストカバレッジを取る
テストのカバレッジを取得したい場合は以下のコマンドにてテストを実行します。
$ ./configure --coverage $ make coverage
テストが完了すると以下のファイルをブラウザで確認してください。
カバレッジはlibとsrcで分かれています。
- lib(JavaScript):
coverage/index.html - src(C++):
coverage/cxxcoverage.html
ビルドして動作確認を行う
nodejs/nodeのビルドには前述のとおりmakeコマンドを用います。
$ ./configure $ make -j4
-jオプションについても前述のとおり、お使いのCPUの数に合わせて適宜変更してください。
Windowsの場合
> .\vcbuild
ビルドが成功するとnodeディレクトリの直下から./nodeを実行してNode.jsのREPLが起動することを確認してください。
その後修正した内容に応じて動作確認を行ってください。
コミットする
修正したファイルをgit addしてgit commitするだけです。
$ git add my/changed/files $ git commit
このときにコミットメッセージに注意してください。
コミットメッセージ
Node.jsではコミットメッセージにルールがあります。
- 1行目は
subsystem名: 修正内容の概要を書かなければいけません。 - 2行目は空白の改行にしてください
- 3行目以降はコミットに関する詳細を書いてください。1行目だけで伝わる場合は3行目以降は不要です。
- この3行目以降に関連するIssueやPull Requestなどのリンクを貼ってください
- コミットにより閉じれるIssueがある場合は
Fixes: https://github.com/nodejs/node/issues/1337のようにFixes:から始めて書いてください - 関連する参考リンクは
Refs: https://github.com/nodejs/node/pull/3615のようにRefs:から始めて書いてください
- コミットにより閉じれるIssueがある場合は
- この3行目以降に関連するIssueやPull Requestなどのリンクを貼ってください
まとめると以下のように形になります。
subsystem: explain the commit in one line The body of the commit message should be one or more paragraphs, explaining things in more detail. Please word-wrap to keep columns to 72 characters or less. Fixes: https://github.com/nodejs/node/issues/1337 Refs: https://eslint.org/docs/rules/space-in-parens.html
ルールに沿わなかったからといって問題にはならないですしコラボレーターが優しく教えてくれると思います。なので、気負わずPull Requestを出してください。
Rebaseする
Pushする前にgit remote addしたupstream/masterにgit rebaseしてください。
$ git fetch upstream $ git rebase upstream/master
git rebaseすることでnodejs/nodeの最新の状態を取り込むことができます。
ForkしたリポジトリにPushする
Forkした自分のnodeリポジトリにPushする前に念の為git remoteで確認してください。
私の場合はFork先がshisama/nodeのため、以下の結果になります。
$ git remote -v origin git@github.com:shisama/node.git (fetch) origin git@github.com:shisama/node.git (push) upstream git@github.com:nodejs/node.git (fetch) upstream git@github.com:nodejs/node.git (push)
originのリポジトリが自分がForkしたリポジトリになっていることを確認したら、originにPushしてください。
以下はfix-foo-barブランチをpushする例です。
$ git push origin fix-foo-bar
Pull Requestを作成
nodejs/nodeをブラウザで開くと、右上に以下のボタンが表示されていると思います。

以下のボタンを押してください。

すると、以下の画面が表示されます。

本文には以下のテンプレート文章が入力されています。
<!--
Thank you for your pull request. Please provide a description above and review
the requirements below.
Bug fixes and new features should include tests and possibly benchmarks.
Contributors guide: https://github.com/nodejs/node/blob/master/CONTRIBUTING.md
-->
##### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
- [ ] `make -j4 test` (UNIX), or `vcbuild test` (Windows) passes
- [ ] tests and/or benchmarks are included
- [ ] documentation is changed or added
- [ ] commit message follows [commit guidelines](https://github.com/nodejs/node/blob/master/doc/guides/contributing/pull-requests.md#commit-message-guidelines)
<!--
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
-->
<!-- -->で囲まれている部分は変更する必要はありません。
この中で重要なのはチェックリストです。
確認した事項にチェックを入れていってください。
- [ ]
make -j4 test(UNIX), orvcbuild test(Windows) passes - [ ] tests and/or benchmarks are included
- [ ] documentation is changed or added
- [ ] commit message follows commit guidelines
日本語に訳すと、
- [ ]
make -j4 test(UNIX) またはvcbuild test(Windows) が通ること - [ ] テスト(
test)やベンチマーク(benchmarks)が含まれていること - [ ] ドキュメントが変更、追記されていること
- [ ] コミットメッセージが ガイドラインに従っていること
コミット内容によっては全てチェックする必要はありません。
例えば、テストを追加しただけの場合はドキュメントの変更などは無いのでdocumentation is changed or addedにはチェックを付ける必要はありません。
また、本文に追加情報が必要な場合は書いてください。
ここまできたらCreate pull requestボタンを押してPull Requestを送ってください。
コードレビュー
Pull Requestを送るとNode.jsのコラボレーターのメンバーがコードレビューしてくれます。
もし、なかなかコードレビューしてくれなければ @nodejs/collaboratorsとコメントしてコラボレーターにメンションしてください。
コードレビューで指摘があった場合は適宜修正したり議論してください。
CI
コードレビューで承認され始めるとコラボレーターがCIを実行してくれます。このCIはJenkinsで動いています。
Node.jsは様々な環境で動作しなければいけないため、数種類のOSやCPUアーキテクチャによるCIジョブが動きます。

これら全てが通らない場合は何が原因かCIの結果を見て解決させましょう。
また、破壊的変更とみなされる修正の場合、代表的なnpmパッケージで正常動作するかテストが行われます。それによりnpmのエコシステムに影響が無いことを担保しようとしています。
例えばreactやeslintなど100種類以上のパッケージでテストが行われます。
それがCITGMです。
CITGMでどのパッケージをテストしているかは citgm/lookup.json をご確認ください。
Landed 🎉
コラボレーターが承認してCIが通ればauthor readyというラベルが貼られます。このラベルが貼られたあと48時間の間に他のコラボレーターから反対意見などが出なければコラボレーターがmasterにマージしてくれます。

これで初めてのNode.jsへのコミットが完了です🎉🎉🎉
英語について
ここまで触れてきていませんでしたが、OSSの世界ではコミュニケーションはすべて英語で行われます。
ただ、Google翻訳を使って読み書きすれば全く問題なくコミュニケーションはとれるので気負わずにコミュニケーションをとってほしいと思います。
Node.js コア以外へのコントリビュート
Node.js コア以外にもNode.jsへのコントリビュート方法はいっぱいあります。
例えば、ブログや勉強会で発信することもコントリビュートの一つだと思いますし、ドキュメントの翻訳をしたりOSSのコントリビュートのサポートをするのも立派なコントリビュートだと思います。
発信したり行動することで批判があるかもしれませんが、もっと良いこともたくさんあるので気負わずに行っていただけたら良いなと個人的には考えています。
はじめてのOSSへの貢献
ここからは私個人の話になります。技術的な話は出てきません。
この章は私がOSSへ貢献をしたことによる変化や影響に関する話です。
Node.jsにコミットする前からOSSへのコントリビュートの経験はありました。
はじめてOSSに貢献したのは、Key-ValueストレージのLevelDBをNode.jsで使うことができるようにするlevelupのハンズオンlevelmeupの翻訳でした。
このlevelmeupはNodeSchoolのworkshopの一つです。
翻訳のOSSへの立派なコントリビュート方法の一つです。
この経験は @leichtgewicht と @kamiyam が行っていたNodeSchool Osaka のイベント内で教えてもらいながら始めたのがきっかけでした。
そのあと、彼らの支援で関西Node学園というコミュニティを立ち上げることができ、東京Node学園祭やJSConf JPのカンファレンススタッフを経験することができました。
OSSへの貢献やコミュニティへの参加が人生に大きく影響しました。
同じようにコミュニティの輪を広げたりその人の助けになれれば良いと思うので、Node.jsや他のOSSへのコントリビュートについて質問などは可能な限り答えたいと思っています。Twitter - @shisama_宛やこのブログへのコメントなどで気兼ねなく質問してください。
また、jsconfjpのslackには日本のNode.jsの一線で活躍されている人がいるのでそこで質問するのもいいでしょう。私も相談していました。
OSSに貢献するということ
OSSに貢献するということで人との関わりが生まれます。
それは、インターネット上だけかもしれません。しかし、OSSに携わるということはまだ会ったことない人とのコミュニケーションが発生します。
そこからもしかすると新しい良い出会いがあるかもしれません。
また、同じようにOSSに貢献している人同士がインターネット上や勉強会などで偶然出会って繋がりあうこともあるかもしれません。
私自身、Node.jsにコントリビュートしなければ出会えなかった人もいたと感じます。
特にNodeSchool Osakaのメンバーや関西でのコミュニティで出会った人たちや、海外の偉大なエンジニア、JSConf JPのメンバーとの出会いは人生におけるかけがえのない財産だと感じています。
OSS貢献を通じて読者の方の人との繋がりが生まれたり人生が良い方向に向くことを願っています。この記事がその一助になれば幸いです。
長い記事でしたが、最後までお読みいただきありがとうございました。不備や質問はTwitter - @shisama_やコメント欄でお願いします。
