こんにちは。マーケティングテクノロジー室のわきさかです。

先日python/cpython(CPython : C言語で記述されたPythonの標準実装)へのPull Request(以下PR)がMergeされました。 普通のOSSとは異なり、PRに関する管理体制やプロセスの自動化がしっかりしていて面白かったので、Issueの作成からMergeまでの流れを紹介します。

背景/経緯

CPythonを読む会を、以前所属していたAI室のメンバーと毎週1時間行っています。目的は、普段自分たちが使っている言語がどのように実行されているのかを知ること。

その中で、タイポを発見したので、若者の経験値として、PRチャレンジをいただきました。
今回出したPRはこちら

OSSにPRを投げること自体が初体験だったので、大先輩方にご助言を頂戴しながら、無事にマージされるに至りました。
記念スクショと記念Tweetを晒させていただきます。

Merged

PRの投げ方

以下にPRを投げる手順を説明していきますが、基本的にPythonの開発者ガイドに従っていくだけです。
英語が読めて、OSSへのPRに恐れがない人は、そちらを読めば事足りるかもしれません。

Here is a quick overview of how you can contribute to CPython:

  1. Create an issue that describes your change [*]
  2. Create a new branch in Git
  3. Work on changes (e.g. fix a bug or add a new feature)
  4. Run tests and make patchcheck
  5. Commit and push changes to your GitHub fork
  6. Create Pull Request on GitHub to merge a branch from your fork
  7. Review and address comments on your Pull Request
  8. When your changes are merged, you can delete the PR branch
  9. Celebrate contributing to CPython! :)

[*] If an issue is trivial (e.g. typo fixes), or if an issue already exists, you can skip this step.

1. Issueの作成

1.1. Issue Trackerへ登録

さて、さっそくですが、PRを投げる下準備として、Issue Trackerに登録をしましょう。
“bpo"と称されますが、放送倫理・番組向上機構とは一切関係なく、 bugs.python.org の略です。
たまにめっちゃ重いですが、諦めずにアクセスしてください。笑

左のサイドバーにある「User > Register」から登録をします。GitHubアカウントを入力する欄があるので、PRを投げる用のアカウントを指定します。僕は業務用とプライベート用でアカウントを分けているうちの、プライベート用を登録しました。

1.2. Contributionに関する同意書の提出

Python Software Foundation(PSF)へのContributionについて、詳細はこちら
PSFに対して、Apache Licenseへの同意書を提出します。
(Academic Free Licenseでもよいようですが、リンク切れで詳細がわからないのでApacheで…)

You can also submit the agreement by postal mail, fax, or by email.

とあるので、手紙とか送ったらちょっと面白そう、と思いながら、こちらのオンラインフォームから提出しました。

フォームに記載する内容は下記。

フォーム入力が完了すると、一度 Adobe Sign <echosign@echosign.com> から Please confirm your signature on Python Contributor Agreement Form というタイトルのメールが届きます。
メール内のConfirm my email addressというリンクをクリックした段階で、同意書の提出とみなされます。

無事に同意書が受理されると、Issue Trackerのユーザページで、プロフィールの Contributor Form ReceivedYes on: yyyy-MM-dd.HH:mm:ss になります。

1.3. Issue TrackerにIssueを登録

同意書の受理が確認できたら、いよいよ、Issueの登録です。サイドバーの「Issues > Create New」から、Issue内容を記載します。今回は、下記のように記入しました。

Title Typo in Python/import.c
Type - no selection -
Components Interpreter Core
Versions Python 3.8

登録が済むと、Issue IDが付与されます。IDは、Issueページの上部にissue{IssueId}のように記載されています。
また、URLが https://bugs.python.org/issue{IssueId} のようになっているので、そちらで確認してもいいでしょう。

2. 修正!

2.1. リポジトリをフォークする

https://github.com/python/cpython の右上の「Fork」をポチッと押して、1.1. で登録したGitHubアカウントのリポジトリとしてフォークします。

すると、{github_account}/cpython というリポジトリが生成されるので、
$ git clone git@github.com:{github_account}/cpython.git
などで、ローカルにリポジトリを引っ張ってきます。

2.2. コードを修正する

ブランチを切って修正
$ git checkout -b {new_branch_name} master
で、修正用のブランチを作成します。ブランチ名は、ドキュメントではfix-issue-{IssueId}となっていますが、bpo-{IssueId}としているものや、簡単なIssue内容にしているものもあったので、強い制限はないようです。

修正用のブランチでコードを修正します。今回はTypo、それもメソッド内のローカル変数だったため、Find & Replaceしただけです。笑

コミット
コミットについても強い制限は無いようですが、もし普段複数のGitHubアカウントで作業する場合があれば、コミットするGitHubアカウントが、1.1.で登録したものになるようにしましょう。僕はこれで後でハマりました…。(後述)
コミットコメントは、3.1.で後述するPRタイトルに合わせる形が一般的なようです。

bpo-{IssueId}: What I fixed

News Entry
News Entryとは、変更内容を記載したrst形式のドキュメントで、Misc/NEWS.d/next/Libraryに格納されています。 下記のドキュメントに従って、News Entryも追加します。PRを眺めていると、skip news(News Entry不要)というタグがついているものもあるので、微細な修正には不要のようです。
https://devguide.python.org/committing/#what-s-new-and-news-entries

2.3. テスト

ドキュメントに従い、下記の手順でテストを走らせます。(OSによって若干異なります。下記はOS X向けです)
途中めっちゃ重くてPCがサーッとなるかもしれませんが、堪えましょう。

$ ./configure --with-pydebug && make -j
$ ./python.exe -m test -j3

3. プルをリクエストする

3.1. ルールに従ってPRを投げる

PRの作成
https://github.com/{github_account}/cpython の左上の「New pull request」をポチッと押すと、PR作成画面になります。PRにおけるbaseとheadをきちんと確認しましょう。

base fork python/cpython
base master
head fork {github_account}/cpython
compare {new_branch_name}

タイトル
PRのタイトルは下記のようにします。
bpo-{IssueId}: What I fixed

※ 2.2.のブランチ名やコミットコメントと異なり、ここはきちんとルールに従わないといけません ※
Prefixのbpo-{IssueId}: の部分を自動で読み込んで、Issue Trackerの該当IssueにPRを紐付ける仕組みになっています。正しく読み込まれれば、1.3.で作成したIssueのページの「Pull Requests」に、PRの情報が反映されます。(しゅごい…!)

CLA(Contributor License Agreement)

the-knights-who-say-ni というbotが走っています。この子は、Contributionの同意を確認しています。
1.2.で同意書が正しく受理されていれば、PRにCLA signedのラベルが、受理されていなければ、CLA not signedのラベルが自動で付与されます。(しゅごい…!!)

CI
その他、ドキュメントの文法チェックを含むCIがいくつか走るので、パスしていないものがあればコメントを確認しながら修正します。
後述しますが、僕はNews Entryの文法チェックでTravisおじさんに怒られました。(しゅごい…!!!)

Labels
自動で付与されたラベルたち

3.2. コメントに対応する

とはいえ今回はTypoの修正だったため、コードに関してはコメントはありませんでした。
唯一のコメントは、「News Entry要らないよ」でした。(勝手にファイル削除してくれた)

3.3. マージを待つ

土日を挟んで4日後にマージされました。それまでは我慢して待ちましょう!
OSS初コミットだったので、粛々と待つことしかできませんでしたが、マージされた時の喜びは、Typoとはいえヒトシオでした。

感想

自滅しなければ沼は少ない

今回はまった沼は、3点。

1. 同意書が受理されない

結局原因はよくわからなかったですが、再度同意書を送って解決。
2、3営業日待っても、Issue TrackerのContributor Form ReceivedNoのまま、あるいはPRのCLA not signedCLA signedに変わらない場合は、もう一回送り直してみる、が吉かもしれません。
ドキュメントに書いてある contributors@python.org に問い合わせしたところ、こちらも数日中に返信が来たので、再トライしてもダメな場合は問い合わせをするのも手でしょう。

2. News Entry

そもそも今回は不要ということで、ハマる必要すらない沼だったわけですが、3.1.に記載したCIで、News Entryの文法がおかしいと怒られまくっていました。
原因としては、rstファイル内に、ポインタ変数を表す*を使用していたためでした。\*のようにエスケープするだけの話だったのですが、rstの記法を把握しておらず…。Markdownと同じで、*は強調記号として用いられるようです。rst記法についてはこちら

3. GitHubアカウント

私は業務用アカウントとプライベートのアカウントを分けているのですが、それが裏目となり、一度CommitterとAuthorが別のアカウントになっていました。3.1.に記載したラベルがCLA signedになるためには、CommitterとAuthorの両方の同意が必要だったようで、Committerの履歴をいじるという地味な知見をゲットして修正をしました。

なんだかいけそうな気がする

OSSへのContributionは、普段のコーディングやインフラ構築とは別の、でもエンジニアとして知識や経験として持っていて損は無い類のものだと思います。アドバイスをいただきながらでしたが、無事完遂したので、おおよそ一連の流れがわかったのは大きいです。
そして、OSSにPR投げてマージされたってだけで「うおお、エンジニアだ…!!!」って感じなのに、「python/cpythonにPR投げてマージされた」って響きがかっこいい。えも言われぬ自信のようなものが沸いてくる。

まとめ

臆せずにコード/ドキュメントを読もう

まずOSSにPRを投げるには、OSSのコードを読まないことには始まりません。今回のように頭から順に読む機会はなかなかないかもしれませんが、自分が利用するフレームワークの理解のために、使用している部分からコードを遡ってみるとよいでしょう。
また、OSSへのPRの投げ方、規則なども、ドキュメントに書いてあったりするので、公式のドキュメントを頑張って読むことも大事です。ドキュメントがあまりないOSSの場合は、他のPRを眺めてみると傾向が読めるでしょう。

やろう!

社会人からエンジニアを始めて、ちょうど丸2年で初OSSコミットでした。経験や年齢に関係なく、やるぞという気持ちで走り出すことが肝心だな、と思いました。やればなんとかなる!皆さんも Let’s Contribute!

(コミットネタがなくてもPSFへのDonationでの貢献もできますよ!)

Yuki Wakisaka (ukwksk)
Yuki Wakisaka (ukwksk)

2016年新卒エンジニア。AI室→マーケティングテクノロジー室。AI室ではChatbot開発を行う。現在はデータ分析基盤の構築に従事。